26 #include <xmsgrid/geometry/geoms.h> 38 const double kVERTICAL = std::numeric_limits<double>::quiet_NaN();
47 , m_intercept(a_intercept)
58 if (std::isnan(m_slope))
66 double slope = -1.0 / m_slope;
92 a_p.
x = std::isnan(a_other.
m_slope) ? d : ((d - b) / (a - c));
93 a_p.
y = a * a_p.
x + b;
118 const VecPt3d& a_interpolationPts,
123 size_t points_sz = a_centerLinePts.size();
129 for (
size_t i = 1; i < points_sz; ++i)
131 const Pt3d& p0 = a_centerLinePts[i - 1];
132 const Pt3d& p1 = a_centerLinePts[i];
133 if (p0.
x == p1.
x && p0.
y == p1.
y)
156 for (
auto& p : a_points)
159 results.insert(results.end(), tranformedPts.begin(), tranformedPts.end());
188 const VecPt3d& a_interpolationPoints,
197 result =
CalculateIDW(a_xScale, a_interpolationPoints, snvs[0], a_IDWPower, a_tol);
209 double dx(a_p0.
x - a_p1.
x);
210 double dy(a_p0.
y - a_p1.
y);
211 double distanceSquared(dx * dx + dy * dy);
212 return sqrt(distanceSquared);
226 double dx = a_xScale * (a_p0.
x - a_p1.
x);
227 double dy = a_p0.
y - a_p1.
y;
228 return (dx * dx) + (dy * dy);
248 const Pt3d& a_target,
252 double numerator(0.0);
253 double denominator(0.0);
254 double power(
double(a_power) * 0.5);
255 std::function<double(double)> powerFunc;
257 powerFunc = [](
double x) ->
double {
return x; };
259 powerFunc = [=](
double x) ->
double {
return pow(x, power); };
260 for (
auto& p : a_points)
264 if (distanceSquared <= a_tol)
268 double weight(1.0 / powerFunc(distanceSquared));
269 numerator += value * weight;
270 denominator += weight;
272 return numerator / denominator;
286 const Pt3d& pa = a_p;
289 double bcx = pc.
x - pb.
x;
290 double bcy = pc.
y - pb.
y;
291 double bax = pa.
x - pb.
x;
292 double bay = pa.
y - pb.
y;
293 return gmCross2D(bcx, bcy, bax, bay);
304 if (a_p0.
x == a_p1.
x)
308 double slope = (a_p1.
y - a_p0.
y) / (a_p1.
x - a_p0.
x);
309 double intercept(a_p0.
y - slope * a_p0.
x);
326 return gmPtDistanceAlongSegment(pi, pf, a_p, 1.0e-7);
341 Pt3d& a_intersection,
342 double& a_param)
const 376 a_results.push_back(
SNResult(a_segmentIndex, param, cross, intersection));
379 else if (a_lastParam > 1.0)
382 a_results.push_back(
SNResult(a_segmentIndex, 0.0, cross, pa));
396 double lastParam = -1.0;
423 double value = a_p.
z;
428 for (
auto& result : results)
433 double s = len0 + result.m_param * (len1 - len0);
434 double n = (result.m_cross == 0.0) ? 0.0
435 : result.m_cross < 0.0 ? -
Distance(a_p, result.m_position)
437 Pt3d snv(s, n, value);
440 if (snPoints.size() == 0)
442 snPoints.push_back(snv);
444 else if (abs(snv.
y) < abs(snPoints[0].y))
451 snPoints.push_back(snv);
477 VecPt3d centerline = {{-1, 0, 0}, {0, 0, 0}, {1, 0, 0}};
478 VecPt3d crossSections = {{-0.5, -1, 0}, {-0.5, 0, -1}, {-0.5, 1, 0},
479 {0.5, -1, 0}, {0.5, 0, -1}, {0.5, 1, 0}};
480 Pt3d target(0, 0, 0);
483 bool pickClosest =
true;
484 interpolator.
SetPoints(centerline, crossSections, pickClosest);
495 VecPt3d snPoints2 = {sn1, sn4};
498 TS_ASSERT_EQUALS(expect, result);
500 VecPt3d snPoints3 = {sn0, sn2, sn3, sn5};
503 TS_ASSERT_EQUALS(expect, result);
507 TS_ASSERT_DELTA(expect, result, 0.01);
525 VecPt3d centerline = {{-10, 0, 0}, {-10, 10, 0}, {10, 10, 0}, {10, 0, 0}};
526 VecPt3d crossSections = {{-15, 15, 0}, {-10, 10, -1}, {-5, 5, 0},
527 {5, 5, 0}, {10, 10, -1}, {15, 15, 0}};
528 Pt3d target(0, 5, 0);
531 bool pickClosest =
false;
532 interpolator.
SetPoints(centerline, crossSections, pickClosest);
534 double cross = interpolator.
CrossProduct(0, crossSections[2]);
535 TS_ASSERT(cross < 0.0);
538 VecPt3d sn2Expected = {{5, -5, 0}, {15, -5, 0}, {35, -15, 0}};
541 VecPt3d sn3Expected = {{5, -15, 0}, {25, -5, 0}, {35, -5, 0}};
547 double expect = -0.2699;
548 TS_ASSERT_DELTA(expect, result, 0.01);
550 Pt3d target2(0, 15, 0);
552 TS_ASSERT_DELTA(result, result2, 1.0e-6);
554 Pt3d target3 = crossSections[1];
557 TS_ASSERT_DELTA(crossSections[1].z, result3, 1.0e-6);
580 VecPt3d centerline = {{-10, 10, 0}, {0, 0, 0}, {10, 10, 0}};
581 VecPt3d crossSections = {{-8, 2, -3}, {-2, 8, 2}, {2, 8, 2}, {8, 2, -3}};
584 bool pickClosest =
true;
585 interpolator.
SetPoints(centerline, crossSections, pickClosest);
588 double xScale = 0.25;
589 double idwPower = 3.0;
592 Pt3d target1(0, 4.242, 0);
593 double result1 = interpolator.
InterpolatePoint(target1, snPoints, xScale, idwPower);
594 double expect1 = 2.0;
595 TS_ASSERT_DELTA(expect1, result1, 0.1);
598 Pt3d target2(0, -4.242, 0);
599 double result2 = interpolator.
InterpolatePoint(target2, snPoints, xScale, idwPower);
600 double expect2 = -3.0;
601 TS_ASSERT_DELTA(expect2, result2, 0.1);
604 VecPt3d transform1Expected = {{11.14, 3.00, 0}, {17.14, 3.00, 0}};
608 VecPt3d transform2Expected = {{14.14, -4.242, 0}};
VecDbl m_accLengths
The accumulated distance along the centerline of each point.
VecPt3d m_centerLinePts
The polyline representing the centerline.
double InterpolatePoint(const Pt3d &a_target, const VecPt3d &a_interpolationPoints, double a_xScale, double a_IDWPower=2, double a_tol=1.0e-5)
Interpolate the z coordinate of the interpolation points to point a_target.
void testAmbiguity()
Test to demonstrate ambiguity.
LineParameters GetLineParameters(const Pt3d &a_p0, const Pt3d &a_p1) const
Compute the 2d slope and intercept for a line through two points.
bool GetIntersectionOfSegmentWithPoint(size_t a_segmentIndex, const Pt3d &a_p, Pt3d &a_intersection, double &a_param) const
Get the intersecting point and its parameter of a line through point a_p normal to a segment of m_cen...
bool Intersection(const LineParameters &a_other, Pt3d &a_p) const
Get the intersection point of this and another line.
VecPt3d TransformPoint(const Pt3d &a_p, bool a_onlyClosest=false)
Transforms a point from (x, y, z) to (s, n, z) coordinates. s is for station (distance along the cent...
double CalculateIDW(double a_xScale, const VecPt3d &a_points, const Pt3d &a_target, double a_power, double a_tol=1.0e-5)
Calculates the Inverse Distance Weighted interpolation of a set of points at a target point...
AnisotropicInterpolator()
Constructor.
VecPt3d m_SNPoints
The interpolation points.
VecPt3d ComputeInterpolationPoints(const VecPt3d &a_interpolationPts, bool a_pickClosest)
Transforms a set of points from normal (x, y, z) coordinates to (s, n, z) coordinates. Note: The z coordinate is left unchanged.
LineParameters NormalThrough(const Pt3d &a_p) const
Get the LineParameters for a line normal to this through a point.
double CrossProduct(size_t a_segmentIndex, const Pt3d &a_p) const
Compute the 2d cross product of the vectors from a_p to the 1st and last points in a segment of m_cen...
Hold data of transforming from xyz to station,normal space.
double AnisotropicDistanceSquared(const Pt3d &a_p0, const Pt3d &a_p1, double a_xScale)
Compute the distance squared between two points, after a scale factor is applied to their x coordinat...
void SetPoints(const VecPt3d &a_centerlinePts, const VecPt3d &a_interpolationPts, bool a_pickClosest=false)
Set the centerline points to parameterize to.
const VecPt3d & GetInterpolationPoints() const
Get the transformed interpolation points in (s, n, z) space.
void testSimple()
Tests simple interpolation problem.
void testCrossSectionThroughPoint()
Tests interpolation of crosssection going through a centerline point.
std::vector< SNResult > VecSNResult
A Vector of station normal results (for a given point).
Class to transform points relative to a centerline polyline into a space where the centerline segment...
double Distance(const Pt3d &a_p0, const Pt3d &a_p1) const
Compute the distance between two points.
double GetParameterInSegment(size_t a_segmentIndex, const Pt3d &a_p) const
Compute the parameter for a point in a segment of m_centerLinePts. The parameter will be between 0 an...
LineParameters(double a_slope, double a_intercept)
Constructor from slope and intercept.
void GetNormalPointParameter(size_t a_segmentIndex, const Pt3d &a_p, double &a_lastParam, VecSNResult &a_results) const
Append the transform (if any) of a point to a centerline segment.
double m_slope
Slope of the line. 0 is horizontal. Nan is vertical.
void GetAllNormalPointParameters(const Pt3d &a_p, VecSNResult &a_results)
Get the SNResults for a point.
double m_intercept
x intercept if vertical; else, the y intercept.
std::vector< LineParameters > m_lineParams
const double kVERTICAL
Slope value indicating that a line is vertical.
std::vector< Pt3d > VecPt3d
2D Line definition. If vertical m_slope is Nan.