xmsstamper  1.0
XmStampEndCap.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 
17 // 4. External library headers
18 
19 // 5. Shared code headers
20 #include <xmscore/math/math.h>
21 #include <xmscore/misc/XmError.h>
22 //#include <xmscore/stl/set.h>
24 //#include <xmscore/misc/Observer.h>
25 #include <xmscore/misc/xmstype.h>
30 
31 // 6. Non-shared code headers
32 
33 //----- Forward declarations ---------------------------------------------------
34 
35 //----- External globals -------------------------------------------------------
36 
37 //----- Namespace declaration --------------------------------------------------
38 
39 namespace xms
40 {
41 //----- Constants / Enumerations -----------------------------------------------
42 
43 //----- Classes / Structs ------------------------------------------------------
44 
48 {
49 public:
52 
53  virtual void RotateEndCapCrossSections(XmStamperIo& a_io,
54  VecPt3d2d& a_left,
55  VecPt3d2d& a_right) override;
56  virtual void ConvertTo3dPts(XmStamperIo& a_io, XmStamper3dPts& a_3dpts) override;
57 
58  void AdjustCrossSection(bool a_first, XmStamperIo& a_cap, VecPt3d2d& a_left, VecPt3d2d& a_right);
59  void RotateCrossSection(double a_angle, Pt3d& a_cl, VecPt3d& a_cs);
60  void RotateCrossSectionForType(bool a_first,
61  Pt3d& a_clPt,
62  XmStamperEndCap& a_cap,
63  VecPt3d& a_left,
64  VecPt3d& a_right,
65  int a_leftShoulderIdx,
66  int a_rightShoulderIdx);
67  void GuidebankRotate(bool a_first,
68  Pt3d& a_clPt,
69  XmStamperEndCap& a_cap,
70  VecPt3d& a_left,
71  VecPt3d& a_right,
72  int a_leftShoulderIdx,
73  int a_rightShoulderIdx);
74  void SlopedAbutmentRotateShoulders(double a_capAngle, int a_shoulderIdx, VecPt3d& a_cs);
75  void WingWallRotate(bool a_first,
76  double a_capAngle,
77  double a_wwAngle,
78  int a_shoulderIdx,
79  VecPt3d& a_cs);
80  void EndCapTo3dPts(bool a_first, XmStamperIo& a_io, XmStamper3dPts& a_3dpts);
81  void GuidebankEndCapTo3dPts(bool a_first, XmStamperIo& a_io, XmStamper3dPts& a_3dpts);
82  void SlopedAbutmentEndCapTo3dPts(bool a_first, XmStamperIo& a_io, XmStamper3dPts& a_3dpts);
83 };
84 
89 //------------------------------------------------------------------------------
91 //------------------------------------------------------------------------------
92 XmStampEndCapImpl::XmStampEndCapImpl()
93 {
94 } // XmStampEndCapImpl::XmStampEndCapImpl
95 //------------------------------------------------------------------------------
97 //------------------------------------------------------------------------------
98 XmStampEndCapImpl::~XmStampEndCapImpl()
99 {
100 } // XmStampEndCapImpl::~XmStampEndCapImpl
101 //------------------------------------------------------------------------------
107 //------------------------------------------------------------------------------
109  VecPt3d2d& a_left,
110  VecPt3d2d& a_right)
111 {
112  bool firstEndCap(true), lastEndCap(false);
113  AdjustCrossSection(firstEndCap, a_io, a_left, a_right);
114  AdjustCrossSection(lastEndCap, a_io, a_left, a_right);
115 } // XmStampEndCapImpl::RotateEndCapCrossSections
116 //------------------------------------------------------------------------------
121 //------------------------------------------------------------------------------
123 {
124  bool firstEndCap(true), lastEndCap(false);
125  EndCapTo3dPts(firstEndCap, a_io, a_3dpts);
126  EndCapTo3dPts(lastEndCap, a_io, a_3dpts);
127 } // XmStampEndCapImpl::RotateEndCapCrossSections
128 //------------------------------------------------------------------------------
135 //------------------------------------------------------------------------------
137  XmStamperIo& a_io,
138  VecPt3d2d& a_left,
139  VecPt3d2d& a_right)
140 {
141  XmStamperEndCap* cap(nullptr);
142  int leftShoulderIdx(0), rightShoulderIdx(0);
143  VecPt3d *left(nullptr), *right(nullptr);
144  Pt3d clPt;
145  if (a_first)
146  {
147  cap = &a_io.m_firstEndCap;
148  left = &a_left[0];
149  leftShoulderIdx = a_io.m_cs[0].m_idxLeftShoulder;
150  right = &a_right[0];
151  rightShoulderIdx = a_io.m_cs[0].m_idxRightShoulder;
152  clPt = a_io.m_centerLine.front();
153  }
154  else
155  {
156  cap = &a_io.m_lastEndCap;
157  left = &a_left.back();
158  leftShoulderIdx = a_io.m_cs.back().m_idxLeftShoulder;
159  right = &a_right.back();
160  rightShoulderIdx = a_io.m_cs.back().m_idxRightShoulder;
161  clPt = a_io.m_centerLine.back();
162  }
163  RotateCrossSection(cap->m_angle, clPt, *left);
164  RotateCrossSection(cap->m_angle, clPt, *right);
165 
166  RotateCrossSectionForType(a_first, clPt, *cap, *left, *right, leftShoulderIdx, rightShoulderIdx);
167 } // XmStampEndCapImpl::AdjustCrossSection
168 //------------------------------------------------------------------------------
174 //------------------------------------------------------------------------------
175 void XmStampEndCapImpl::RotateCrossSection(double a_angle, Pt3d& a_clPt, VecPt3d& a_cs)
176 {
177  if (0.0 == a_angle || a_cs.empty())
178  return;
179 
180  Pt3d p0(a_clPt);
181 
182  double oldMag(0), oldAngle(0);
183  for (size_t i = 0; i < a_cs.size(); ++i)
184  {
185  Pt3d p1(a_cs[i]), p2(p1);
186  // calculate the angle and magnitude
187  p2.x = p1.x - p0.x;
188  p2.y = p1.y - p0.y;
189  gmComponentMagnitudes(&p2.x, &p2.y, &oldMag, &oldAngle, true);
190 
191  // new angle
192  double newAngle = oldAngle + a_angle;
193  // new magnitude
194  double newMag = oldMag / cos(a_angle * (XM_PI / 180.0));
195 
196  // calculate new x,y points
197  gmComponentMagnitudes(&p2.x, &p2.y, &newMag, &newAngle, false);
198  a_cs[i].x = p2.x + p0.x;
199  a_cs[i].y = p2.y + p0.y;
200  }
201 } // XmStampEndCapImpl::RotateCrossSection
202 //------------------------------------------------------------------------------
214 //------------------------------------------------------------------------------
216  Pt3d& a_clPt,
217  XmStamperEndCap& a_cap,
218  VecPt3d& a_left,
219  VecPt3d& a_right,
220  int a_leftShoulderIdx,
221  int a_rightShoulderIdx)
222 {
223  int t = a_cap.m_type;
224  XM_ENSURE_TRUE(0 == t || 1 == t || 2 == t);
225 
226  if (0 == a_cap.m_type) // guidebank
227  {
228  GuidebankRotate(a_first, a_clPt, a_cap, a_left, a_right, a_leftShoulderIdx, a_rightShoulderIdx);
229  }
230  else if (1 == a_cap.m_type) // sloped abutment
231  {
232  SlopedAbutmentRotateShoulders(a_cap.m_angle, a_leftShoulderIdx, a_left);
233  SlopedAbutmentRotateShoulders(a_cap.m_angle, a_rightShoulderIdx, a_right);
234  }
235  else
236  {
237  WingWallRotate(a_first, a_cap.m_angle, a_cap.m_wingWall.m_wingWallAngle, a_leftShoulderIdx,
238  a_left);
239  WingWallRotate(!a_first, a_cap.m_angle, a_cap.m_wingWall.m_wingWallAngle, a_rightShoulderIdx,
240  a_right);
241  }
242 } // XmStampEndCapImpl::RotateCrossSection
243 //------------------------------------------------------------------------------
255 //------------------------------------------------------------------------------
257  Pt3d& a_clPt,
258  XmStamperEndCap& a_cap,
259  VecPt3d& a_left,
260  VecPt3d& a_right,
261  int a_leftShoulderIdx,
262  int a_rightShoulderIdx)
263 {
264  XM_ENSURE_TRUE(static_cast<size_t>(a_leftShoulderIdx) < a_left.size());
265  XM_ENSURE_TRUE(static_cast<size_t>(a_rightShoulderIdx) < a_right.size());
266  // get cs width between the CL and shoulder
267  Pt3d p0(a_clPt), p1(a_left[a_leftShoulderIdx - 1]), p2(a_right[a_rightShoulderIdx - 1]);
268  double leftWidth = Mdist(p0.x, p0.y, p1.x, p1.y);
269  double rightWidth = Mdist(p0.x, p0.y, p2.x, p2.y);
270  bool gbLeft = a_cap.m_guidebank.m_side == 0;
271 
272  // switch angle if this is the first cs and guidebank is left side OR
273  // last cs and guidebank is right side
274  double gbWidth = a_cap.m_guidebank.m_width;
275  double gbAngle = a_cap.m_angle;
276  double rightAngle(0), leftAngle(0);
277  if ((a_first && gbLeft) || (!a_first && !gbLeft))
278  {
279  rightAngle = atan(gbWidth / 2 / leftWidth) * 180.0 / XM_PI;
280  leftAngle = -atan(gbWidth / 2 / rightWidth) * 180.0 / XM_PI;
281  }
282  else
283  {
284  leftAngle = atan(gbWidth / 2 / leftWidth) * 180.0 / XM_PI;
285  rightAngle = -atan(gbWidth / 2 / rightWidth) * 180.0 / XM_PI;
286  }
287 
288  double oldMag(0), oldAngle(0), newMag(0), newAngle(0);
289  // rotate for the left guidebank
290  for (size_t i = 0; i < a_left.size(); ++i)
291  {
292  p1 = a_left[i] - p0;
293  gmComponentMagnitudes(&p1.x, &p1.y, &oldMag, &oldAngle, true);
294  oldAngle -= gbAngle;
295  oldMag *= cos(gbAngle * XM_PI / 180.0);
296 
297  newAngle = oldAngle + gbAngle + leftAngle;
298  newMag = oldMag / cos((gbAngle + leftAngle) * XM_PI / 180.0);
299 
300  // calc new xy
301  gmComponentMagnitudes(&p2.x, &p2.y, &newMag, &newAngle, false);
302 
303  a_left[i].x = p2.x + p0.x;
304  a_left[i].y = p2.y + p0.y;
305  }
306 
307  // rotate for right guidebank
308  for (size_t i = 0; i < a_right.size(); ++i)
309  {
310  p1 = a_right[i] - p0;
311  gmComponentMagnitudes(&p1.x, &p1.y, &oldMag, &oldAngle, true);
312  oldAngle -= gbAngle;
313  oldMag *= cos(gbAngle * XM_PI / 180.0);
314 
315  newAngle = oldAngle + gbAngle - rightAngle;
316  newMag = oldMag / cos((gbAngle - rightAngle) * XM_PI / 180.0);
317 
318  // calc new xy
319  gmComponentMagnitudes(&p2.x, &p2.y, &newMag, &newAngle, false);
320 
321  a_right[i].x = p2.x + p0.x;
322  a_right[i].y = p2.y + p0.y;
323  }
324 
325  // do more past the shoulders
326  if ((a_first && gbLeft) || (!a_first && !gbLeft))
327  {
328  rightAngle = 45.0 - rightAngle;
329  leftAngle = -45.0 - leftAngle;
330  }
331  else
332  {
333  leftAngle = 45.0 - leftAngle;
334  rightAngle = -45.0 - rightAngle;
335  }
336 
337  p0 = a_left[a_leftShoulderIdx - 1];
338  // rotate left wing wall
339  size_t start = static_cast<size_t>(a_leftShoulderIdx);
340  for (size_t i = start; i < a_left.size(); ++i)
341  {
342  p1 = a_left[i] - p0;
343  gmComponentMagnitudes(&p1.x, &p1.y, &oldMag, &oldAngle, true);
344  oldAngle -= gbAngle;
345  oldMag *= cos(gbAngle * XM_PI / 180.0);
346 
347  newAngle = oldAngle + gbAngle + leftAngle;
348  newMag = oldMag / cos((gbAngle + leftAngle) * XM_PI / 180.0);
349 
350  // calc new xy
351  gmComponentMagnitudes(&p2.x, &p2.y, &newMag, &newAngle, false);
352 
353  a_left[i].x = p2.x + p0.x;
354  a_left[i].y = p2.y + p0.y;
355  }
356 
357  p0 = a_right[a_rightShoulderIdx - 1];
358  // rotate right wing wall
359  start = static_cast<size_t>(a_rightShoulderIdx);
360  for (size_t i = start; i < a_right.size(); ++i)
361  {
362  p1 = a_right[i] - p0;
363  gmComponentMagnitudes(&p1.x, &p1.y, &oldMag, &oldAngle, true);
364  oldAngle -= gbAngle;
365  oldMag *= cos(gbAngle * XM_PI / 180.0);
366 
367  newAngle = oldAngle + gbAngle - rightAngle;
368  newMag = oldMag / cos((gbAngle - rightAngle) * XM_PI / 180.0);
369 
370  // calc new xy
371  gmComponentMagnitudes(&p2.x, &p2.y, &newMag, &newAngle, false);
372 
373  a_right[i].x = p2.x + p0.x;
374  a_right[i].y = p2.y + p0.y;
375  }
376 } // XmStampEndCapImpl::GuidebankRotate
377 //------------------------------------------------------------------------------
383 //------------------------------------------------------------------------------
385  int a_shoulderIdx,
386  VecPt3d& a_cs)
387 {
388  if (0 == a_capAngle)
389  return;
390  XM_ENSURE_TRUE(static_cast<size_t>(a_shoulderIdx) < a_cs.size());
391  Pt3d p0 = a_cs[a_shoulderIdx - 1];
392 
393  double oldMag(0), oldAngle(0);
394  size_t start = static_cast<size_t>(a_shoulderIdx);
395  for (size_t i = start; i < a_cs.size(); ++i)
396  {
397  Pt3d p1 = a_cs[i] - p0;
398  gmComponentMagnitudes(&p1.x, &p1.y, &oldMag, &oldAngle, true);
399  oldAngle -= a_capAngle;
400  oldMag *= cos(a_capAngle * XM_PI / 180.0);
401 
402  // calc the new xy
403  Pt3d p2;
404  gmComponentMagnitudes(&p2.x, &p2.y, &oldMag, &oldAngle, false);
405 
406  a_cs[i].x = p2.x + p0.x;
407  a_cs[i].y = p2.y + p0.y;
408  }
409 } // XmStampEndCapImpl::SlopedAbutmentRotateShoulders
410 //------------------------------------------------------------------------------
418 //------------------------------------------------------------------------------
420  double a_capAngle,
421  double a_wwAngle,
422  int a_shoulderIdx,
423  VecPt3d& a_cs)
424 {
425  if (0 == a_capAngle && 0 == a_wwAngle)
426  return;
427 
428  XM_ENSURE_TRUE_NO_ASSERT(static_cast<size_t>(a_shoulderIdx) < a_cs.size());
429 
430  if (a_first)
431  a_wwAngle *= -1.0;
432  Pt3d p0 = a_cs[a_shoulderIdx - 1];
433  // rotate the wing wall
434  double oldMag(0), oldAngle(0), newAngle(0), newMag(0);
435  size_t start = static_cast<size_t>(a_shoulderIdx);
436  for (size_t i = start; i < a_cs.size(); ++i)
437  {
438  Pt3d p1 = a_cs[i] - p0;
439  gmComponentMagnitudes(&p1.x, &p1.y, &oldMag, &oldAngle, true);
440  oldAngle -= a_capAngle;
441  oldMag *= cos(a_capAngle * XM_PI / 180.0);
442  // calc new angle and magnitude
443  newAngle = oldAngle + a_capAngle + a_wwAngle;
444  newMag = oldMag / cos((a_capAngle + a_wwAngle) * XM_PI / 180.0);
445  // calc new xy
446  Pt3d p2;
447  gmComponentMagnitudes(&p2.x, &p2.y, &newMag, &newAngle, false);
448  a_cs[i].x = p2.x + p0.x;
449  a_cs[i].y = p2.y + p0.y;
450  }
451 } // XmStampEndCapImpl::WingWallRotate
452 //------------------------------------------------------------------------------
458 //------------------------------------------------------------------------------
460 {
461  stXs3dPts* pts(&a_3dpts.m_first_endcap);
462  XmStamperEndCap cap(a_io.m_firstEndCap);
463  if (!a_first)
464  {
465  pts = &a_3dpts.m_last_endcap;
466  cap = a_io.m_lastEndCap;
467  }
468  pts->m_left.resize(0);
469  pts->m_right.resize(0);
470  // do nothing for a wing wall
471  if (cap.m_type == 2)
472  return;
473  // make sure the cap is a guidebank or a sloped abutment
474  XM_ENSURE_TRUE(cap.m_type == 0 || cap.m_type == 1);
475 
476  if (cap.m_type == 0)
477  GuidebankEndCapTo3dPts(a_first, a_io, a_3dpts);
478  else
479  SlopedAbutmentEndCapTo3dPts(a_first, a_io, a_3dpts);
480 
481 } // XmStampEndCapImpl::EndCapTo3dPts
482 //------------------------------------------------------------------------------
488 //------------------------------------------------------------------------------
490  XmStamperIo& a_io,
491  XmStamper3dPts& a_3dpts)
492 {
493  BSHP<XmGuideBankUtil> gb = XmGuideBankUtil::New();
494  gb->DoConvertTo3d(a_first, a_io, a_3dpts);
495 } // XmStampEndCapImpl::EndCapTo3dPts
496 //------------------------------------------------------------------------------
502 //------------------------------------------------------------------------------
504  XmStamperIo& a_io,
505  XmStamper3dPts& a_3dpts)
506 {
507  BSHP<XmSlopedAbutmentUtil> sa = XmSlopedAbutmentUtil::New();
508  sa->DoConvertTo3d(a_first, a_io, a_3dpts);
509 } // XmStampEndCapImpl::SlopedAbutmentEndCapTo3dPts
510 
511 //------------------------------------------------------------------------------
514 //------------------------------------------------------------------------------
515 BSHP<XmStampEndCap> XmStampEndCap::New()
516 {
517  BSHP<XmStampEndCap> interp(new XmStampEndCapImpl);
518  return interp;
519 } // XmStampEndCap::New
520 //------------------------------------------------------------------------------
522 //------------------------------------------------------------------------------
523 XmStampEndCap::XmStampEndCap()
524 {
525 } // XmStampEndCap::XmStampEndCap
526 //------------------------------------------------------------------------------
528 //------------------------------------------------------------------------------
529 XmStampEndCap::~XmStampEndCap()
530 {
531 } // XmStampEndCap::~XmStampEndCap
532 
533 } // namespace xms
static BSHP< XmGuideBankUtil > New()
Creates a XmStampInterpCrossSection class.
static BSHP< XmStampEndCap > New()
Creates a XmStampInterpCrossSection class.
VecPt3d2d m_right
3d locations of cross section points
stXs3dPts m_last_endcap
3d locations of the last end cap
XmStamperEndCap m_firstEndCap
end cap at beginnig of polyline
Definition: XmStamperIo.h:195
void GuidebankRotate(bool a_first, Pt3d &a_clPt, XmStamperEndCap &a_cap, VecPt3d &a_left, VecPt3d &a_right, int a_leftShoulderIdx, int a_rightShoulderIdx)
Rotates cross section points based on the angle specified for an end cap.
virtual void ConvertTo3dPts(XmStamperIo &a_io, XmStamper3dPts &a_3dpts) override
Rotates cross section points based on the angle specified for an end cap.
#define XM_ENSURE_TRUE_NO_ASSERT(...)
End cap definition for feature stamp.
Definition: XmStamperIo.h:120
static BSHP< XmSlopedAbutmentUtil > New()
Creates a XmSlopedAbutmentUtil class.
void EndCapTo3dPts(bool a_first, XmStamperIo &a_io, XmStamper3dPts &a_3dpts)
Converts an end cap to 3d pts defining the geometry.
End caps for feature stamping.
Definition: XmStampEndCap.h:37
class to hold 3d points for a cross section
void RotateCrossSectionForType(bool a_first, Pt3d &a_clPt, XmStamperEndCap &a_cap, VecPt3d &a_left, VecPt3d &a_right, int a_leftShoulderIdx, int a_rightShoulderIdx)
Rotates cross section points based on the angle specified for an end cap.
XmStamperEndCap m_lastEndCap
end cap at end of polyline
Definition: XmStamperIo.h:197
void SlopedAbutmentEndCapTo3dPts(bool a_first, XmStamperIo &a_io, XmStamper3dPts &a_3dpts)
Converts an end cap to 3d pts defining the geometry.
#define XM_ENSURE_TRUE(...)
int m_side
position of guidebank relative to center line, 0-left, 1-right
Definition: XmStamperIo.h:108
void SlopedAbutmentRotateShoulders(double a_capAngle, int a_shoulderIdx, VecPt3d &a_cs)
Rotates cross section points based on the angle specified for an end cap.
XmWingWall m_wingWall
wing wall definition
Definition: XmStamperIo.h:133
XmGuidebank m_guidebank
guidebank definition
Definition: XmStamperIo.h:131
double m_wingWallAngle
degrees from 0 to 60
Definition: XmStamperIo.h:68
void gmComponentMagnitudes(double *a_x, double *a_y, double *a_mag, double *a_dir, bool a_tomagdir)
stXs3dPts m_first_endcap
3d locations of first end cap
class to hold 3d points generated by the stamping operation
int m_type
type of end cap: 0- guidebank, 1- sloped abutment, 2- wing wall
Definition: XmStamperIo.h:129
Pt3< double > Pt3d
Stamping inputs/outputs class.
Definition: XmStamperIo.h:171
Implementaion of XmStampEndCap.
void GuidebankEndCapTo3dPts(bool a_first, XmStamperIo &a_io, XmStamper3dPts &a_3dpts)
Converts an end cap to 3d pts defining the geometry.
std::vector< VecPt3d > VecPt3d2d
void AdjustCrossSection(bool a_first, XmStamperIo &a_cap, VecPt3d2d &a_left, VecPt3d2d &a_right)
Rotates cross section points based on the angle specified for an end cap.
virtual void RotateEndCapCrossSections(XmStamperIo &a_io, VecPt3d2d &a_left, VecPt3d2d &a_right) override
Rotates cross section points based on the angle specified for an end cap.
#define XM_PI
std::vector< XmStampCrossSection > m_cs
cross sections along the polyLine
Definition: XmStamperIo.h:193
double Mdist(_T x1, _U y1, _V x2, _W y2)
VecPt3d2d m_left
3d locations of cross section points
double m_angle
degrees from -45 to 45
Definition: XmStamperIo.h:130
double m_width
width of guidebank about the center line
Definition: XmStamperIo.h:111
void WingWallRotate(bool a_first, double a_capAngle, double a_wwAngle, int a_shoulderIdx, VecPt3d &a_cs)
Rotates cross section points based on the angle specified for an end cap.
void RotateCrossSection(double a_angle, Pt3d &a_cl, VecPt3d &a_cs)
Rotates cross section points based on the angle specified for an end cap.
std::vector< Pt3d > VecPt3d
VecPt3d m_centerLine
Definition: XmStamperIo.h:189