+ switch (_projection) {
+ case PROJECTION_SAMSON_FLAMSTEED:
+ {
+ // Sanson-Flamsteed projection, relative to the projection center
+ double lonDiff = geod.getLongitudeRad() - _projectionCenter.getLongitudeRad(),
+ latDiff = geod.getLatitudeRad() - _projectionCenter.getLatitudeRad();
+
+ p = SGVec2d(cos(geod.getLatitudeRad()) * lonDiff, latDiff) * r * currentScale();
+ break;
+ }
+
+ case PROJECTION_AZIMUTHAL_EQUIDISTANT:
+ {
+ // Azimuthal Equidistant projection, relative to the projection center
+ // http://www.globmaritime.com/martech/marine-navigation/general-concepts/626-azimuthal-equidistant-projection
+ double ref_lat = _projectionCenter.getLatitudeRad(),
+ ref_lon = _projectionCenter.getLongitudeRad(),
+ lat = geod.getLatitudeRad(),
+ lon = geod.getLongitudeRad(),
+ lonDiff = lon - ref_lon;
+
+ double c = acos( sin(ref_lat) * sin(lat) + cos(ref_lat) * cos(lat) * cos(lonDiff) );
+ if (c == 0.0){
+ // angular distance from center is 0
+ p= SGVec2d(0.0, 0.0);
+ break;
+ }
+
+ double k = c / sin(c);
+ double x, y;
+ if (ref_lat == (90 * SG_DEGREES_TO_RADIANS))
+ {
+ x = (SGD_PI / 2 - lat) * sin(lonDiff);
+ y = -(SGD_PI / 2 - lat) * cos(lonDiff);
+ }
+ else if (ref_lat == -(90 * SG_DEGREES_TO_RADIANS))
+ {
+ x = (SGD_PI / 2 + lat) * sin(lonDiff);
+ y = (SGD_PI / 2 + lat) * cos(lonDiff);
+ }
+ else
+ {
+ x = k * cos(lat) * sin(lonDiff);
+ y = k * ( cos(ref_lat) * sin(lat) - sin(ref_lat) * cos(lat) * cos(lonDiff) );
+ }
+ p = SGVec2d(x, y) * r * currentScale();
+
+ break;
+ }
+
+ case PROJECTION_ORTHO_AZIMUTH:
+ {
+ // http://mathworld.wolfram.com/OrthographicProjection.html
+ double cosTheta = cos(geod.getLatitudeRad());
+ double sinDLambda = sin(geod.getLongitudeRad() - _projectionCenter.getLongitudeRad());
+ double cosDLambda = cos(geod.getLongitudeRad() - _projectionCenter.getLongitudeRad());
+ double sinTheta1 = sin(_projectionCenter.getLatitudeRad());
+ double sinTheta = sin(geod.getLatitudeRad());
+ double cosTheta1 = cos(_projectionCenter.getLatitudeRad());
+
+ p = SGVec2d(cosTheta * sinDLambda,
+ (cosTheta1 * sinTheta) - (sinTheta1 * cosTheta * cosDLambda)) * r * currentScale();
+ break;
+ }
+
+ case PROJECTION_SPHERICAL:
+ {
+ SGVec3d cartCenter = SGVec3d::fromGeod(_projectionCenter);
+ SGVec3d cartPt = SGVec3d::fromGeod(geod) - cartCenter;
+
+ // rotate relative to projection center
+ SGQuatd orient = SGQuatd::fromLonLat(_projectionCenter);
+ cartPt = orient.rotateBack(cartPt);
+ return SGVec2d(cartPt.y(), cartPt.x()) * currentScale();
+ break;
+ }
+ } // of projection mode switch
+