bool _stdcall PtIsOnArc( const LLPoint & llArcCenter, double dArcRadius, double dArcStartAzimuth, double dArcEndAzimuth, int nArcDirection, const LLPoint & llTestPt, int & bOnArc ) { InverseResult invResult; if(!DistVincenty(llArcCenter, llTestPt, invResult)) return false; double dDist = invResult.distance; double dCrs = invResult.azimuth; bOnArc = false; if(fabs(dDist - dArcRadius) > 0.5e-3) //Tol()) bOnArc = false; else { double dArcExtent = GetArcExtent(dArcStartAzimuth, dArcEndAzimuth, nArcDirection, Tol()); if(dArcExtent == M_2PI) bOnArc = true; else { double dSubExtent = GetArcExtent(dArcStartAzimuth, dCrs, nArcDirection, Tol()); if(nArcDirection > 0) { if(dSubExtent <= dArcExtent) bOnArc = true; } else { if(dSubExtent >= dArcExtent) bOnArc = true; } } } return true; }
bool PtIsOnArc(const LLPoint &llArcCenter, double dArcRadius, double dArcStartAzimuth, double dArcEndAzimuth, int nArcDirection, const LLPoint &llTestPt, int &bOnArc) { InverseResult invResult; if (!DistVincenty(llArcCenter, llTestPt, invResult)) return false; bOnArc = false; if (fabs(invResult.distance - dArcRadius) <= 0.5e-3) { const double dSubtendedAng1 = GetArcExtent(dArcStartAzimuth, dArcEndAzimuth, nArcDirection, kTol); if (dSubtendedAng1 == M_2PI) bOnArc = true; else { const double dSubtendedAng2 = GetArcExtent(dArcStartAzimuth, invResult.azimuth, nArcDirection, kTol); if (nArcDirection > 0) { if (dSubtendedAng2 <= dSubtendedAng1) bOnArc = true; } else { if (dSubtendedAng2 >= dSubtendedAng1) bOnArc = true; } } } return true; }
double DiscretizedArcLength(const LLPoint ¢er, double dRadius, double dStartCrs, double dEndCrs, int nOrient, int nSegments, double dTol) { nSegments = clamp(nSegments, 1, 128); double dError = 0.0; double dArcLength = 0.0; double dOldArcLength = 0.0; const double dSubtendedAngle = GetArcExtent(dStartCrs, dEndCrs, nOrient, dTol); // with k equal to 0 then there will only be nSegments subsegments calculated. // need to figure out how to make this flexible based on the value in dRadius. // Bigger radius need more segments than 16 and smaller segments need less. // For now 16 is enough to pass the 8260.54A test case. int k = 0; while (k == 0 || ((dError > kTol) && (k <= 0))) { const double dTheta = dSubtendedAngle / nSegments; const double dAltitude = 0.0; dArcLength = 0.0; for (int i = 0; i < nSegments; i++) { const double theta = dStartCrs + i * dTheta; const LLPoint p1 = DestVincenty(center, theta, dRadius); const LLPoint p2 = DestVincenty(center, theta + 0.5 * dTheta, dRadius); const LLPoint p3 = DestVincenty(center, theta + dTheta, dRadius); const VMath::Vector3 v1 = ECEF(p1, dAltitude); const VMath::Vector3 v2 = ECEF(p2, dAltitude); const VMath::Vector3 v3 = ECEF(p3, dAltitude); const VMath::Vector3 vChord1 = v2 - v1; const VMath::Vector3 vChord2 = v2 - v3; const double x1 = VMath::Vector3::Length(vChord1); //v2 - v1); const double x2 = VMath::Vector3::Length(vChord2); //v2 - v3); const double d = VMath::Vector3::Dot(vChord1, vChord2); if (IsNearZero(x1, kTol) && IsNearZero(x2, kTol) && IsNearZero(d, kTol)) { dArcLength = 0.0; break; } const double xi = d / (x1 * x2); const double _x1_x2Sq = x1 / x2 - xi; const double sigma = sqrt(1.0 - (xi * xi)); const double R = (x2 * sqrt((_x1_x2Sq * _x1_x2Sq) + (sigma * sigma))) / (2.0 * sigma); const double A = 2 * (M_PI - acos(xi)); const double L = R * A; dArcLength += L; } nSegments *= 2; dError = fabs(dArcLength - dOldArcLength); dOldArcLength = dArcLength; k++; } return dArcLength; }