xmsinterp  1.0
InterpIdw.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 #include <boost/thread.hpp>
12 // 2. My header
14 
15 // 3. Standard Library Headers
16 
17 // 4. External Library Headers
18 
19 // 5. Shared Headers
20 #include <xmscore/math/math.h>
21 #include <xmscore/stl/utility.h>
22 #include <xmscore/stl/vector.h>
23 #include <xmsgrid/geometry/GmPtSearch.h>
27 #include <xmsgrid/geometry/geoms.h>
30 #include <xmscore/misc/XmError.h>
31 #include <xmscore/misc/xmstype.h>
32 
33 // 6. Non-shared Headers
34 
35 //----- Forward declarations ---------------------------------------------------
36 
37 //----- External globals -------------------------------------------------------
38 
39 //----- Namespace declaration --------------------------------------------------
40 
41 namespace xms
42 {
43 //----- Constants / Enumerations -----------------------------------------------
44 
45 //----- Classes / Structs ------------------------------------------------------
47 class InterpIdwImpl : public InterpIdw
48 {
49 public:
51  class InterpThread : public ThreadLoop
52  {
53  public:
58  InterpThread(InterpIdwImpl& a_, VecFlt& a_s, const VecPt3d& a_p)
59  : m_interp(a_)
60  , m_scalarTo(a_s)
61  , m_pts(a_p)
62  {
63  } // InterpThread
64 
67  const VecPt3d& m_pts;
68 
71  BSHP<ThreadLoop> CreateForNewThread() override
72  {
73  BSHP<InterpThread> r(new InterpThread(m_interp, m_scalarTo, m_pts));
74  BSHP<ThreadLoop> q = BDPC<ThreadLoop>(r);
75  return q;
76  }
77 
78  private:
80  void Worker() override
81  {
82  int i = (int)CurrIdx();
83  m_scalarTo[i] = m_interp.InterpToPt(m_pts[i], i);
84  }
85  };
86 
87  InterpIdwImpl();
88  virtual ~InterpIdwImpl();
89 
90  virtual void SetPtsTris(BSHP<VecPt3d> a_pts, BSHP<VecInt> a_tris) override;
91  void SetScalars(const float* a_scalar, size_t a_n) override;
92  void SetScalars(BSHP<VecFlt> a_scalar) override;
93  virtual void SetPts(BSHP<VecPt3d> a_pts, bool a_2d) override;
94  // this method will run parallel
95  virtual float InterpToPt(const Pt3d& a_pt) override;
96  virtual void InterpToPts(const VecPt3d& a_pts, VecFlt& a_scalars) override;
97  virtual void SetPtActivity(DynBitset& a_activity) override;
99  virtual void SetTriActivity(DynBitset&) override {}
100  virtual const BSHP<VecPt3d> GetPts() const override;
101  virtual const BSHP<VecInt> GetTris() const override;
102  virtual const BSHP<VecFlt> GetScalars() const override;
103  virtual DynBitset GetPtActivity() const override;
104  virtual DynBitset GetTriActivity() const override;
105  virtual void SetTrunc(double a_sMax, double a_sMin) override;
106 
109  virtual bool GetTruncateInterpolatedValues() const override { return m_trunc; }
112  virtual double GetTruncMin() const override { return m_truncMin; }
115  virtual double GetTruncMax() const override { return m_truncMax; }
118  virtual double GetPower() const override { return m_power; }
121  virtual int GetSearchOptsNumNearestPts() const override { return m_nNearestPts; }
124  virtual bool GetSearchOptsUseQuadrantSearch() const override { return m_quadOctSearch; }
127  virtual WeightEnum GetWeightCalcMethod() const override
128  {
130  return InterpIdw::CLASSIC;
131  return InterpIdw::MODIFIED;
132  }
135  virtual NodalFuncEnum GetNodalFunctionType() const override
136  {
137  if (!m_nodalFunc)
138  return InterpIdw::CONSTANT;
139  return static_cast<InterpIdw::NodalFuncEnum>(m_nodalFunc->GetType());
140  }
143  virtual int GetNodalFunctionNumNearestPts() const override
144  {
145  if (!m_nodalFunc)
146  return 0;
147  return m_nodalFunc->GetNumNearestPoints();
148  }
151  virtual bool GetNodalFunctionUseQuadrantSearch() const override
152  {
153  if (!m_nodalFunc)
154  return false;
155  return m_nodalFunc->GetUseQuadrantSearch();
156  }
157 
158 
161  virtual void SetSaveWeights(bool a_) override { m_saveWeights = a_; }
162  virtual void InterpWeights(const Pt3d& a_pt,
163  VecInt& a_idx,
164  VecDbl& a_wt) const override;
165 
169  virtual void SetMultiThreading(bool a_) override { m_multiThread = a_; }
170 
171  virtual std::string ToString() const override;
172 
173  void SetPower(double a_power) override;
174  void RecalcNodalFunc();
175  void SetSearchOpts(int a_nNearestPoints, bool a_quad_oct_Search) override;
176  float InterpToPt(const Pt3d& a_pt, int a_idx) const;
180  void SetObserver(BSHP<Observer> a_prog) override { m_prog = a_prog; }
181 
182  void ValFromWeights(VecDbl& a_w,
183  VecInt& a_nPts,
184  float& a_val,
185  int a_ptIdx,
186  const Pt3d& a_pt) const;
187  void SetWeightCalcMethod(InterpIdw::WeightEnum a_) override;
189  int a_nNearest,
190  bool a_quad_oct,
191  BSHP<Observer> a_p) override;
193  int a_nNearest,
194  bool a_quad_oct,
195  BSHP<Observer> a_p);
196  double ScalarFromNodalFunc(int a_ptIdx, const Pt3d& a_loc) const;
197 
198  bool m_2d;
199  bool m_quadOctSearch;
204  double m_power;
208  BSHP<GmPtSearch> m_ptSearch;
209  BSHP<VecPt3d> m_pts;
210  BSHP<VecInt> m_tris;
211  BSHP<VecFlt> m_scalarFrom;
212  BSHP<NodalFunc> m_nodalFunc;
213  BSHP<Observer> m_prog;
217  bool m_trunc;
218  double m_truncMax;
219  double m_truncMin;
221  std::string m_idString;
222 };
223 
224 //----- Internal functions -----------------------------------------------------
225 namespace
226 {
227 //------------------------------------------------------------------------------
229 //------------------------------------------------------------------------------
230 static VecInt2d& iPtIdx()
231 {
232  static VecInt2d m_;
233  return m_;
234 }
235 //------------------------------------------------------------------------------
237 //------------------------------------------------------------------------------
238 static VecDbl2d& iWeights()
239 {
240  static VecDbl2d m_weights;
241  return m_weights;
242 }
243 //------------------------------------------------------------------------------
247 //------------------------------------------------------------------------------
248 static void iSaveWeight(int a_ptIdx, int a_pt, double a_val)
249 {
250  XM_ENSURE_TRUE_VOID_NO_ASSERT(a_ptIdx > XM_NONE);
251  iPtIdx()[a_ptIdx].push_back(a_pt);
252  iWeights()[a_ptIdx].push_back(a_val);
253 } // iSaveWeight
254 //------------------------------------------------------------------------------
258 //------------------------------------------------------------------------------
259 static void iCallSignals(VecInt2d& a_ptIdx,
260  VecDbl2d& a_weights)
261 {
262  for (size_t i = 0; i < a_ptIdx.size(); ++i)
263  {
264  inSetDataIndex((int)i);
265  for (size_t j = 0; j < a_ptIdx[i].size(); ++j)
266  {
267  inFillWtArray(a_ptIdx[i][j] + 1, a_weights[i][j]);
268  }
269  }
270  a_ptIdx.clear();
271  a_weights.clear();
272 } // iCallSignals
273 } // unnamed namespace
274 //----- Class / Function definitions -------------------------------------------
275 
280 //------------------------------------------------------------------------------
283 //------------------------------------------------------------------------------
284 BSHP<InterpIdw> InterpIdw::New()
285 {
286  BSHP<InterpIdw> ptr(new InterpIdwImpl());
287  return ptr;
288 } // InterpIdw::New
289 //------------------------------------------------------------------------------
291 //------------------------------------------------------------------------------
293 {
294 }
295 //------------------------------------------------------------------------------
297 //------------------------------------------------------------------------------
299 {
300 }
301 
307 //------------------------------------------------------------------------------
309 //------------------------------------------------------------------------------
311 : m_2d(true)
312 , m_quadOctSearch(false)
313 , m_modifiedShepardWeights(true)
314 , m_nNearestPts(16)
315 , m_power(2)
316 , m_ptSearch()
317 , m_pts(new VecPt3d())
318 , m_tris(new VecInt())
319 , m_scalarFrom(new VecFlt())
320 , m_nodalFunc()
321 , m_prog()
322 , m_saveWeights(false)
323 , m_trunc(false)
324 , m_truncMax(0.0)
325 , m_truncMin(0.0)
326 , m_multiThread(true)
327 {
328 } // InterpIdwImpl::InterpIdwImpl
329 //------------------------------------------------------------------------------
331 //------------------------------------------------------------------------------
332 InterpIdwImpl::~InterpIdwImpl()
333 {
334 } // InterpIdwImpl::~InterpIdwImpl
335 //------------------------------------------------------------------------------
339 //------------------------------------------------------------------------------
340 void InterpIdwImpl::SetPtsTris(BSHP<VecPt3d> a_pts, BSHP<VecInt> a_tris)
341 {
342  SetPts(a_pts, true);
343  m_tris = a_tris;
344 } // InterpIdwImpl::SetPtsTris
345 //------------------------------------------------------------------------------
349 //------------------------------------------------------------------------------
350 void InterpIdwImpl::SetPts(BSHP<VecPt3d> a_pts, bool a_2d)
351 {
352  m_2d = a_2d;
353  m_pts = a_pts;
354  m_ptSearch = GmPtSearch::New(m_2d);
355  m_ptSearch->PtsToSearch(m_pts);
356  if (m_2d && m_scalarFrom->empty())
357  {
358  m_scalarFrom->resize(0);
359  m_scalarFrom->reserve(m_pts->size());
360  VecFlt& s(*m_scalarFrom);
361  VecPt3d& pts(*m_pts);
362  for (Pt3d& p : pts)
363  s.push_back((float)p.z);
364  }
365 } // InterpIdwImpl::SetPts
366 //------------------------------------------------------------------------------
370 //------------------------------------------------------------------------------
371 void InterpIdwImpl::SetScalars(const float* a_scalar, size_t a_n)
372 {
373  m_scalarFrom->resize(0);
374  m_scalarFrom->insert(m_scalarFrom->begin(), a_scalar, a_scalar + a_n);
375  RecalcNodalFunc();
376 } // InterpIdwImpl::SetScalars
377 //------------------------------------------------------------------------------
380 //------------------------------------------------------------------------------
381 void InterpIdwImpl::SetScalars(BSHP<VecFlt> a_scalar)
382 {
383  m_scalarFrom = a_scalar;
384  RecalcNodalFunc();
385 } // InterpIdwImpl::SetScalars
386 //------------------------------------------------------------------------------
392 //------------------------------------------------------------------------------
393 void InterpIdwImpl::SetPower(double a_power)
394 {
395  m_power = a_power;
396  XM_ENSURE_TRUE(!m_nodalFunc); // Not handled: SetPower after creating nodal func
397 } // InterpIdwImpl::SetPower
398 //------------------------------------------------------------------------------
400 //------------------------------------------------------------------------------
402 {
403  if (m_nodalFunc)
404  {
405  m_nodalFunc->ComputeNodalFuncs();
406  }
407 } // InterpIdwImpl::RecalcNodalFunc
408 //------------------------------------------------------------------------------
416 //------------------------------------------------------------------------------
417 void InterpIdwImpl::SetSearchOpts(int a_nNearestPoints, bool a_quad_oct_Search)
418 {
419  m_nNearestPts = a_nNearestPoints;
420  m_quadOctSearch = a_quad_oct_Search;
421 } // InterpIdwImpl::SetPower
422 //------------------------------------------------------------------------------
426 //------------------------------------------------------------------------------
427 float InterpIdwImpl::InterpToPt(const Pt3d& a_pt)
428 {
429  return InterpToPt(a_pt, XM_NONE);
430 } // InterpIdwImpl::InterpToPt
431 //------------------------------------------------------------------------------
439 //------------------------------------------------------------------------------
440 float InterpIdwImpl::InterpToPt(const Pt3d& a_pt, int a_idx) const
441 {
442  float rval(0);
443  XM_ENSURE_FALSE(m_scalarFrom->empty(), rval);
444  VecInt nPts;
445  VecDbl w;
446  InterpWeights(a_pt, nPts, w);
447  if (1 == nPts.size())
448  {
449  rval = (*m_scalarFrom)[nPts[0]];
450  if (m_saveWeights)
451  iSaveWeight(a_idx, nPts[0], 1.0);
452  return rval;
453  }
454  ValFromWeights(w, nPts, rval, a_idx, a_pt);
455  if (m_trunc)
456  {
457  if (rval < m_truncMin)
458  rval = (float)m_truncMin;
459  if (rval > m_truncMax)
460  rval = (float)m_truncMax;
461  }
462  return rval;
463 } // InterpIdwImpl::InterpToPt
464 //------------------------------------------------------------------------------
471 //------------------------------------------------------------------------------
472 void InterpIdwImpl::InterpToPts(const VecPt3d& a_pts, VecFlt& a_scalars)
473 {
474  a_scalars.assign(a_pts.size(), 0);
475  if (m_saveWeights)
476  {
477  iPtIdx().assign(a_scalars.size(), VecInt());
478  iWeights().assign(a_scalars.size(), VecDbl());
479  }
480 
481  if (!m_multiThread)
482  {
483  for (size_t i = 0; i < a_pts.size(); ++i)
484  {
485  a_scalars[i] = InterpToPt(a_pts[i], (int)i);
486  }
487  }
488  else
489  {
490  BSHP<ThreadMgr> threadMgr = ThreadMgr::New();
491  threadMgr->SetThreadLoopClass(InterpThread(*this, a_scalars, a_pts).CreateForNewThread());
492  threadMgr->SetObserver(m_prog);
493  if (a_pts.size() < 10000)
494  threadMgr->ExplicitlySetNumThreads(2);
495  threadMgr->RunThreads((int)a_scalars.size());
496  }
497 
498  if (m_saveWeights)
499  iCallSignals(iPtIdx(), iWeights());
500 } // InterpIdwImpl::InterpToPts
501 //------------------------------------------------------------------------------
504 //------------------------------------------------------------------------------
506 {
507  m_ptSearch->SetActivity(a_activity);
508 } // InterpIdwImpl::SetPtActivity
509 //------------------------------------------------------------------------------
512 //------------------------------------------------------------------------------
513 const BSHP<VecPt3d> InterpIdwImpl::GetPts() const
514 {
515  return m_pts;
516 } // InterpIdwImpl::GetPts
517 //------------------------------------------------------------------------------
520 //------------------------------------------------------------------------------
521 const BSHP<VecInt> InterpIdwImpl::GetTris() const
522 {
523  return m_tris;
524 } // InterpIdwImpl::GetTris
525 //------------------------------------------------------------------------------
528 //------------------------------------------------------------------------------
529 const BSHP<VecFlt> InterpIdwImpl::GetScalars() const
530 {
531  return m_scalarFrom;
532 } // InterpIdwImpl::GetScalars
533 //------------------------------------------------------------------------------
536 //------------------------------------------------------------------------------
538 {
539  if (!m_ptSearch)
540  return DynBitset();
541  return m_ptSearch->GetActivity();
542 } // InterpIdwImpl::GetPtActivity
543 //------------------------------------------------------------------------------
546 //------------------------------------------------------------------------------
548 {
549  return DynBitset();
550 } // InterpIdwImpl::GetTriActivity
551 //------------------------------------------------------------------------------
556 //------------------------------------------------------------------------------
557 void InterpIdwImpl::SetTrunc(double a_sMax, double a_sMin)
558 {
559  m_trunc = true;
560  m_truncMax = a_sMax;
561  m_truncMin = a_sMin;
562 } // InterpIdwImpl::SetTrunc
563 //------------------------------------------------------------------------------
570 //------------------------------------------------------------------------------
572  VecInt& a_nPts,
573  VecDbl& a_w) const
574 {
575  VecDbl d2;
576  // first see if we are at this location
577  m_ptSearch->NearestPtsToPt(a_pt, 1, false, a_nPts);
578  // get the distance between our location and the nearest point
579  inDistanceSquared(a_pt, a_nPts, *m_pts, m_2d, d2);
580  if (m_nNearestPts == 1 || d2[0] < gmXyTol())
581  {
582  a_w.resize(1);
583  a_w[0] = 1;
584  return;
585  }
586  // see if we are doing all points
587  if (m_nNearestPts < 0)
588  {
589  a_nPts.assign(m_pts->size(), 0);
590  for (size_t i = 0; i < m_pts->size(); ++i)
591  a_nPts[i] = (int)i;
592  }
593  else
594  {
595  m_ptSearch->NearestPtsToPt(a_pt, m_nNearestPts, m_quadOctSearch, a_nPts);
596  }
597  // compute weights for each point
598  inDistanceSquared(a_pt, a_nPts, *m_pts, m_2d, d2);
600 } // InterpIdwImpl::InterpWeights
601 //------------------------------------------------------------------------------
604 //------------------------------------------------------------------------------
605 std::string InterpIdwImpl::ToString() const
606 {
607  std::stringstream ss;
608  ss << m_2d << "=2d " << m_quadOctSearch << "=quadOctSearch " << m_modifiedShepardWeights
609  << "=modifiedShepardWeights " << m_nNearestPts << "=nNearestPts " << m_power << "=power "
610  << m_saveWeights << "=saveWeights " << m_multiThread << "=multiThread "
611  << "\n";
612 
613  if (m_ptSearch)
614  ss << m_ptSearch->ToString() << "=ptSearch "
615  << "\n";
616 
617  if (m_pts)
618  VecToStream(ss, *m_pts, "pts");
619  if (m_tris)
620  VecToStream(ss, *m_tris, "tris");
621  if (m_scalarFrom)
622  VecToStream(ss, *m_scalarFrom, "scalarFrom");
623 
624  if (m_nodalFunc)
625  ss << m_nodalFunc->ToString() << "=nodalFunc "
626  << "\n";
627 
628  for (size_t i = 0; i < m_ptIdx.size(); ++i)
629  VecToStream(ss, m_ptIdx[i], "ptIdx");
630  ss << "=ptIdx "
631  << "\n";
632 
633  for (size_t i = 0; i < m_weights.size(); ++i)
634  VecToStream(ss, m_weights[i], "weights");
635  ss << "=weights "
636  << "\n";
637 
638  return ss.str();
639 } // InterpIdwImpl::ToString
640 //------------------------------------------------------------------------------
651 //------------------------------------------------------------------------------
653  VecInt& a_nPts,
654  float& a_val,
655  int a_ptIdx,
656  const Pt3d& a_pt) const
657 {
658  a_val = 0;
659  double val(0);
660  for (size_t i = 0; i < a_w.size(); ++i)
661  {
662  int j = a_nPts[i];
663  // val += a_w[i] * m_scalarFrom[j];
664  val += a_w[i] * ScalarFromNodalFunc(j, a_pt);
665  if (m_saveWeights)
666  iSaveWeight(a_ptIdx, j, a_w[i]);
667  }
668  a_val = (float)val;
669 } // InterpIdwImpl::ValFromWeights
670 //------------------------------------------------------------------------------
675 //------------------------------------------------------------------------------
677 {
678  if (a_ == InterpIdw::CLASSIC)
679  m_modifiedShepardWeights = false;
680  else if (a_ == InterpIdw::MODIFIED)
682  else
684 } // InterpIdwImpl::SetWeightCalcMethod
685 //------------------------------------------------------------------------------
695 //------------------------------------------------------------------------------
697  int a_nNearest,
698  bool a_quad_oct,
699  BSHP<Observer> a_p)
700 {
701  XM_ENSURE_TRUE_VOID_NO_ASSERT(a_ != CONSTANT);
703  XM_ENSURE_TRUE(!m_pts->empty());
704 
705  CreateNodalFunctionPtr(a_, a_nNearest, a_quad_oct, a_p);
706 } // InterpIdwImpl::SetNodalFunction
707 //------------------------------------------------------------------------------
715 //------------------------------------------------------------------------------
717  int a_nNearest,
718  bool a_quad_oct,
719  BSHP<Observer> a_p)
720 {
721  m_nodalFunc = NodalFunc::New((int)a_, m_2d, m_ptSearch, *m_pts, *m_scalarFrom, a_nNearest,
722  a_quad_oct, m_power, m_modifiedShepardWeights, a_p, nullptr);
723 } // InterpIdwImpl::CreateNodalFunctionPtr
724 //------------------------------------------------------------------------------
732 //------------------------------------------------------------------------------
733 double InterpIdwImpl::ScalarFromNodalFunc(int a_ptIdx, const Pt3d& a_loc) const
734 {
735  double rval((double)(*m_scalarFrom)[a_ptIdx]);
736  if (m_nodalFunc)
737  {
738  rval = m_nodalFunc->ScalarFromPtIdx(a_ptIdx, a_loc);
739  }
740  return rval;
741 } // InterpIdwImpl::ScalarFromNodalFunc
742 
743 } // namespace xms
744 
745 #ifdef CXX_TEST
746 
749 
751 #include <xmscore/misc/XmLog.h>
752 
753 // namespace xms {
754 using namespace xms;
755 //------------------------------------------------------------------------------
760 //------------------------------------------------------------------------------
761 static void iGetPoints(VecPt3d& a_pts,
762  VecFlt& a_scalar,
763  VecPt3d& a_iPts)
764 {
765  a_pts = {{-75.0, -16.0, 0.0}, {-60.0, 32.0, 0.0}, {-34.0, 50.0, 0.0}, {-34.0, 27.0, 0.0},
766  {-8.0, 40.0, 0.0}, {16.0, 38.0, 0.0}, {-25.0, 14.0, 43.64}, {10.0, 18.0, 44.16},
767  {27.0, 26.0, 0.0}, {63.0, 35.0, 0.0}, {-32.0, 0.0, 59.04}, {-7.0, 7.0, 90.2},
768  {26.0, 6.0, 67.2}, {75.0, 7.0, 0.0}, {-37.0, -15.0, 9.24}, {-7.0, -13.0, 71.0},
769  {2.0, -3.0, 98.4}, {31.0, -15.0, 25.56}, {60.0, -13.0, 0.0}, {-50.0, -30.0, 0.0},
770  {-30.0, -28.0, 0.0}, {43.0, -22.0, 0.0}, {-32.0, -50.0, 0.0}, {27.0, -37.0, 0.0},
771  {60.0, -33.0, 0.0}};
772  a_scalar.resize(a_pts.size());
773  for (size_t i = 0; i < a_pts.size(); ++i)
774  a_scalar[i] = (float)a_pts[i].z;
775 
776  a_iPts = {{-90, 60, 0}, {90, 60, 0}, {-90, -60, 0}, {90, -60, 0}, {60, -33, 0}};
777 } // iGetPoints
778 
783 //------------------------------------------------------------------------------
785 //------------------------------------------------------------------------------
787 {
788  BSHP<InterpIdw> pts = InterpIdw::New();
789  TS_ASSERT(pts);
790 }
791 //------------------------------------------------------------------------------
793 //------------------------------------------------------------------------------
795 {
796  BSHP<InterpIdw> idw = InterpIdw::New();
797  BSHP<VecPt3d> pts(new VecPt3d());
798  pts->push_back(Pt3d());
799  VecFlt scalar(1, 2);
800  idw->SetPts(pts, true);
801  idw->SetScalars(&scalar[0], scalar.size());
802 
803  pts->resize(0);
804  pts->push_back(Pt3d(1, 1, 1));
805  scalar.resize(0);
806  idw->SetMultiThreading(false);
807  idw->InterpToPts(*pts, scalar);
808  TS_ASSERT_EQUALS(2.0f, scalar[0]);
809 } // InterpIdwUnitTests::testInterpToPts
810 //------------------------------------------------------------------------------
812 //------------------------------------------------------------------------------
814 {
815  BSHP<VecPt3d> pts(new VecPt3d());
816  VecPt3d ipts;
817  BSHP<VecFlt> scalar(new VecFlt());
818  VecFlt s, vBase;
819  iGetPoints(*pts, *scalar, ipts);
820 
821  BSHP<InterpIdw> idw = InterpIdw::New();
822  idw->SetPts(pts, true);
823  idw->SetScalars(scalar);
824  idw->SetMultiThreading(false);
825  idw->InterpToPts(ipts, s);
826  vBase = {4.5606198f, 2.9842966f, 4.8022637f, 2.8352659f, 0.0f};
827  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
828 } // InterpIdwUnitTests::testInterp2d_a
829 //------------------------------------------------------------------------------
831 //------------------------------------------------------------------------------
833 {
834  BSHP<VecPt3d> pts(new VecPt3d());
835  VecPt3d ipts;
836  VecFlt scalar, s(5), vBase;
837  iGetPoints(*pts, scalar, ipts);
838  BSHP<InterpIdw> idw = InterpIdw::New();
839  idw->SetPts(pts, true);
840  idw->SetScalars(&scalar[0], scalar.size());
841  idw->SetSearchOpts(-1, false);
842  for (int i = 0; i < 5; ++i)
843  s[i] = idw->InterpToPt(ipts[i]);
844  vBase = {10.172515f, 7.9736009f, 9.5391436f, 7.2670202f, 0.0f};
845  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
846 } // InterpIdwUnitTests::testInterp2d_b
847 //------------------------------------------------------------------------------
849 //------------------------------------------------------------------------------
851 {
852  BSHP<VecPt3d> pts(new VecPt3d());
853  VecPt3d ipts;
854  VecFlt scalar;
855  iGetPoints(*pts, scalar, ipts);
856  BSHP<InterpIdw> idw = InterpIdw::New();
857  idw->SetPts(pts, true);
858  idw->SetScalars(&scalar[0], scalar.size());
859  idw->SetSearchOpts(5, false);
860  VecInt idx;
861  VecDbl wt, wtBase;
862  Pt3d myPt;
863  idw->InterpWeights(myPt, idx, wt);
864  wtBase = {0.0019633969662346436, 0.064476394365326525, 0.0, 0.014616102731534851,
865  0.91894410593690401};
866  TS_ASSERT_DELTA_VEC(wtBase, wt, 1e-7);
867 } // InterpIdwUnitTests::testInterp2d_c
868 //------------------------------------------------------------------------------
870 //------------------------------------------------------------------------------
872 {
873  BSHP<VecPt3d> pts(new VecPt3d());
874  VecPt3d ipts;
875  VecFlt scalar, s(5), vBase;
876  iGetPoints(*pts, scalar, ipts);
877  BSHP<InterpIdw> idw = InterpIdw::New();
878  idw->SetPts(pts, true);
879  idw->SetScalars(&scalar[0], scalar.size());
880  idw->SetSearchOpts(6, true);
881  idw->SetPower(3);
882  idw->SetNodalFunction(InterpIdw::GRAD_PLANE, 6, true, NULL);
883  for (int i = 0; i < 5; ++i)
884  s[i] = idw->InterpToPt(ipts[i]);
885  vBase = {6.1976342f, 0.60451090f, -0.80145311f, 13.252287f, 0.0f};
886  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
887 }
888 //------------------------------------------------------------------------------
890 //------------------------------------------------------------------------------
892 {
893  BSHP<VecPt3d> pts(new VecPt3d());
894  VecPt3d ipts;
895  VecFlt scalar, s(5), vBase;
896  iGetPoints(*pts, scalar, ipts);
897  BSHP<InterpIdw> idw = InterpIdw::New();
898  idw->SetPts(pts, true);
899  idw->SetScalars(&scalar[0], scalar.size());
900  idw->SetWeightCalcMethod(InterpIdw::CLASSIC);
901  for (int i = 0; i < 5; ++i)
902  s[i] = idw->InterpToPt(ipts[i]);
903  vBase = {16.884138f, 15.516511f, 16.895596f, 14.160349f, 0.0f};
904  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
905  idw->SetPower(1);
906  for (int i = 0; i < 5; ++i)
907  s[i] = idw->InterpToPt(ipts[i]);
908  vBase = {21.907907f, 21.933628f, 22.670679f, 19.839111f, 0.0f};
909  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
910 } // InterpIdwUnitTests::testInterp2d_e
911 //------------------------------------------------------------------------------
913 //------------------------------------------------------------------------------
915 {
916  BSHP<VecPt3d> pts(new VecPt3d());
917  VecPt3d ipts;
918  VecFlt scalar, s(5), vBase;
919  iGetPoints(*pts, scalar, ipts);
920  BSHP<InterpIdw> idw = InterpIdw::New();
921  idw->SetPts(pts, true);
922  idw->SetScalars(&scalar[0], scalar.size());
923  idw->SetNodalFunction(InterpIdw::QUADRATIC, XM_NONE, true, NULL);
924  for (int i = 0; i < 5; ++i)
925  s[i] = idw->InterpToPt(ipts[i]);
926  vBase = {-46.129936f, -65.856499f, -71.997749f, -47.643417f, 0.0f};
927  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
928 } // InterpIdwUnitTests::testInterp2d_f
929 //------------------------------------------------------------------------------
931 //------------------------------------------------------------------------------
933 {
934  BSHP<VecPt3d> pts(new VecPt3d());
935  VecPt3d ipts;
936  VecFlt scalar, s(5), vBase;
937  iGetPoints(*pts, scalar, ipts);
938  BSHP<InterpIdw> idw = InterpIdw::New();
939  idw->SetPts(pts, false);
940  idw->SetScalars(&scalar[0], scalar.size());
941  idw->SetNodalFunction(InterpIdw::GRAD_PLANE, XM_NONE, true, NULL);
942  for (int i = 0; i < 5; ++i)
943  s[i] = idw->InterpToPt(ipts[i]);
944  vBase = {1.5025957e-008f, -7.7562149e-008f, 1.4442284e-007f, -6.1540938e-008f, 0.0f};
945  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
946  idw->SetNodalFunction(InterpIdw::QUADRATIC, XM_NONE, true, NULL);
947  for (int i = 0; i < 5; ++i)
948  s[i] = idw->InterpToPt(ipts[i]);
949  vBase = {5.2535050e-008f, -1.2138121e-007f, 4.1972626e-007f, -1.1271275e-007f, 0.0f};
950  TS_ASSERT_DELTA_VEC(vBase, s, 1e-7);
951 } // InterpIdwUnitTests::testInterp2d_f
952 //------------------------------------------------------------------------------
955 //------------------------------------------------------------------------------
957 {
958  BSHP<VecPt3d> pts(new VecPt3d());
959  VecPt3d ipts;
960  VecFlt scalar, s(5), vBase;
961  *pts = {{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0}};
962  scalar.assign(pts->size(), 0);
963  ipts.assign(5, Pt3d(-1, 0, 0));
964 
966  InterpIdwImpl idw;
967  idw.SetPts(pts, false);
968  idw.SetScalars(&scalar[0], scalar.size());
969  idw.SetNodalFunction(InterpIdw::QUADRATIC, 1, true, NULL);
970  // no nodal function created on previous line because all scalars are equal
971 
972  idw.CreateNodalFunctionPtr(InterpIdw::QUADRATIC, 1, true, NULL);
973  TS_ASSERT_EQUALS(true, (XmLog::Instance().ErrCount() != 0));
975 } // InterpIdwUnitTests::testErrors
976 //------------------------------------------------------------------------------
978 //------------------------------------------------------------------------------
980 {
981  BSHP<VecPt3d> pts(new VecPt3d());
982  VecPt3d ipts;
983  VecFlt scalar, s(5), vBase;
984  *pts = {{0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {3, 0, 0}};
985  scalar.assign(pts->size(), 0);
986  ipts.assign(5, Pt3d(-1, 0, 0));
987 
989  InterpIdwImpl idw;
990  idw.SetPts(pts, true);
991  idw.SetScalars(&scalar[0], scalar.size());
992  idw.SetNodalFunction(InterpIdw::GRAD_PLANE, 2, true, NULL);
993  // no nodal function created on previous line because all scalars are equal
994 
995  idw.CreateNodalFunctionPtr(InterpIdw::GRAD_PLANE, 2, true, NULL);
996  for (int i = 0; i < 5; ++i)
997  s[i] = idw.InterpToPt(ipts[i]);
998  TS_ASSERT_EQUALS(true, (XmLog::Instance().ErrCount() != 0));
1000 } // InterpIdwUnitTests::testErrors
1001 
1002 //} // namespace xms
1003 #endif // CXX_TEST
virtual bool GetSearchOptsUseQuadrantSearch() const override
get the search options option to do a quadrant or octant search
Definition: InterpIdw.cpp:124
BSHP< VecFlt > m_scalarFrom
Scalars at the points used to interpolate.
Definition: InterpIdw.cpp:211
BSHP< VecPt3d > m_pts
Points used to interpolate.
Definition: InterpIdw.cpp:209
virtual float InterpToPt(const Pt3d &a_pt) override
Interpolates to the location specified by a_pt and returns the value.
Definition: InterpIdw.cpp:427
void testInterp2d_b()
tests 2d interpolation using all idw points
Definition: InterpIdw.cpp:832
std::vector< int > VecInt
double m_truncMin
Minimum truncation value. All interpolated values will be >=.
Definition: InterpIdw.cpp:219
Threading class to compute idw interpolation in parallel.
Definition: InterpIdw.cpp:51
double ScalarFromNodalFunc(int a_ptIdx, const Pt3d &a_loc) const
Returns a scalar value based on the nodal function. When nodal functions are used then the scalar val...
Definition: InterpIdw.cpp:733
void testInterp2d_e()
tests 2d interpolation using classic weighting, exponent set to 1
Definition: InterpIdw.cpp:891
virtual const BSHP< VecInt > GetTris() const override
Returns shared pointer to triangles vector.
Definition: InterpIdw.cpp:521
#define XM_NONE
InterpIdwImpl & m_interp
Idw interpolation class.
Definition: InterpIdw.cpp:65
BSHP< GmPtSearch > m_ptSearch
Class used to find nearest points.
Definition: InterpIdw.cpp:208
#define XM_ENSURE_FALSE(...)
Signals that can be called when performing idw or kriging interpolation. Used by GMS with Pilot Point...
void testInterp3d()
test 3d interpolation
Definition: InterpIdw.cpp:932
std::vector< double > VecDbl
virtual void SetTrunc(double a_sMax, double a_sMin) override
Set the truncation values for the interpolation and turn on truncation.
Definition: InterpIdw.cpp:557
virtual int GetSearchOptsNumNearestPts() const override
get the search options number of nearest points
Definition: InterpIdw.cpp:121
virtual DynBitset GetTriActivity() const override
Returns empty bitset. No triangles used for idw.
Definition: InterpIdw.cpp:547
std::vector< float > VecFlt
static BSHP< NodalFunc > New(int a_type, bool a_2d, boost::shared_ptr< GmPtSearch > a_ptSearch, const std::vector< Pt3d > &a_pts, const std::vector< float > &a_scalar, int a_nNearest, bool a_quad_oct, double a_power, bool a_modifiedShepardWeights, boost::shared_ptr< Observer > a_p, InterpNatNeigh *a_natNeigh)
Creates a NodalFunc class.
Definition: NodalFunc.cpp:188
void SetWeightCalcMethod(InterpIdw::WeightEnum a_) override
Sets the method for calculating the weights. The classic just uses 1/distance^exponent. The modified method uses another formulation based on the distance of the furtherest location from the interpolation pt.
Definition: InterpIdw.cpp:676
virtual bool GetTruncateInterpolatedValues() const override
get the option to truncate interpolated values
Definition: InterpIdw.cpp:109
bool m_trunc
flag to indicate if truncation is on
Definition: InterpIdw.cpp:217
int CurrIdx()
Returns the current index of the thread.
Definition: ThreadLoop.cpp:89
static BSHP< InterpIdw > New()
Creates an InterpIdw class.
Definition: InterpIdw.cpp:284
bool m_saveWeights
flag for saving the interpolation weights
Definition: InterpIdw.cpp:214
void testInterp2d_a()
tests 2d interpolation
Definition: InterpIdw.cpp:813
void testInterp2d_f()
test 2d interpolation with a quadratic nodal function
Definition: InterpIdw.cpp:914
Class that performs inverse distance weighted interpolation.
Definition: InterpIdw.h:28
void testCreateClass()
Creates a class.
Definition: InterpIdw.cpp:786
void SetNodalFunction(NodalFuncEnum a_, int a_nNearest, bool a_quad_oct, BSHP< Observer > a_p) override
Sets the type of nodal function as well as options for computing nodal functions. ...
Definition: InterpIdw.cpp:696
BSHP< NodalFunc > m_nodalFunc
Nodal function (constant, gradient plane, quadratic)
Definition: InterpIdw.cpp:212
void VecToStream(std::stringstream &a_ss, const T &a_v, std::string a_label)
virtual ~InterpIdw()
Destructor.
Definition: InterpIdw.cpp:298
virtual void SetPts(BSHP< VecPt3d > a_pts, bool a_2d) override
Sets the points that will be used to do the interpolation.
Definition: InterpIdw.cpp:350
InterpIdwImpl()
Creates an InterpIdw class.
Definition: InterpIdw.cpp:310
void testErrors()
test error reporting. Errors can be generated by the nodal function setup process.
Definition: InterpIdw.cpp:956
virtual const BSHP< VecPt3d > GetPts() const override
Returns shared pointer to points vector.
Definition: InterpIdw.cpp:513
void SetObserver(BSHP< Observer > a_prog) override
Set the observer class so that feedback on the interpolation process can be received.
Definition: InterpIdw.cpp:180
virtual void SetPtsTris(BSHP< VecPt3d > a_pts, BSHP< VecInt > a_tris) override
Sets the points that will be used to do the interpolation.
Definition: InterpIdw.cpp:340
virtual void SetSaveWeights(bool a_) override
sets a flag to save the weights computed by the interpolation
Definition: InterpIdw.cpp:161
boost::dynamic_bitset< size_t > DynBitset
std::vector< VecInt > VecInt2d
const VecPt3d & m_pts
Pts being interpolated to.
Definition: InterpIdw.cpp:67
InterpIdw()
Constructor.
Definition: InterpIdw.cpp:292
void testErrors2()
test error reporting.
Definition: InterpIdw.cpp:979
void RecalcNodalFunc()
Recalculates the nodal function. This happens when the scalars change.
Definition: InterpIdw.cpp:401
virtual double GetTruncMax() const override
get the maximum truncation value
Definition: InterpIdw.cpp:115
VecDbl2d m_weights
calculated weights for saving weights
Definition: InterpIdw.cpp:216
virtual void InterpWeights(const Pt3d &a_pt, VecInt &a_idx, VecDbl &a_wt) const override
Given a location and an array of points the weights associated with array of points are calculated...
Definition: InterpIdw.cpp:571
void SetSearchOpts(int a_nNearestPoints, bool a_quad_oct_Search) override
Sets the search options for how to find the nearest points to the interpolation point. The number of nearest points can be specified as well as whether to find the nearest points in each quadrant or octant.
Definition: InterpIdw.cpp:417
void SetPower(double a_power) override
Sets the exponent for the interpolation. By default the class does inverse distance squared weighting...
Definition: InterpIdw.cpp:393
std::string GetAndClearStackStr()
#define XM_ENSURE_TRUE(...)
virtual WeightEnum GetWeightCalcMethod() const override
get the weight calculation method
Definition: InterpIdw.cpp:127
void Worker() override
Actually does the interpolation in a thread.
Definition: InterpIdw.cpp:80
Thread worker class.
Definition: ThreadLoop.h:23
void inSetDataIndex(int val)
Calls the SetDataIndex signal.
static BSHP< ThreadMgr > New()
Creates a ThreadMgr.
Definition: ThreadMgr.cpp:105
void ValFromWeights(VecDbl &a_w, VecInt &a_nPts, float &a_val, int a_ptIdx, const Pt3d &a_pt) const
Given a vector of weights, the interpolated value a_val is computed at the point a_pt.
Definition: InterpIdw.cpp:652
virtual void SetTriActivity(DynBitset &) override
Sets triangle activity. Ignored by IDW.
Definition: InterpIdw.cpp:99
#define XM_ENSURE_TRUE_VOID_NO_ASSERT(...)
VecFlt & m_scalarTo
Scalars filled by this class.
Definition: InterpIdw.cpp:66
Implementation of InterpIdw class.
Definition: InterpIdw.cpp:47
virtual void SetMultiThreading(bool a_) override
sets a flag to use (or not) multi-threading when interpolating
Definition: InterpIdw.cpp:169
void testInterp2d_c()
tests 2d interpolation using nearest 5 points
Definition: InterpIdw.cpp:850
virtual void SetPtActivity(DynBitset &a_activity) override
Sets the activity on the point being used to interpolate.
Definition: InterpIdw.cpp:505
void CreateNodalFunctionPtr(NodalFuncEnum a_, int a_nNearest, bool a_quad_oct, BSHP< Observer > a_p)
Creates the Nodal function class.
Definition: InterpIdw.cpp:716
virtual const BSHP< VecFlt > GetScalars() const override
Returns shared pointer to scalars vector.
Definition: InterpIdw.cpp:529
WeightEnum
Weight calculation method enumeration.
Definition: InterpIdw.h:35
void testInterp2d_d()
tests 2d interpolation changing the exponent to 3 and nearest 6 pts
Definition: InterpIdw.cpp:871
virtual int GetNodalFunctionNumNearestPts() const override
get the nodal function number of nearest points
Definition: InterpIdw.cpp:143
Utility functions called by interpolation code.
bool m_multiThread
flag to indicate if multithreading should be used when interpolating
Definition: InterpIdw.cpp:220
void inDistanceSquared(const Pt3d &a_pt, const std::vector< int > &a_ptIdxs, const std::vector< Pt3d > &a_ptLoc, bool a_2d, std::vector< double > &a_d2)
Computes the distance squared between the point "a_pt" and the other points. The other points are def...
Definition: InterpUtil.cpp:266
BSHP< ThreadLoop > CreateForNewThread() override
creates an instance of this class for a new thread
Definition: InterpIdw.cpp:71
virtual NodalFuncEnum GetNodalFunctionType() const override
get the type of nodal function (constant, gradient plane, quadratic)
Definition: InterpIdw.cpp:135
InterpThread(InterpIdwImpl &a_, VecFlt &a_s, const VecPt3d &a_p)
constructor
Definition: InterpIdw.cpp:58
NodalFuncEnum
Nodal fuction type enumeration.
Definition: InterpIdw.h:37
std::string m_idString
identification for comparison with other Interp classes
Definition: InterpIdw.cpp:221
virtual double GetTruncMin() const override
get minimum truncation value
Definition: InterpIdw.cpp:112
BSHP< Observer > m_prog
Observer that reports status of interpolation process.
Definition: InterpIdw.cpp:213
std::vector< VecDbl > VecDbl2d
void testInterpToPts()
tests interpolating to 1 location from 1 location
Definition: InterpIdw.cpp:794
BSHP< VecInt > m_tris
triangles ignored by idw
Definition: InterpIdw.cpp:210
virtual bool GetNodalFunctionUseQuadrantSearch() const override
get the nodal function option to use a quadrant search
Definition: InterpIdw.cpp:151
virtual std::string ToString() const override
Write the internals to a string.
Definition: InterpIdw.cpp:605
VecInt2d m_ptIdx
pt indexes for saving weights
Definition: InterpIdw.cpp:215
static XmLog & Instance(bool a_delete=false, XmLog *a_new=NULL)
virtual void InterpToPts(const VecPt3d &a_pts, VecFlt &a_scalars) override
Interpolates to an array of points and fills in an array of scalars. This method will run in parallel...
Definition: InterpIdw.cpp:472
void SetScalars(const float *a_scalar, size_t a_n) override
Sets the scalar values that will be used to do the interpolation.
Definition: InterpIdw.cpp:371
void inIdwWeights(const std::vector< double > &a_distSquare, double a_power, bool a_modifiedShepardWeights, std::vector< double > &a_w)
Computes the idw weights that would be assigned to points associated with the distance squared that i...
Definition: InterpUtil.cpp:305
static void iGetPoints(VecPt3d &a_pts, VecFlt &a_scalar, VecPt3d &a_iPts)
Get points for testing.
Definition: InterpIdw.cpp:761
double m_truncMax
Maximum truncation value. All interpolated values will be <=.
Definition: InterpIdw.cpp:218
virtual double GetPower() const override
get the idw power (1/d or 1/d^2 or 1/d^3)
Definition: InterpIdw.cpp:118
bool m_modifiedShepardWeights
flag for calculating weights using a the modified shepard&#39;s approach
Definition: InterpIdw.cpp:202
bool m_quadOctSearch
flag for performing quadrant(2d) or octant (3d) searching for nearest ps
Definition: InterpIdw.cpp:200
void inFillWtArray(int id, double wt)
calls the FillWtArray signal
virtual DynBitset GetPtActivity() const override
Returns bitset of point activity.
Definition: InterpIdw.cpp:537
#define TS_ASSERT_DELTA_VEC(a, b, delta)
bool inAllScalarsEqual(const std::vector< float > &a_scalars, const DynBitset &a_act)
Check to see if the all of the values in the scalars array are the same. It will also take into accou...
Definition: InterpUtil.cpp:363
std::vector< Pt3d > VecPt3d