xmsinterp  1.0
TutInterpolation.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 
12 // 2. My own header
13 
14 // 3. Standard library headers
15 
16 // 4. External library headers
17 
18 // 5. Shared code headers
19 #include <xmsgrid/geometry/geoms.h>
20 #include <xmscore/misc/xmstype.h>
21 // 6. Non-shared code headers
22 
23 //----- Forward declarations ---------------------------------------------------
24 
25 //----- External globals -------------------------------------------------------
26 
27 //----- Namespace declaration --------------------------------------------------
28 
29 namespace xms
30 {
31 //----- Constants / Enumerations -----------------------------------------------
32 
33 //----- Classes / Structs ------------------------------------------------------
34 
35 //----- Internal functions -----------------------------------------------------
36 
37 //----- Class / Function definitions -------------------------------------------
38 
39 } // namespace xms
40 
41 #if CXX_TEST
42 // UNIT TESTS
46 
48 
52 
57 //------------------------------------------------------------------------------
59 //------------------------------------------------------------------------------
62 {
63  BSHP<xms::VecInt> tris(new xms::VecInt()); // not used by idw
64 
65  // Create the points used to interpolate
66  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
67  *pts = {{0, 0, 0}, {10, 0, 1}, {10, 10, 2}, {0, 10, 3}};
68 
69  // create the interpolator class
70  BSHP<xms::InterpIdw> interp = xms::InterpIdw::New();
71  // Set the points and triangles used by the interpolator. The triangles are
72  // empty and are not used by idw.
73  interp->SetPtsTris(pts, tris);
74 
75  // interpolate to a location
76  xms::Pt3d loc(5, 5, 0);
77  float val = interp->InterpToPt(loc);
78 
79  // verify the value
80  float base(1.5);
81  TS_ASSERT_EQUALS(base, val);
82 
83 } // TutInterpolationIntermediateTests::test_Example_IDW
85 //------------------------------------------------------------------------------
87 //------------------------------------------------------------------------------
90 {
91  // Create the points used to interpolate
92  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
93  *pts = {{0, 0, 0}, {10, 0, 1}, {10, 10, 2}, {0, 10, 3}};
94 
95  // Create the triangles used to interpolate. The triangles are specified as
96  // 3 indexes that refer to the points vector. The indexes should be ordered
97  // counter clockwise.
98  BSHP<xms::VecInt> tris(new xms::VecInt());
99  *tris = {0, 1, 3, 1, 2, 3};
100 
101  // create the interpolator class
102  BSHP<xms::InterpLinear> interp = xms::InterpLinear::New();
103  // Set the points and triangles used by the interpolator.
104  interp->SetPtsTris(pts, tris);
105 
106  // interpolate to a location
107  xms::Pt3d loc(2, 1, 0);
108  float val = interp->InterpToPt(loc);
109 
110  // verify the value
111  float base(0.5);
112  TS_ASSERT_EQUALS(base, val);
113 } // TutInterpolationIntermediateTests::test_Example_Linear
115 //------------------------------------------------------------------------------
117 //------------------------------------------------------------------------------
120 {
121  // Create the points used to interpolate
122  BSHP<xms::VecPt3d> pts(new xms::VecPt3d());
123  *pts = {{0, 0, 0}, {10, 0, 1}, {10, 10, 2}, {0, 10, 3}};
124 
125  // Create the triangles used to interpolate. The triangles are specified as
126  // 3 indexes that refer to the points vector. The indexes should be ordered
127  // counter clockwise.
128  BSHP<xms::VecInt> tris(new xms::VecInt());
129  *tris = {0, 1, 3, 1, 2, 3};
130 
131  // create the interpolator class
132  BSHP<xms::InterpLinear> interp = xms::InterpLinear::New();
133  // Set the points and triangles used by the interpolator.
134  interp->SetPtsTris(pts, tris);
135 
136  int nodalFunc = 0; // 0 constant, 1 gradient plane, 3 quadratic
137  int nodalFuncOpt = 1; // 0 natural neighbors, 1 nearest n points
138  int nNearest = 12; // 12 nearest points used for nodal function
139  bool blendWeights = false; // flag to add weight blending
140  BSHP<xms::Observer> progress; // observer to get feedback
141  // set to use natural neighbor interpolation
142  interp->SetUseNatNeigh(true, nodalFunc, nodalFuncOpt, nNearest, blendWeights, progress);
143 
144  // interpolate to a location
145  xms::Pt3d loc(2, 1, 0);
146  float val = interp->InterpToPt(loc);
147 
148  // verify the value
149  float base(0.46f);
150  TS_ASSERT_EQUALS(base, val);
151 } // TutInterpolationIntermediateTests::test_Example_NaturalNeighbor
153 //------------------------------------------------------------------------------
155 //------------------------------------------------------------------------------
158 {
159  // Create the centerline points. The segments of this polyline will be mapped
160  // onto the x-axis. The total length will be preserved.
161  xms::VecPt3d centerline = {{0, 0, 0}, {20, 0, 0}, {40, 20, 0}, {60, 20, 0}};
162 
163  // Create the points used to interpolate. These points are typically taken
164  // from cross sections across the center line. These points will be
165  // transformed so that the x-coordinate corresponds to the intersection of a
166  // line through the point and perpendicular to a segment of the centerline.
167  // The y coordinate will be the distance above or below that intersection.
168  // Note that a single point may project onto several segments, generating
169  // multiple transformed points.
170  xms::VecPt3d interpolationPoints = {
171  // cross-section 1
172  {0, 10, 100},
173  {0, -10, 100},
174  // cross-section 2
175  {10, 10, 90},
176  {10, 5, 60},
177  {10, 0, 50},
178  {10, -5, 70},
179  {10, -10, 90},
180  // cross-section 3
181  {20, 20, 80},
182  {30, 10, 40},
183  {40, 0, 80},
184  // cross-section 4
185  {30, 40, 70},
186  {35, 30, 50},
187  {40, 20, 30},
188  {45, 10, 70},
189  // cross-section 5
190  {60, 30, 50},
191  {60, 10, 50},
192  };
193 
194  // create the interpolator class
195  BSHP<xms::InterpAnisotropic> interpolator = xms::InterpAnisotropic::New();
196 
197  // Set the centerline and interpolation points used by the interpolator.
198  // Any point may project onto several segments of the centerline. You can use
199  // all such transformed points or set pickClosest to true to use only the
200  // one nearest the centerline.
201  bool pickClosest = false;
202  interpolator->SetPoints(centerline, interpolationPoints, pickClosest);
203 
204  // After the points are transformed, an inverse distance weighted
205  // interpolation is done (using all of the interpolation points) after scaling
206  // the points in the x direction. The default x scale factor is 1. Set to a
207  // value less than 1 to compress the x values (thus giving them more weight
208  // than y) or to a value greater than 1 (to have the opposite effect).
209  interpolator->SetXScale(0.5);
210 
211  // Set the exponent of the inverse distance weight to a value over 1 to dilute
212  // the influence of interpolation points far from the point in question.
213  interpolator->SetPower(3);
214 
215  // You can access the actual transformed interpolation points as shown below.
216  // This isn't necessary for the interpolation, but is useful if you want
217  // plot and visualize the transformation.
218  xms::VecPt3d snPoints;
219  interpolator->GetInterpolationPts(snPoints);
220  // clang-format off
221  xms::VecPt3d expectedSnPoints = {
222  // cross-section 1
223  {0, 10, 100}, // 0
224  {0, -10, 100}, // 1
225  // cross-section 2
226  {5, 10, 90}, // 2
227  {10, 14.142, 90}, // 2
228  {5, 5, 60}, // 3
229  {5, 0, 50}, // 4
230  {5, -5, 70}, // 5
231  {5, -10, 90}, // 6
232  // cross-section 3
233  {10, 20, 80}, // 7
234  {17.071, 14.142, 80}, // 7
235  {17.071, 0, 40}, // 8
236  {17.071, -14.142, 80}, // 9
237  {24.142, -20, 80}, // 9
238  // cross-section 4
239  {24.142, 22.361, 70}, // 10
240  {24.142, 11.180, 50}, // 11
241  {24.142, 0, 30}, // 12
242  {24.142, 0, 30}, // 12
243  {22.374, -10.607, 70}, // 13
244  {26.642, -10, 70}, // 13
245  // cross-section 5
246  {34.142, 10, 50}, // 14
247  {34.142, -10, 50} // 15
248  };
249  TS_ASSERT_DELTA_VECPT3D(expectedSnPoints, snPoints, 0.01);
250  // interpolate to a location and verify the value.
251  xms::Pt3d loc(20, 5, 0);
252  float val = interpolator->InterpToPt(loc);
253  float base(59.5313f);
254  TS_ASSERT_DELTA(base, val, 0.001);
255 
256  // interpolate to several locations and verify the values. Note that the
257  // last two points are beyond the range of the centerline; hence, they
258  // generate no data (XM_NODATA) interpolation values.
259  xms::VecPt3d interpToPoints = {
260  {5, 5, 0}, {5, 0, 0}, {5, -5, 0},
261  {20, 5, 0},
262  {20, 0, 0},
263  {20, -5, 0}, {10, 20, 0}, {30, -5, 0}, {30, 30, 0},
264  {35, 20, 0}, {45, 25, 0}, {45, 15, 0},
265  {65, 20, 0}, {-5, 0, 0}};
266 
267  // The transformed values of interpolated to points can be retrieved by
268  // using GetTransformedPts. The transformed points could be used for
269  // plotting or using another interpolation method.
270  xms::VecPt3d snInterpToPoints;
271  interpolator->GetTransformedPts(interpToPoints, false, snInterpToPoints);
272  xms::VecPt3d expectedSnInterpToPoints = {
273  {2.5, 5, 0}, {2.5, 0, 0}, {2.5, -5, 0}, // points 0, 1, 2
274  {10, 5, 0}, {11.768, 3.536, 0}, // point 3 is transformed to 2 stations
275  {10, 0, 0}, {10, 0, 0}, // point 4 is transformed to segment 0 { param 1 } and segment 1 { param 0 }
276  {10, -5, 0}, {5, 20, 0}, {13.536, 21.213, 0}, {11.768, -10.607, 0}, // points 5, 6, 7
277  {24.142, 14.142, 0}, {22.374, 3.536, 0}, {26.642, 5, 0}, // points 8, 9, 10
278  {24.142, -7.071, 0}, {26.642, -5, 0}}; // point 11 is transformed to 2 stations
279  // clang-format on
280  TS_ASSERT_DELTA_VECPT3D(expectedSnInterpToPoints, snInterpToPoints, 0.001);
281 
282  xms::VecFlt interpValues;
283  interpolator->InterpToPts(interpToPoints, interpValues);
284  xms::VecFlt expectedInterpValues = {64.614f, 54.390f, 71.970f, 59.531f, 58.468f,
285  68.0917f, 81.688f, 76.032f, 53.130f, 35.413f,
286  40.457f, 50.839f, (float)XM_NODATA, (float)XM_NODATA};
287  TS_ASSERT_DELTA_VEC(expectedInterpValues, interpValues, 0.01);
288 
289 } // TutInterpolationIntermediateTests::test_Example_Anisotropic
291 #endif
void test_Example_IDW()
Example for IDW Interpolation.
void test_Example_Linear()
[snip_test_Example_Idw]
#define TS_ASSERT_DELTA_VECPT3D(a, b, delta)
static BSHP< InterpIdw > New()
Creates an InterpIdw class.
Definition: InterpIdw.cpp:284
void test_Example_Anisotropic()
[snip_test_Example_NatNeigh]
#define XM_NODATA
void test_Example_NaturalNeighbor()
[snip_test_Example_Linear]
static BSHP< InterpLinear > New()
Creates an TriSearch class.
#define TS_ASSERT_DELTA_VEC(a, b, delta)
static BSHP< InterpAnisotropic > New()
Creates an InterpAnisotropic class.