116 using namespace MSP::CCS;
124 const double PI = 3.14159265358979323e0;
137 ObliqueMercator::ObliqueMercator(
double ellipsoidSemiMajorAxis,
double ellipsoidFlattening,
double originLatitude,
double longitude1,
double latitude1,
double longitude2,
double latitude2,
double falseEasting,
double falseNorthing,
double scaleFactor ) :
139 es( 0.08181919084262188000 ),
140 es_OVER_2( .040909595421311 ),
141 OMerc_A( 6383471.9177251 ),
142 OMerc_B( 1.0008420825413 ),
143 OMerc_E( 1.0028158089754 ),
144 OMerc_gamma( .41705894983580 ),
145 OMerc_azimuth( .60940407333533 ),
146 OMerc_Origin_Long( -.46732023406900 ),
147 cos_gamma( .91428423352628 ),
148 sin_gamma( .40507325303611 ),
149 sin_azimuth( .57237890829911 ),
150 cos_azimuth( .81998925927985 ),
151 A_over_B( 6378101.0302010 ),
152 B_over_A( 1.5678647849335e-7 ),
153 OMerc_u( 5632885.2272051 ),
154 OMerc_Origin_Lat( ((45.0 *
PI) / 180.0) ),
155 OMerc_Lon_1( ((-5.0 *
PI) / 180.0) ),
156 OMerc_Lat_1( ((40.0 *
PI) / 180.0) ),
157 OMerc_Lon_2( ((5.0 *
PI) / 180.0) ),
158 OMerc_Lat_2( ((50.0 *
PI) / 180.0) ),
159 OMerc_False_Easting( 0.0 ),
160 OMerc_False_Northing( 0.0 ),
161 OMerc_Scale_Factor( 1.0 ),
162 OMerc_Delta_Northing( 40000000.0 ),
163 OMerc_Delta_Easting( 40000000.0 )
192 double inv_f = 1 / ellipsoidFlattening;
193 double es2, one_MINUS_es2;
194 double cos_olat, cos_olat2;
195 double sin_olat, sin_olat2, es2_sin_olat2;
197 double D, D2, D2_MINUS_1, sqrt_D2_MINUS_1;
203 if (ellipsoidSemiMajorAxis <= 0.0)
207 if ((inv_f < 250) || (inv_f > 350))
223 if (latitude1 == 0.0)
227 if (latitude1 == latitude2)
231 if (((latitude1 < 0.0) && (latitude2 > 0.0)) ||
232 ((latitude1 > 0.0) && (latitude2 < 0.0)))
236 if ((longitude1 < -
PI) || (longitude1 >
TWO_PI))
240 if ((longitude2 < -
PI) || (longitude2 >
TWO_PI))
252 OMerc_Origin_Lat = originLatitude;
253 OMerc_Lon_1 = longitude1;
254 OMerc_Lat_1 = latitude1;
255 OMerc_Lon_2 = longitude2;
256 OMerc_Lat_2 = latitude2;
257 OMerc_False_Northing = falseNorthing;
258 OMerc_False_Easting = falseEasting;
259 OMerc_Scale_Factor = scaleFactor;
263 one_MINUS_es2 = 1 - es2;
264 es_OVER_2 = es / 2.0;
266 cos_olat = cos(OMerc_Origin_Lat);
267 cos_olat2 = cos_olat * cos_olat;
268 sin_olat = sin(OMerc_Origin_Lat);
269 sin_olat2 = sin_olat * sin_olat;
270 es2_sin_olat2 = es2 * sin_olat2;
272 OMerc_B = sqrt(1 + (es2 * cos_olat2 * cos_olat2) / one_MINUS_es2);
273 OMerc_A = (
semiMajorAxis * OMerc_B * OMerc_Scale_Factor * sqrt(one_MINUS_es2)) / (1.0 - es2_sin_olat2);
274 A_over_B = OMerc_A / OMerc_B;
275 B_over_A = OMerc_B / OMerc_A;
277 t0 = omercT(OMerc_Origin_Lat, es * sin_olat, es_OVER_2);
278 t1 = omercT(OMerc_Lat_1, es * sin(OMerc_Lat_1), es_OVER_2);
279 t2 = omercT(OMerc_Lat_2, es * sin(OMerc_Lat_2), es_OVER_2);
281 D = (OMerc_B * sqrt(one_MINUS_es2)) / (cos_olat * sqrt(1.0 - es2_sin_olat2));
285 D2_MINUS_1 = D2 - 1.0;
286 sqrt_D2_MINUS_1 = sqrt(D2_MINUS_1);
287 if (D2_MINUS_1 > 1.0e-10)
289 if (OMerc_Origin_Lat >= 0.0)
290 OMerc_E = (D + sqrt_D2_MINUS_1) * pow(t0, OMerc_B);
292 OMerc_E = (D - sqrt_D2_MINUS_1) * pow(t0, OMerc_B);
295 OMerc_E = D * pow(t0, OMerc_B);
296 H = pow(t1, OMerc_B);
297 L = pow(t2, OMerc_B);
299 G = (F - 1.0 / F) / 2.0;
300 E2 = OMerc_E * OMerc_E;
302 J = (E2 - LH) / (E2 + LH);
303 P = (L - H) / (L + H);
305 dlon = OMerc_Lon_1 - OMerc_Lon_2;
310 dlon = OMerc_Lon_1 - OMerc_Lon_2;
311 OMerc_Origin_Long = (OMerc_Lon_1 + OMerc_Lon_2) / 2.0 - (atan(J * tan(OMerc_B * dlon / 2.0) / P)) / OMerc_B;
313 dlon = OMerc_Lon_1 - OMerc_Origin_Long;
315 OMerc_Origin_Long -=
TWO_PI;
317 OMerc_Origin_Long +=
TWO_PI;
319 dlon = OMerc_Lon_1 - OMerc_Origin_Long;
320 OMerc_gamma = atan(sin(OMerc_B * dlon) / G);
321 cos_gamma = cos(OMerc_gamma);
322 sin_gamma = sin(OMerc_gamma);
324 OMerc_azimuth = asin(D * sin_gamma);
325 cos_azimuth = cos(OMerc_azimuth);
326 sin_azimuth = sin(OMerc_azimuth);
328 if (OMerc_Origin_Lat >= 0)
329 OMerc_u = A_over_B * atan(sqrt_D2_MINUS_1/cos_azimuth);
331 OMerc_u = -A_over_B * atan(sqrt_D2_MINUS_1/cos_azimuth);
340 es_OVER_2 = om.es_OVER_2;
341 OMerc_A = om.OMerc_A;
342 OMerc_B = om.OMerc_B;
343 OMerc_E = om.OMerc_E;
344 OMerc_gamma = om.OMerc_gamma;
345 OMerc_azimuth = om.OMerc_azimuth;
346 OMerc_Origin_Long = om.OMerc_Origin_Long;
347 cos_gamma = om.cos_gamma;
348 sin_gamma = om.sin_gamma;
349 sin_azimuth = om.sin_azimuth;
350 cos_azimuth = om.cos_azimuth;
351 A_over_B = om.A_over_B;
352 B_over_A = om.B_over_A;
353 OMerc_u = om.OMerc_u;
354 OMerc_Origin_Lat = om.OMerc_Origin_Lat;
355 OMerc_Lon_1 = om.OMerc_Lon_1;
356 OMerc_Lat_1 = om.OMerc_Lat_1;
357 OMerc_Lon_2 = om.OMerc_Lon_2;
358 OMerc_Lat_2 = om.OMerc_Lat_2;
359 OMerc_False_Easting = om.OMerc_False_Easting;
360 OMerc_False_Northing = om.OMerc_False_Northing;
361 OMerc_Scale_Factor = om.OMerc_Scale_Factor;
362 OMerc_Delta_Northing = om.OMerc_Delta_Northing;
363 OMerc_Delta_Easting = om.OMerc_Delta_Easting;
379 es_OVER_2 = om.es_OVER_2;
380 OMerc_A = om.OMerc_A;
381 OMerc_B = om.OMerc_B;
382 OMerc_E = om.OMerc_E;
383 OMerc_gamma = om.OMerc_gamma;
384 OMerc_azimuth = om.OMerc_azimuth;
385 OMerc_Origin_Long = om.OMerc_Origin_Long;
386 cos_gamma = om.cos_gamma;
387 sin_gamma = om.sin_gamma;
388 sin_azimuth = om.sin_azimuth;
389 cos_azimuth = om.cos_azimuth;
390 A_over_B = om.A_over_B;
391 B_over_A = om.B_over_A;
392 OMerc_u = om.OMerc_u;
393 OMerc_Origin_Lat = om.OMerc_Origin_Lat;
394 OMerc_Lon_1 = om.OMerc_Lon_1;
395 OMerc_Lat_1 = om.OMerc_Lat_1;
396 OMerc_Lon_2 = om.OMerc_Lon_2;
397 OMerc_Lat_2 = om.OMerc_Lat_2;
398 OMerc_False_Easting = om.OMerc_False_Easting;
399 OMerc_False_Northing = om.OMerc_False_Northing;
400 OMerc_Scale_Factor = om.OMerc_Scale_Factor;
401 OMerc_Delta_Northing = om.OMerc_Delta_Northing;
402 OMerc_Delta_Easting = om.OMerc_Delta_Easting;
455 double dlam, B_dlam, cos_B_dlam;
456 double t, S, T, V, U;
463 double longitude = geodeticCoordinates->
longitude();
464 double latitude = geodeticCoordinates->
latitude();
470 if ((longitude < -
PI) || (longitude >
TWO_PI))
475 dlam = longitude - OMerc_Origin_Long;
493 if (fabs(fabs(latitude) -
PI_OVER_2) > 1.0e-10)
495 t = omercT(latitude, es * sin(latitude), es_OVER_2);
496 Q = OMerc_E / pow(t, OMerc_B);
498 S = (Q - Q_inv) / 2.0;
499 T = (Q + Q_inv) / 2.0;
500 B_dlam = OMerc_B * dlam;
502 U = ((-1.0 * V * cos_gamma) + (S * sin_gamma)) / T;
503 if (fabs(fabs(U) - 1.0) < 1.0e-10)
509 v = A_over_B * log((1.0 - U) / (1.0 + U)) / 2.0;
510 cos_B_dlam = cos(B_dlam);
511 if (fabs(cos_B_dlam) < 1.0e-10)
512 u = OMerc_A * B_dlam;
516 double temp = atan(((S * cos_gamma) + (V * sin_gamma)) / cos_B_dlam);
518 u = A_over_B * (temp +
PI);
520 u = A_over_B * (temp -
PI);
523 u = A_over_B * atan(((S * cos_gamma) + (V * sin_gamma)) / cos_B_dlam);
529 v = A_over_B * log(tan(
PI_OVER_4 - (OMerc_gamma / 2.0)));
531 v = A_over_B * log(tan(
PI_OVER_4 + (OMerc_gamma / 2.0)));
532 u = A_over_B * latitude;
538 double easting = OMerc_False_Easting + v * cos_azimuth + u * sin_azimuth;
539 double northing = OMerc_False_Northing + u * cos_azimuth - v * sin_azimuth;
565 double Q_prime, Q_prime_inv;
566 double S_prime, T_prime, V_prime, U_prime;
571 double temp_phi = 0.0;
573 double longitude, latitude;
575 double easting = mapProjectionCoordinates->
easting();
576 double northing = mapProjectionCoordinates->
northing();
578 if ((easting < (OMerc_False_Easting - OMerc_Delta_Easting))
579 || (easting > (OMerc_False_Easting + OMerc_Delta_Easting)))
583 if ((northing < (OMerc_False_Northing - OMerc_Delta_Northing))
584 || (northing > (OMerc_False_Northing + OMerc_Delta_Northing)))
589 dy = northing - OMerc_False_Northing;
590 dx = easting - OMerc_False_Easting;
591 v = dx * cos_azimuth - dy * sin_azimuth;
592 u = dy * cos_azimuth + dx * sin_azimuth;
594 Q_prime = exp(-1.0 * (v * B_over_A ));
595 Q_prime_inv = 1.0 / Q_prime;
596 S_prime = (Q_prime - Q_prime_inv) / 2.0;
597 T_prime = (Q_prime + Q_prime_inv) / 2.0;
598 u_B_over_A = u * B_over_A;
599 V_prime = sin(u_B_over_A);
600 U_prime = (V_prime * cos_gamma + S_prime * sin_gamma) / T_prime;
601 if (fabs(fabs(U_prime) - 1.0) < 1.0e-10)
607 longitude = OMerc_Origin_Long;
611 t = pow(OMerc_E / sqrt((1.0 + U_prime) / (1.0 - U_prime)), 1.0 / OMerc_B);
613 while (fabs(phi - temp_phi) > 1.0e-10 && count)
616 es_sin = es * sin(phi);
617 phi =
PI_OVER_2 - 2.0 * atan(t * pow((1.0 - es_sin) / (1.0 + es_sin), es_OVER_2));
625 longitude = OMerc_Origin_Long - atan2((S_prime * cos_gamma - V_prime * sin_gamma), cos(u_B_over_A)) / OMerc_B;
628 if (fabs(latitude) < 2.0e-7)
640 if (fabs(longitude) < 2.0e-7)
644 else if (longitude < -
PI)
649 if (fabs(longitude - OMerc_Origin_Long) >=
PI_OVER_2)
659 double ObliqueMercator::omercT(
double lat,
double e_sinlat,
double e_over_2 )
661 return (tan(
PI_OVER_4 - lat / 2.0)) / (pow((1 - e_sinlat) / (1 + e_sinlat), e_over_2));