xmsstamper  1.0
XmStampInterpCrossSection.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
14 
15 // 3. Standard library headers
16 #include <map>
17 
18 // 4. External library headers
19 
20 // 5. Shared code headers
21 #include <xmscore/math/math.h>
22 #include <xmscore/misc/XmError.h>
23 #include <xmscore/stl/set.h>
25 #include <xmscore/misc/Observer.h>
27 
28 // 6. Non-shared code headers
29 
30 //----- Forward declarations ---------------------------------------------------
31 
32 //----- External globals -------------------------------------------------------
33 
34 //----- Namespace declaration --------------------------------------------------
35 
36 namespace xms
37 {
38 //----- Constants / Enumerations -----------------------------------------------
39 
40 //----- Classes / Structs ------------------------------------------------------
41 
45 {
46 public:
49 
50  virtual void InterpMissingCrossSections(XmStamperIo& a_) override;
51  virtual bool ValidCrossSectionsExist(XmStamperIo& a_) override;
52  virtual void InterpCs(XmStampCrossSection& a_prev,
53  XmStampCrossSection& a_next,
54  double a_percent,
55  XmStampCrossSection& a_cs) override;
56 
57  BSHP<Observer> m_observer;
59 
62  int FindNextValidCrossSection(int a_idx);
63  void InterpCs(int a_prev, int a_next, double a_percent, XmStampCrossSection& a_cs);
64  void InterpPts(VecPt3d& a_v1,
65  int a_beg1,
66  int a_end1,
67  VecPt3d& a_v2,
68  int a_beg2,
69  int a_end2,
70  double a_percent,
71  VecPt3d& a_interpPts);
72  void CalcTvals(VecPt3d& a_v, int a_beg, int a_end, VecDbl& a_t);
73  Pt3d PtFromT(VecPt3d& a_v, int a_beg, VecDbl& a_t, double a_tval);
74 };
75 
81 //------------------------------------------------------------------------------
83 //------------------------------------------------------------------------------
84 XmStampInterpCrossSectionImpl::XmStampInterpCrossSectionImpl()
85 : m_observer()
86 , m_io(nullptr)
87 {
88 } // XmStampInterpCrossSectionImpl::XmStampInterpCrossSectionImpl
89 //------------------------------------------------------------------------------
91 //------------------------------------------------------------------------------
92 XmStampInterpCrossSectionImpl::~XmStampInterpCrossSectionImpl()
93 {
94 } // XmStampInterpCrossSectionImpl::~XmStampInterpCrossSectionImpl
95 //------------------------------------------------------------------------------
99 //------------------------------------------------------------------------------
101 {
102  m_io = &a_;
103 
104  // make sure shoulder index is not 0 on any cross section
105  for (size_t i = 0; i < m_io->m_cs.size(); ++i)
106  {
107  auto& cs(m_io->m_cs[i]);
108  if (cs.m_left.size() > 1 || cs.m_right.size() > 1)
109  {
110  if (cs.m_idxLeftShoulder < 1)
111  cs.m_idxLeftShoulder = 1;
112  if (cs.m_idxRightShoulder < 1)
113  cs.m_idxRightShoulder = 1;
114  }
115  }
116 
117  int first = FindFirstValidCrossSection();
118  // copy this cross section to any before it
119  for (int i = 0; i < first; ++i)
120  {
121  m_io->m_cs[i] = m_io->m_cs[first];
122  }
123  int last = FindLastValidCrossSection();
124  // copy this cross section to any after it
125  for (size_t i = (size_t)(last + 1); last > 0 && i < m_io->m_cs.size(); ++i)
126  {
127  m_io->m_cs[i] = m_io->m_cs[last];
128  }
129  // loop between first and last to fill in the cross sections
130  const VecPt3d& pts(m_io->m_centerLine);
131  int prev = first, next;
132  double prevDist, nextDist, percent;
133  for (int i = first + 1; i < last; ++i)
134  {
135  auto& cs(m_io->m_cs[i]);
136  if (cs.m_left.size() > 1 || cs.m_right.size() > 1)
137  {
138  prev = i;
139  continue;
140  }
141 
142  // get the next valid cross section
143  next = FindNextValidCrossSection(i);
144  // get distance between current and previous
145  prevDist = gmXyDistance(pts[prev], pts[i]);
146  // get distance between current and next
147  nextDist = gmXyDistance(pts[i], pts[next]);
148  percent = prevDist / (prevDist + nextDist);
149  // interpolate the cross section
150  InterpCs(prev, next, percent, cs);
151  }
152 } // XmStampInterpCrossSectionImpl::InterpMissingCrossSections
153 //------------------------------------------------------------------------------
158 //------------------------------------------------------------------------------
160 {
161  m_io = &a_;
162  if (FindFirstValidCrossSection() > -1)
163  return true;
164  return false;
165 } // XmStampInterpCrossSectionImpl::InterpMissingCrossSections
166 //------------------------------------------------------------------------------
170 //------------------------------------------------------------------------------
172 {
173  return FindNextValidCrossSection(-1);
174 } // XmStampInterpCrossSectionImpl::FindFirstValidCrossSection
175 //------------------------------------------------------------------------------
179 //------------------------------------------------------------------------------
181 {
182  int csIdx(-1);
183  for (size_t i = m_io->m_cs.size(); csIdx == -1 && i > 0; --i)
184  {
185  const auto& cs(m_io->m_cs[i - 1]);
186  if (cs.m_left.size() > 1 || cs.m_right.size() > 1)
187  {
188  csIdx = static_cast<int>(i - 1);
189  }
190  }
191  return csIdx;
192 } // XmStampInterpCrossSectionImpl::FindLastValidCrossSection
193 //------------------------------------------------------------------------------
198 //------------------------------------------------------------------------------
200 {
201  int csIdx(-1);
202  size_t start(0);
203  if (a_idx > 0)
204  start = a_idx + 1;
205  for (size_t i = start; csIdx == -1 && i < m_io->m_cs.size(); ++i)
206  {
207  const auto& cs(m_io->m_cs[i]);
208  if (cs.m_left.size() > 1 || cs.m_right.size() > 1)
209  {
210  csIdx = static_cast<int>(i);
211  }
212  }
213  return csIdx;
214 } // XmStampInterpCrossSectionImpl::FindNextValidCrossSection
215 //------------------------------------------------------------------------------
223 //------------------------------------------------------------------------------
225  int a_next,
226  double a_percent,
227  XmStampCrossSection& a_cs)
228 {
229  XmStampCrossSection &pCs(m_io->m_cs[a_prev]), &nCs(m_io->m_cs[a_next]);
230  InterpCs(pCs, nCs, a_percent, a_cs);
231 } // XmStampInterpCrossSectionImpl::InterpCs
232 //------------------------------------------------------------------------------
240 //------------------------------------------------------------------------------
242  XmStampCrossSection& a_next,
243  double a_percent,
244  XmStampCrossSection& a_cs)
245 {
246  XmStampCrossSection &pCs(a_prev), &nCs(a_next);
247  XM_ENSURE_TRUE(!pCs.m_left.empty() || !pCs.m_right.empty());
248  XM_ENSURE_TRUE(!nCs.m_left.empty() || !nCs.m_right.empty());
249  // get the interpolated center line location because the Interp pts
250  // method will not do the t = 0 location
251  Pt3d pt, p1, p2;
252  if (!pCs.m_left.empty())
253  p1 = pCs.m_left[0];
254  else if (!pCs.m_right.empty())
255  p1 = pCs.m_right[0];
256  if (!nCs.m_left.empty())
257  p2 = nCs.m_left[0];
258  else if (!nCs.m_right.empty())
259  p2 = nCs.m_right[0];
260  pt.x = p1.x - (a_percent * (p1.x - p2.x));
261  pt.y = p1.y - (a_percent * (p1.y - p2.y));
262  a_cs.m_left.assign(1, pt);
263  a_cs.m_right.assign(1, pt);
264 
265  // Left side interpolation
266  VecPt3d &l1(pCs.m_left), &l2(nCs.m_left), &l3(a_cs.m_left);
267  int ls1(pCs.m_idxLeftShoulder), ls2(nCs.m_idxLeftShoulder);
268  // interpolate points between the center line and the left shoulder
269  InterpPts(l1, 0, ls1, l2, 0, ls2, a_percent, l3);
270  a_cs.m_idxLeftShoulder = std::max(0, (int)l3.size() - 1);
271  // interpolate points between left shoulder and end
272  int lend1((int)pCs.m_left.size() - 1), lend2((int)nCs.m_left.size() - 1);
273  InterpPts(l1, ls1, lend1, l2, ls2, lend2, a_percent, l3);
274  // interpolate max dist
275  a_cs.m_leftMax = a_prev.m_leftMax - (a_percent * (a_prev.m_leftMax - a_next.m_leftMax));
276 
277  // Right side interpolation
278  VecPt3d &r1(pCs.m_right), &r2(nCs.m_right), &r3(a_cs.m_right);
279  int rs1(pCs.m_idxRightShoulder), rs2(nCs.m_idxRightShoulder);
280  // interpolate points between the center line and the left shoulder
281  InterpPts(r1, 0, rs1, r2, 0, rs2, a_percent, r3);
282  a_cs.m_idxRightShoulder = std::max(0, (int)r3.size() - 1);
283  // interpolate points between left shoulder and end
284  int rend1((int)pCs.m_right.size() - 1), rend2((int)nCs.m_right.size() - 1);
285  InterpPts(r1, rs1, rend1, r2, rs2, rend2, a_percent, r3);
286  // interpolate max dist
287  a_cs.m_rightMax = a_prev.m_rightMax - (a_percent * (a_prev.m_rightMax - a_next.m_rightMax));
288 } // XmStampInterpCrossSectionImpl::InterpCs
289 //------------------------------------------------------------------------------
303 //------------------------------------------------------------------------------
305  int a_beg1,
306  int a_end1,
307  VecPt3d& a_v2,
308  int a_beg2,
309  int a_end2,
310  double a_percent,
311  VecPt3d& a_interpPts)
312 {
313  VecDbl t1, t2;
314  CalcTvals(a_v1, a_beg1, a_end1, t1);
315  CalcTvals(a_v2, a_beg2, a_end2, t2);
316  // get a union of t values
317  SetDbl tvals(t1.begin(), t1.end());
318  tvals.insert(t2.begin(), t2.end());
319 
320  Pt3d p1, p2, pt;
321  tvals.erase(0.0);
322  for (const auto& t : tvals)
323  {
324  p1 = PtFromT(a_v1, a_beg1, t1, t);
325  p2 = PtFromT(a_v2, a_beg2, t2, t);
326  pt.x = p1.x - (a_percent * (p1.x - p2.x));
327  pt.y = p1.y - (a_percent * (p1.y - p2.y));
328  a_interpPts.push_back(pt);
329  }
330 
331 } // XmStampInterpCrossSectionImpl::InterpPts
332 //------------------------------------------------------------------------------
338 //------------------------------------------------------------------------------
339 void XmStampInterpCrossSectionImpl::CalcTvals(VecPt3d& a_v, int a_beg, int a_end, VecDbl& a_t)
340 {
341  if (a_v.empty())
342  return;
343  a_t.assign(1, 0);
344  // calculate parametric t values for each x value
345  double diff = a_v[a_end].x - a_v[a_beg].x;
346  for (int i = a_beg + 1; i <= a_end; ++i)
347  {
348  double t = (a_v[i].x - a_v[a_beg].x) / diff;
349  a_t.push_back(t);
350  }
351 } // XmStampInterpCrossSectionImpl::CalcTvals
352 //------------------------------------------------------------------------------
359 //------------------------------------------------------------------------------
360 Pt3d XmStampInterpCrossSectionImpl::PtFromT(VecPt3d& a_v, int a_beg, VecDbl& a_t, double a_tval)
361 {
362  if (a_v.empty())
363  return Pt3d();
364  if (a_t.size() == 1 && a_t[0] == 0.0)
365  return a_v[0];
366 
367  Pt3d r, p1, p2;
368  double t1(-1), t2(-1);
369  int idx(-1);
370  // find where t is
371  for (size_t i = 1; idx < 0 && i < a_t.size(); ++i)
372  {
373  if (a_tval < a_t[i])
374  {
375  idx = static_cast<int>(i) - 1;
376  p1 = a_v[a_beg + idx];
377  p2 = a_v[a_beg + idx + 1];
378  t1 = a_t[idx];
379  t2 = a_t[idx + 1];
380  }
381  else if (a_tval == a_t[i])
382  {
383  idx = static_cast<int>(i);
384  p1 = a_v[a_beg + idx];
385  t1 = a_t[idx];
386  }
387  }
388  // interpolate to t
389  if (a_tval == t1)
390  return p1;
391  double localt = (a_tval - t1) / (t2 - t1);
392  r.x = p1.x + localt * (p2.x - p1.x);
393  r.y = p1.y + localt * (p2.y - p1.y);
394  return r;
395 } // XmStampInterpCrossSectionImpl::PtFromT
396 
397 //------------------------------------------------------------------------------
400 //------------------------------------------------------------------------------
401 BSHP<XmStampInterpCrossSection> XmStampInterpCrossSection::New()
402 {
403  BSHP<XmStampInterpCrossSection> interp(new XmStampInterpCrossSectionImpl);
404  return interp;
405 } // XmStampInterpCrossSection::New
406 //------------------------------------------------------------------------------
408 //------------------------------------------------------------------------------
409 XmStampInterpCrossSection::XmStampInterpCrossSection()
410 {
411 } // XmStampInterpCrossSection::XmStamperXmStampInterpCrossSection
412 //------------------------------------------------------------------------------
414 //------------------------------------------------------------------------------
415 XmStampInterpCrossSection::~XmStampInterpCrossSection()
416 {
417 } // XmStampInterpCrossSection::~XmStampInterpCrossSection
418 
419 } // namespace xms
420 
421 #ifdef CXX_TEST
422 //------------------------------------------------------------------------------
423 // Unit Tests
424 //------------------------------------------------------------------------------
425 using namespace xms;
427 
429 
430 //------------------------------------------------------------------------------
432 //------------------------------------------------------------------------------
434 {
435  XmStamperIo io;
436  io.m_centerLine = {{0, 0}, {5, 0}, {10, 0}, {15, 0}, {20, 0}, {25, 0}};
437  io.m_cs.assign(6, XmStampCrossSection());
438 
439  // should fail because there are no valid cross sections
442  for (auto& c : io.m_cs)
443  {
444  TS_ASSERT(c.m_left.empty());
445  TS_ASSERT(c.m_right.empty());
446  TS_ASSERT(c.m_idxLeftShoulder == 0);
447  TS_ASSERT(c.m_idxRightShoulder == 0);
448  TS_ASSERT(c.m_leftMax == 0);
449  TS_ASSERT(c.m_rightMax == 0);
450  }
451 
452  XmStampCrossSection cs, cs1;
453  io.m_stampingType = 0;
454 
455  cs.m_left = {{0, 10}, {1, 11}, {2, 12}, {4, 11}, {5, 10}, {10, 5}, {15, 0}};
456  cs.m_idxLeftShoulder = 4;
457  cs.m_leftMax = 16;
458  cs.m_right = cs.m_left;
460  cs.m_rightMax = cs.m_leftMax;
461  io.m_cs[1] = cs;
462 
463  cs1.m_left = {{0, 20}, {4, 19}, {6, 18}, {8, 18}, {10, 20}, {15, 15}, {20, 10}};
464  cs1.m_leftMax = 19;
465  cs1.m_idxLeftShoulder = 4;
466  cs1.m_right = cs1.m_left;
468  cs1.m_rightMax = cs1.m_leftMax;
469  io.m_cs[4] = cs1;
470 
472  // values copied from cs[1]
473  TS_ASSERT_EQUALS_VEC(io.m_cs[1].m_left, io.m_cs[0].m_left);
474  TS_ASSERT_EQUALS(io.m_cs[1].m_idxLeftShoulder, io.m_cs[0].m_idxLeftShoulder);
475  TS_ASSERT_EQUALS(io.m_cs[1].m_leftMax, io.m_cs[0].m_leftMax);
476  TS_ASSERT_EQUALS(io.m_cs[1].m_rightMax, io.m_cs[0].m_rightMax);
477  TS_ASSERT_EQUALS_VEC(io.m_cs[1].m_right, io.m_cs[0].m_right);
478  TS_ASSERT_EQUALS(4, io.m_cs[0].m_idxRightShoulder);
479  // values copied from cs[4]
480  TS_ASSERT_EQUALS_VEC(io.m_cs[4].m_left, io.m_cs[5].m_left);
481  TS_ASSERT_EQUALS(io.m_cs[4].m_idxLeftShoulder, io.m_cs[5].m_idxLeftShoulder);
482  TS_ASSERT_EQUALS(io.m_cs[4].m_leftMax, io.m_cs[5].m_leftMax);
483  TS_ASSERT_EQUALS(io.m_cs[4].m_rightMax, io.m_cs[5].m_rightMax);
484  TS_ASSERT_EQUALS_VEC(io.m_cs[4].m_right, io.m_cs[5].m_right);
485  TS_ASSERT_EQUALS(io.m_cs[4].m_idxRightShoulder, io.m_cs[5].m_idxRightShoulder);
486  VecPt3d baseCs = {{0.00, 13.33}, {1.33, 13.83}, {2.67, 14.33}, {4.0, 13.67},
487  {5.33, 13.33}, {6.67, 13.33}, {11.67, 8.33}, {16.67, 3.33}};
488  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_left, 1e-2);
489  TS_ASSERT_EQUALS(5, io.m_cs[2].m_idxLeftShoulder);
490  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_right, 1e-2);
491  TS_ASSERT_EQUALS(5, io.m_cs[2].m_idxRightShoulder);
492  VecPt3d baseCs1 = {{0, 16.67}, {1.67, 16.67}, {3.33, 16.67}, {5.0, 15.83},
493  {6.67, 15.67}, {8.33, 16.67}, {13.33, 11.67}, {18.33, 6.67}};
494  TS_ASSERT_DELTA_VECPT2D(baseCs1, io.m_cs[3].m_left, 1e-2);
495  TS_ASSERT_EQUALS(5, io.m_cs[3].m_idxLeftShoulder);
496  TS_ASSERT_DELTA_VECPT2D(baseCs1, io.m_cs[3].m_right, 1e-2);
497  TS_ASSERT_EQUALS(5, io.m_cs[3].m_idxRightShoulder);
498 
499  cs.m_idxLeftShoulder = 0;
500  cs.m_left.clear();
501  cs.m_leftMax = 0;
502  io.m_cs.assign(6, XmStampCrossSection());
503  io.m_cs[1] = cs;
504  io.m_cs[4] = cs1;
506 
507  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_right, 1e-2);
508  TS_ASSERT_EQUALS(5, io.m_cs[2].m_idxRightShoulder);
509  baseCs = {{0, 13.33}, {1.33, 6.33}, {2, 6}, {2.67, 6}, {3.33, 6.67}, {5, 5}, {6.67, 3.33}};
510  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_left, 1e-2);
511  TS_ASSERT_DELTA(6.33, io.m_cs[2].m_leftMax, 1e-2);
512 
513  TS_ASSERT_DELTA_VECPT2D(baseCs1, io.m_cs[3].m_right, 1e-2);
514  TS_ASSERT_EQUALS(5, io.m_cs[3].m_idxRightShoulder);
515  baseCs1 = {{0, 16.67}, {2.67, 12.67}, {4, 12}, {5.33, 12},
516  {6.67, 13.33}, {10, 10}, {13.33, 6.67}};
517  TS_ASSERT_DELTA_VECPT2D(baseCs1, io.m_cs[3].m_left, 1e-2);
518  TS_ASSERT_DELTA(12.66, io.m_cs[3].m_leftMax, 1e-2);
519 
520 } // XmStampInterpCrossSectionUnitTests::test0
522 //------------------------------------------------------------------------------
524 //------------------------------------------------------------------------------
526 {
527  XmStamperIo io;
528  io.m_centerLine = {{0, 0}, {5, 0}, {10, 0}, {15, 0}, {20, 0}, {25, 0}};
529  io.m_cs.assign(6, XmStampCrossSection());
531  io.m_stampingType = 0;
532  cs.m_left = {{0, 10}, {1, 11}, {2, 12}, {4, 11}, {5, 10}, {10, 5}, {15, 0}};
533  cs.m_idxLeftShoulder = 0;
534  cs.m_right = cs.m_left;
536  io.m_cs[1] = cs;
537  cs.m_left = {{0, 20}, {4, 19}, {6, 18}, {8, 18}, {10, 20}, {15, 15}, {20, 10}};
538  cs.m_idxLeftShoulder = 4;
539  cs.m_right = cs.m_left;
541  io.m_cs[4] = cs;
542 
545  TS_ASSERT_EQUALS_VEC(io.m_cs[1].m_left, io.m_cs[0].m_left);
546  TS_ASSERT_EQUALS(1, io.m_cs[0].m_idxLeftShoulder);
547  TS_ASSERT_EQUALS_VEC(io.m_cs[1].m_right, io.m_cs[0].m_right);
548  TS_ASSERT_EQUALS(1, io.m_cs[0].m_idxRightShoulder);
549  TS_ASSERT_EQUALS_VEC(io.m_cs[4].m_left, io.m_cs[5].m_left);
550  TS_ASSERT_EQUALS(4, io.m_cs[5].m_idxLeftShoulder);
551  TS_ASSERT_EQUALS_VEC(io.m_cs[4].m_right, io.m_cs[5].m_right);
552  TS_ASSERT_EQUALS(4, io.m_cs[5].m_idxRightShoulder);
553  VecPt3d baseCs = {{0.00, 13.33}, {1.60, 13.27}, {2.40, 13.07}, {3.20, 13.20},
554  {4.00, 14.00}, {4.90, 14.43}, {6.71, 13.29}, {7.62, 12.38},
555  {10.33, 9.67}, {12.14, 7.86}, {16.67, 3.33}};
556  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_left, 1e-2);
557  TS_ASSERT_EQUALS(4, io.m_cs[2].m_idxLeftShoulder);
558  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_right, 1e-2);
559  TS_ASSERT_EQUALS(4, io.m_cs[2].m_idxRightShoulder);
560  baseCs = {{0.00, 16.67}, {2.80, 16.13}, {4.20, 15.53}, {5.60, 15.60},
561  {7.00, 17.00}, {7.81, 16.86}, {9.43, 15.57}, {10.24, 14.76},
562  {12.67, 12.33}, {14.29, 10.71}, {18.33, 6.67}};
563  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[3].m_left, 1e-2);
564  TS_ASSERT_EQUALS(4, io.m_cs[3].m_idxLeftShoulder);
565  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[3].m_right, 1e-2);
566  TS_ASSERT_EQUALS(4, io.m_cs[3].m_idxRightShoulder);
567 } // XmStampInterpCrossSectionUnitTests::test0
569 //------------------------------------------------------------------------------
571 //------------------------------------------------------------------------------
574 {
575  XmStamperIo io;
576  io.m_centerLine = {{0, 0}, {5, 0}, {10, 0}, {15, 0}, {20, 0}, {25, 0}};
577  io.m_cs.assign(6, XmStampCrossSection());
579  io.m_stampingType = 0;
580  cs.m_left = {{0, 10}, {1, 11}, {2, 12}, {4, 11}, {5, 10}, {10, 5}, {15, 0}};
581  cs.m_idxLeftShoulder = 2;
582  cs.m_right = cs.m_left;
584  io.m_cs[1] = cs;
585  cs.m_left = {{0, 20}, {4, 19}, {6, 18}, {8, 18}, {10, 20}, {15, 15}, {20, 10}};
586  cs.m_idxLeftShoulder = 3;
587  cs.m_right = cs.m_left;
589  io.m_cs[4] = cs;
590 
593 
594  TS_ASSERT_EQUALS(2, io.m_cs[0].m_idxLeftShoulder);
595  TS_ASSERT_EQUALS(2, io.m_cs[1].m_idxLeftShoulder);
596  TS_ASSERT_EQUALS(3, io.m_cs[2].m_idxLeftShoulder);
597  TS_ASSERT_EQUALS(3, io.m_cs[3].m_idxLeftShoulder);
598  TS_ASSERT_EQUALS(3, io.m_cs[4].m_idxLeftShoulder);
599  TS_ASSERT_EQUALS(3, io.m_cs[5].m_idxLeftShoulder);
600 
601  TS_ASSERT_EQUALS(2, io.m_cs[0].m_idxRightShoulder);
602  TS_ASSERT_EQUALS(2, io.m_cs[1].m_idxRightShoulder);
603  TS_ASSERT_EQUALS(3, io.m_cs[2].m_idxRightShoulder);
604  TS_ASSERT_EQUALS(3, io.m_cs[3].m_idxRightShoulder);
605  TS_ASSERT_EQUALS(3, io.m_cs[4].m_idxRightShoulder);
606  TS_ASSERT_EQUALS(3, io.m_cs[5].m_idxRightShoulder);
607 
608  TS_ASSERT_EQUALS_VEC(io.m_cs[1].m_left, io.m_cs[0].m_left);
609  TS_ASSERT_EQUALS_VEC(io.m_cs[1].m_right, io.m_cs[0].m_right);
610  TS_ASSERT_EQUALS_VEC(io.m_cs[4].m_left, io.m_cs[5].m_left);
611  TS_ASSERT_EQUALS_VEC(io.m_cs[4].m_right, io.m_cs[5].m_right);
612 
613  VecPt3d baseCs = {
614  {0.00, 13.33}, {2.00, 13.66}, {3.00, 13.66}, {4.00, 14.00}, {5.94, 13.94},
615  {6.11, 13.88}, {6.92, 13.07}, {11.38, 8.61}, {11.79, 8.20}, {16.66, 3.33},
616  };
617  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_left, 0.02);
618  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[2].m_right, 0.02);
619 
620  baseCs = {
621  {0.00, 16.66}, {3.00, 16.33}, {4.50, 15.83}, {6.00, 16.00}, {7.89, 16.89},
622  {8.05, 16.94}, {8.84, 16.15}, {13.19, 11.80}, {13.58, 11.41}, {18.33, 6.66},
623  };
624  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[3].m_left, 0.02);
625  TS_ASSERT_DELTA_VECPT2D(baseCs, io.m_cs[3].m_right, 0.02);
626 } // XmStampInterpCrossSectionUnitTests::testCrossSectionTutorial
628 
629 #endif
virtual bool ValidCrossSectionsExist(XmStamperIo &a_) override
Interpolates the missing cross sections. Modifys the m_cs member of the XmStamperIo class that is pas...
int FindLastValidCrossSection()
Finds the last valid cross section in the inputs.
int FindFirstValidCrossSection()
Finds the first valid cross section in the inputs.
static BSHP< XmStampInterpCrossSection > New()
Creates a XmStampInterpCrossSection class.
VecPt3d m_left
left side of the cross section
Definition: XmStamperIo.h:156
Implementaion of XmStampInterpCrossSection.
int m_idxRightShoulder
index to the shoulder point in the m_right vector
Definition: XmStamperIo.h:162
double gmXyDistance(double x1, double y1, double x2, double y2)
std::vector< double > VecDbl
Interpolate cross sections for stamping.
double m_leftMax
max x value for left side
Definition: XmStamperIo.h:157
XmStamperIo * m_io
pointer to the inputs to the stamp operation
void InterpPts(VecPt3d &a_v1, int a_beg1, int a_end1, VecPt3d &a_v2, int a_beg2, int a_end2, double a_percent, VecPt3d &a_interpPts)
Interpolates part of 2 cross sections to part of a new cross section. Separate interpolations are don...
std::set< double > SetDbl
void testCrossSectionTutorial()
[snip_test_Example_XmStamper_Test1]>
virtual void InterpCs(XmStampCrossSection &a_prev, XmStampCrossSection &a_next, double a_percent, XmStampCrossSection &a_cs) override
Interpolates a cross section from 2 other cross sections using a weight (a_percent) ...
void test0()
Tests symetric cross section interpolation.
#define TS_ASSERT_DELTA_VECPT2D(a, b, delta)
#define XM_ENSURE_TRUE(...)
double m_rightMax
max x value for right side
Definition: XmStamperIo.h:161
VecPt3d m_right
right side of the cross section
Definition: XmStamperIo.h:160
void CalcTvals(VecPt3d &a_v, int a_beg, int a_end, VecDbl &a_t)
Calculates parametric t values from a vector of x,y coords based on x.
Stamping inputs/outputs class.
Definition: XmStamperIo.h:171
int FindNextValidCrossSection(int a_idx)
Finds the first valid cross section after a_idx in the inputs.
Pt3d PtFromT(VecPt3d &a_v, int a_beg, VecDbl &a_t, double a_tval)
Calculates the x,y location of the point at a_tval.
virtual void InterpMissingCrossSections(XmStamperIo &a_) override
Interpolates the missing cross sections. Modifys the m_cs member of the XmStamperIo class that is pas...
void test1()
[snip_test_Example_XmStamper_Test1]
Cross section definition for stamping.
Definition: XmStamperIo.h:142
std::vector< XmStampCrossSection > m_cs
cross sections along the polyLine
Definition: XmStamperIo.h:193
#define TS_ASSERT_EQUALS_VEC(a, b)
BSHP< Observer > m_observer
progress observer
int m_stampingType
Stamping type 0 - Cut, 1 - Fill, 2 - Both.
Definition: XmStamperIo.h:191
std::vector< Pt3d > VecPt3d
VecPt3d m_centerLine
Definition: XmStamperIo.h:189