/// New functions void DistanceBearingMercator(double lat0, double lon0, double lat1, double lon1, double *dist, double *brg) { // Calculate bearing by conversion to SM (Mercator) coordinates, then simple trigonometry double lon0x = lon0; double lon1x = lon1; // Make lon points the same phase if ((lon0x * lon1x) < 0.) { lon0x < 0.0 ? lon0x += 360.0 : lon1x += 360.0; // Choose the shortest distance if (fabs(lon0x - lon1x) > 180.) { lon0x > lon1x ? lon0x -= 360.0 : lon1x -= 360.0; } // Make always positive lon1x += 360.; lon0x += 360.; } // Classic formula, which fails for due east/west courses.... if (dist) { // In the case of exactly east or west courses // we must make an adjustment if we want true Mercator distances // This idea comes from Thomas(Cagney) // We simply require the dlat to be (slightly) non-zero, and carry on. // MAS022210 for HamishB from 1e-4 && .001 to 1e-9 for better precision // on small latitude diffs const double mlat0 = fabs(lat1 - lat0) < 1e-9 ? lat0 + 1e-9 : lat0; double east, north; toSM_ECC(lat1, lon1x, mlat0, lon0x, &east, &north); const double C = atan2(east, north); if (cos(C)) { const double dlat = (lat1 - mlat0) * 60.; // in minutes *dist = (dlat / cos(C)); } else { *dist = DistGreatCircle(lat0, lon0, lat1, lon1); } } // Calculate the bearing using the un-adjusted original latitudes and Mercator Sailing if (brg) { double east, north; toSM_ECC(lat1, lon1x, lat0, lon0x, &east, &north); const double C = atan2(east, north); const double brgt = 180. + (C * 180. / PI); if (brgt < 0) *brg = brgt + 360.; else if (brgt >= 360.) *brg = brgt - 360.; else *brg = brgt; } }
void DistanceBearingMercator(double lat0, double lon0, double lat1, double lon1, double *brg, double *dist) { double east, north, brgt, C; double lon0x, lon1x, dlat; double mlat0; // Calculate bearing by conversion to SM (Mercator) coordinates, then simple trigonometry lon0x = lon0; lon1x = lon1; // Make lon points the same phase if((lon0x * lon1x) < 0.) { if(lon0x < 0.) lon0x += 360.; else lon1x += 360.; // Choose the shortest distance if(fabs(lon0x - lon1x) > 180.) { if(lon0x > lon1x) lon0x -= 360.; else lon1x -= 360.; } // Make always positive lon1x += 360.; lon0x += 360.; } // In the case of exactly east or west courses // we must make an adjustment if we want true Mercator distances // This idea comes from Thomas(Cagney) // We simply require the dlat to be (slightly) non-zero, and carry on. // MAS022210 for HamishB from 1e-4 && .001 to 1e-9 for better precision // on small latitude diffs mlat0 = lat0; if(fabs(lat1 - lat0) < 1e-9) mlat0 += 1e-9; toSM_ECC(lat1, lon1x, mlat0, lon0x, &east, &north); C = atan2(east, north); dlat = (lat1 - mlat0) * 60.; // in minutes // Classic formula, which fails for due east/west courses.... if(dist) { if(cos(C)) *dist = (dlat /cos(C)); else *dist = DistGreatCircle(lat0, lon0, lat1, lon1); } // Calculate the bearing using the un-adjusted original latitudes and Mercator Sailing if(brg) { toSM_ECC(lat1, lon1x, lat0, lon0x, &east, &north); C = atan2(east, north); brgt = 180. + (C * 180. / PI); if (brgt < 0) brgt += 360.; if (brgt > 360.) brgt -= 360; *brg = brgt; } // Alternative formulary // From Roy Williams, "Geometry of Navigation", we have p = Dlo (Dlat/DMP) where p is the departure. // Then distance is then:D = sqrt(Dlat^2 + p^2) /* double dlo = (lon1x - lon0x) * 60.; double departure = dlo * dlat / ((north/1852.)); if(dist) *dist = sqrt((dlat*dlat) + (departure * departure)); */ }