There is no possibility to get canvas coordinates of some geographic location - oposite procedure to picking of some location by canvas coordinates.
This functionality is required when somebody requires to move some HTML UI elements according to Position on globe determining its pixel coordinates.
Android version has this functionality. So I propose to port it on JS in the following way...
/**
* Projects a Cartesian point to screen coordinates. This method assumes this matrix represents an inverse
* modelview-projection matrix. The result of this method is undefined if this matrix is not an inverse
* modelview-projection matrix.
* <p/>
* The resultant screen point is in OpenGL screen coordinates, with the origin in the bottom-left corner and axes
* that extend up and to the right from the origin.
* <p/>
* This stores the projected point in the result argument, and returns a boolean value indicating whether or not the
* projection is successful. This returns false if the Cartesian point is clipped by the near clipping plane or the
* far clipping plane.
*
* @param {Number} x the Cartesian point's X component
* @param {Number} y the Cartesian point's y component
* @param {Number} z the Cartesian point's z component
* @param {Rectangle} viewport the viewport defining the screen point's coordinate system
* @param {Vec3} result a pre-allocated {@link Vec3} in which to return the projected point
*
* @return {boolean} true if the transformation is successful, otherwise false
*
* @throws {ArgumentError} If any argument is null
*/
Matrix.prototype.project = function (x, y, z, viewport, result) {
if (!viewport) {
throw new ArgumentError(Logger.logMessage(Logger.ERROR, "Matrix", "project",
"missingViewport"));
}
if (!result) {
throw new ArgumentError(Logger.logMessage(Logger.ERROR, "Matrix", "project",
"missingResult"));
}
// Transform the model point from model coordinates to eye coordinates then to clip coordinates. This inverts
// the Z axis and stores the negative of the eye coordinate Z value in the W coordinate.
var sx = this[0] * x + this[1] * y + this[2] * z + this[3];
var sy = this[4] * x + this[5] * y + this[6] * z + this[7];
var sz = this[8] * x + this[9] * y + this[10] * z + this[11];
var sw = this[12] * x + this[13] * y + this[14] * z + this[15];
if (sw === 0) {
return false;
}
// Complete the conversion from model coordinates to clip coordinates by dividing by W. The resultant X, Y
// and Z coordinates are in the range [-1,1].
sx /= sw;
sy /= sw;
sz /= sw;
// Clip the point against the near and far clip planes.
if (sz < -1 || sz > 1) {
return false;
}
// Convert the point from clip coordinate to the range [0,1]. This enables the X and Y coordinates to be
// converted to screen coordinates, and the Z coordinate to represent a depth value in the range[0,1].
sx = sx * 0.5 + 0.5;
sy = sy * 0.5 + 0.5;
sz = sz * 0.5 + 0.5;
// Convert the X and Y coordinates from the range [0,1] to screen coordinates.
sx = sx * viewport.width + viewport.x;
sy = sy * viewport.height + viewport.y;
result[0] = sx;
result[1] = sy;
result[2] = sz;
return true;
};
// Internal. Intentionally not documented.
this.scratchPoint = new Vec3(0, 0, 0);
/**
* Transforms a Cartesian coordinate point to coordinates relative to this WorldWindow's canvas.
* <p/>
* This stores the converted point in the result argument, and returns a boolean value indicating whether or not the
* converted is successful. This returns false if the Cartesian point is clipped by either the WorldWindow's near
* clipping plane or far clipping plane.
*
* @param {Number} x the Cartesian point's x component in meters
* @param {Number} y the Cartesian point's y component in meters
* @param {Number} z the Cartesian point's z component in meters
* @param {Vec2} result a pre-allocated {@link Vec2} in which to return the screen point
*
* @return {boolean} true if the transformation is successful, otherwise false
*
* @throws {ArgumentError} If the result is null
*/
WorldWindow.prototype.cartesianToScreenPoint = function (x, y, z, result) {
if (!result) {
throw new ArgumentError(Logger.logMessage(Logger.ERROR, "WorldWindow", "cartesianToScreenPoint",
"missingResult"));
}
// Compute the WorldWindow's modelview-projection matrix.
this.computeViewingTransform(this.scratchProjection, this.scratchModelview);
this.scratchProjection.multiplyMatrix(this.scratchModelview);
// Transform the Cartesian point to OpenGL screen coordinates. Complete the transformation by converting to
// Android screen coordinates and discarding the screen Z component.
if (this.scratchProjection.project(x, y, z, this.viewport, this.scratchPoint)) {
result[0] = this.scratchPoint[0];
result[1] = this.viewport.height - this.scratchPoint[1];
return true;
}
return false;
};
/**
* Transforms a geographic position to coordinates relative to this WorldWindow's canvas.
* <p/>
* This stores the converted point in the result argument, and returns a boolean value indicating whether or not the
* converted is successful. This returns false if the Cartesian point is clipped by either of the WorldWindow's
* near clipping plane or far clipping plane.
*
* @param {Number} latitude the position's latitude in degrees
* @param {Number} longitude the position's longitude in degrees
* @param {Number} altitude the position's altitude in meters
* @param {Vec2} result a pre-allocated {@link Vec2} in which to return the screen point
*
* @return {boolean} true if the transformation is successful, otherwise false
*
* @throws {ArgumentError} If the result is null
*/
WorldWindow.prototype.geographicToScreenPoint = function (latitude, longitude, altitude, result) {
if (!result) {
throw new ArgumentError(Logger.logMessage(Logger.ERROR, "WorldWindow", "geographicToScreenPoint",
"missingResult"));
}
// Convert the position from geographic coordinates to Cartesian coordinates.
this.globe.computePointFromPosition(latitude, longitude, altitude, this.scratchPoint);
// Convert the position from Cartesian coordinates to screen coordinates.
return this.cartesianToScreenPoint(this.scratchPoint[0], this.scratchPoint[1], this.scratchPoint[2], result);
};