xmsstamper  1.0
XmBreaklines.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 
12 #pragma warning(disable : 4996) // boost code
13 // 2. My own header
15 
16 // 3. Standard library headers
17 
18 // 4. External library headers
19 #pragma warning(push)
20 #pragma warning(disable : 4512) // boost code: no assignment operator
21 #include <boost/geometry/index/rtree.hpp>
22 #pragma warning(pop)
23 
24 // 5. Shared code headers
25 #include <xmscore/misc/XmLog.h>
27 #include <xmsinterp/geometry/GmBoostTypes.h> // GmBstPoly3d, XmBstRing
32 
33 // 6. Non-shared code headers
34 
35 //----- Forward declarations ---------------------------------------------------
36 namespace bg = boost::geometry;
37 namespace bgi = boost::geometry::index;
38 
39 //----- External globals -------------------------------------------------------
40 
41 //----- Namespace declaration --------------------------------------------------
42 
43 namespace xms
44 {
45 //----- Constants / Enumerations -----------------------------------------------
46 typedef std::pair<GmBstBox3d, int> ValueBox;
47 typedef bgi::rtree<ValueBox, bgi::quadratic<8>> RtreeBox;
48 
49 //----- Classes / Structs ------------------------------------------------------
50 
54 {
55 public:
58 
59  virtual bool CreateBreaklines(XmStamperIo& a_io, cs3dPtIdx& a_ptIdx, VecInt& a_blTypes) override;
60  //------------------------------------------------------------------------------
63  //------------------------------------------------------------------------------
64  virtual const VecInt& GetOuterPolygon() override { return m_outerPoly; }
65  bool BreaklinesIntersect(const VecInt2d& a_bl, const VecPt3d& a_pts) override;
66 
68  VecInt& a_leftCsEndPts,
69  VecInt& a_rightCsEndPts,
70  VecInt& a_firstXsPts,
71  VecInt& a_lastXsPts,
72  XmStamperIo& a_io);
73  void GetEndCapEndPoints(cs3dPtIdx& a_ptIdx,
74  VecInt& a_firstEndCapEndPts,
75  VecInt& a_lastEndCapEndPts,
76  XmStamperIo& a_io);
77 
79  BSHP<RtreeBox> m_rtree;
82  BSHP<XmSlopedAbutmentUtil> m_slopedAbutment;
84  BSHP<XmGuideBankUtil> m_guideBank;
85 };
86 
91 //------------------------------------------------------------------------------
93 //------------------------------------------------------------------------------
94 XmBreaklinesImpl::XmBreaklinesImpl()
95 : m_slopedAbutment(XmSlopedAbutmentUtil::New())
96 , m_guideBank(XmGuideBankUtil::New())
97 {
98 } // XmBreaklinesImpl::XmBreaklinesImpl
99 //------------------------------------------------------------------------------
101 //------------------------------------------------------------------------------
102 XmBreaklinesImpl::~XmBreaklinesImpl()
103 {
104 } // XmBreaklinesImpl::~XmBreaklinesImpl
105 //------------------------------------------------------------------------------
111 //------------------------------------------------------------------------------
113 {
114  a_blTypes.resize(0);
115  VecInt2d& b(a_io.m_outBreakLines);
116  // break line for the center line
117  b.push_back(a_ptIdx.m_centerLine);
118  a_blTypes.push_back(BL_CENTERLINE);
119  // break line for each cross section
120  VecInt leftCsEndPts, rightCsEndPts, leftShoulder, rightShoulder;
121  VecInt firstXsPts, lastXsPts;
122  for (size_t i = 0; i < a_ptIdx.m_centerLine.size(); ++i)
123  {
124  VecInt ixs;
125  // reverse add the left side
126  {
127  auto p = a_ptIdx.m_xsPts.m_left[i].rbegin();
128  auto end = a_ptIdx.m_xsPts.m_left[i].rend();
129  for (; p != end; ++p)
130  ixs.push_back(*p);
131  }
132  // put in the center line point
133  ixs.push_back(a_ptIdx.m_centerLine[i]);
134  // forward add the right side
135  {
136  auto p = a_ptIdx.m_xsPts.m_right[i].begin();
137  auto end = a_ptIdx.m_xsPts.m_right[i].end();
138  for (; p != end; ++p)
139  ixs.push_back(*p);
140  }
141  b.push_back(ixs);
142  a_blTypes.push_back(BL_XSECT);
143  if (i == 0)
144  {
145  firstXsPts = ixs;
146  a_blTypes.back() = BL_END;
147  }
148  if (i + 1 == a_ptIdx.m_centerLine.size())
149  {
150  lastXsPts = ixs;
151  a_blTypes.back() = BL_END;
152  }
153 
154  // left side shoulder and endpts
155  {
156  VecInt& v(a_ptIdx.m_xsPts.m_left[i]);
157  int leftIdx = std::max(a_io.m_cs[i].m_idxLeftShoulder - 1, 0);
158  if (!v.empty())
159  {
160  // break line for the end points of the cross sections
161  leftCsEndPts.push_back(v.back());
162  // break line for the shoulders of the cross sections
163  if (leftIdx < v.size())
164  leftShoulder.push_back(v[leftIdx]);
165  else
166  leftShoulder.push_back(v.back());
167  }
168  else
169  {
170  leftCsEndPts.push_back(a_ptIdx.m_centerLine[i]);
171  leftShoulder.push_back(a_ptIdx.m_centerLine[i]);
172  }
173  }
174  // right side shoulder and endpts
175  {
176  VecInt& v(a_ptIdx.m_xsPts.m_right[i]);
177  int rightIdx = std::max(a_io.m_cs[i].m_idxRightShoulder - 1, 0);
178  if (!v.empty())
179  {
180  // break line for the end points of the cross sections
181  rightCsEndPts.push_back(v.back());
182  // break line for the shoulders of the cross sections
183  if (rightIdx < v.size())
184  rightShoulder.push_back(v[rightIdx]);
185  else
186  rightShoulder.push_back(v.back());
187  }
188  else
189  {
190  rightCsEndPts.push_back(a_ptIdx.m_centerLine[i]);
191  rightShoulder.push_back(a_ptIdx.m_centerLine[i]);
192  }
193  }
194  }
195  b.push_back(leftCsEndPts);
196  a_blTypes.push_back(BL_END);
197  b.push_back(rightCsEndPts);
198  a_blTypes.push_back(BL_END);
199  b.push_back(leftShoulder);
200  a_blTypes.push_back(BL_SHOULDER);
201  b.push_back(rightShoulder);
202  a_blTypes.push_back(BL_SHOULDER);
203 
204  m_slopedAbutment->GetEndCapBreakLines(a_io, a_ptIdx, a_blTypes);
205  m_guideBank->GetEndCapBreakLines(a_io, a_ptIdx, a_blTypes);
206 
207  CreateOuterPolygonBreakline(a_ptIdx, leftCsEndPts, rightCsEndPts, firstXsPts, lastXsPts, a_io);
208 
209  return true;
210 } // XmBreaklinesImpl::CreateBreaklines
211 //------------------------------------------------------------------------------
219 //------------------------------------------------------------------------------
221  VecInt& a_leftCsEndPts,
222  VecInt& a_rightCsEndPts,
223  VecInt& a_firstXsPts,
224  VecInt& a_lastXsPts,
225  XmStamperIo& a_io)
226 {
227  // get endcap end points
228  VecInt firstEndCapEndPts, lastEndCapEndPts;
229  GetEndCapEndPoints(a_ptIdx, firstEndCapEndPts, lastEndCapEndPts, a_io);
230  // make a break line of the outer boundary
231  {
232  VecInt ixs(a_leftCsEndPts);
233  if (!lastEndCapEndPts.empty())
234  ixs.insert(ixs.end(), lastEndCapEndPts.begin(), lastEndCapEndPts.end());
235  else
236  ixs.insert(ixs.end(), a_lastXsPts.begin(), a_lastXsPts.end());
237  ixs.insert(ixs.end(), a_rightCsEndPts.rbegin(), a_rightCsEndPts.rend());
238  if (!firstEndCapEndPts.empty())
239  ixs.insert(ixs.end(), firstEndCapEndPts.begin(), firstEndCapEndPts.end());
240  else
241  ixs.insert(ixs.end(), a_firstXsPts.rbegin(), a_firstXsPts.rend());
242  ixs.push_back(ixs.front());
243  // remove any consective points with the same index
244  auto last = std::unique(ixs.begin(), ixs.end());
245  ixs.erase(last, ixs.end());
246  m_outerPoly.swap(ixs);
247  }
248 } // XmBreaklinesImpl::CreateOuterPolygonBreakline
249 //------------------------------------------------------------------------------
255 //------------------------------------------------------------------------------
257  VecInt& a_firstEndCapEndPts,
258  VecInt& a_lastEndCapEndPts,
259  XmStamperIo& a_io)
260 {
261  a_firstEndCapEndPts.resize(0);
262  a_lastEndCapEndPts.resize(0);
263  m_slopedAbutment->GetEndCapEndPoints(a_ptIdx, a_firstEndCapEndPts, a_lastEndCapEndPts, a_io);
264  m_guideBank->GetEndCapEndPoints(a_ptIdx, a_firstEndCapEndPts, a_lastEndCapEndPts, a_io);
265  if (a_io.m_firstEndCap.m_type == 0) // guidebank used for first endcap
266  {
267  std::reverse(a_firstEndCapEndPts.begin(), a_firstEndCapEndPts.end());
268  }
269 } // XmBreaklinesImpl::GetEndCapEndPoints
270 //------------------------------------------------------------------------------
276 //------------------------------------------------------------------------------
278 {
279  const VecInt2d& vbl(a_bl);
280  // create vector of breakline segments
281  std::pair<int, int> p;
282  std::vector<std::pair<int, int>> vSegs;
283  Pt3d bMin, bMax;
284  ValueBox aBox;
285  std::vector<ValueBox> vBoxes;
286  for (const auto& bl : vbl)
287  {
288  for (size_t i = 1; i < bl.size(); ++i)
289  {
290  p.first = bl[i - 1];
291  p.second = bl[i];
292  const Pt3d &p0(a_pts[p.first]), &p1(a_pts[p.second]);
293  if (p0.x < p1.x)
294  {
295  bMin.x = p0.x;
296  bMax.x = p1.x;
297  }
298  else
299  {
300  bMin.x = p1.x;
301  bMax.x = p0.x;
302  }
303  if (p0.y < p1.y)
304  {
305  bMin.y = p0.y;
306  bMax.y = p1.y;
307  }
308  else
309  {
310  bMin.y = p1.y;
311  bMax.y = p0.y;
312  }
313 
314  GmBstBox3d bb(bMin, bMax);
315  aBox.first = GmBstBox3d(bMin, bMax);
316  aBox.second = static_cast<int>(vSegs.size());
317  vBoxes.push_back(aBox);
318  vSegs.push_back(p);
319  }
320  }
321  m_rtree.reset(new RtreeBox(vBoxes.begin(), vBoxes.end()));
322 
323  // check intersections
324  std::vector<ValueBox> result;
325  for (size_t i = 0; i < vSegs.size(); ++i)
326  {
327  result.resize(0);
328  const Pt3d &p0(a_pts[vSegs[i].first]), &p1(a_pts[vSegs[i].second]);
329 
330  m_rtree->query(bgi::intersects(vBoxes[i].first), std::back_inserter(result));
331  for (size_t j = 0; j < result.size(); ++j)
332  {
333  int ix = result[j].second;
334  // is this the current "i" segment
335  if (ix == (int)i)
336  continue;
337  // see if the result shares a point with the "i" segment
338  if (vSegs[i].first == vSegs[ix].first || vSegs[i].first == vSegs[ix].second ||
339  vSegs[i].second == vSegs[ix].first || vSegs[i].second == vSegs[ix].second)
340  {
341  continue;
342  }
343  // check if the lines intersect
344  const Pt3d &p2(a_pts[vSegs[ix].first]), &p3(a_pts[vSegs[ix].second]);
345  if (gmLinesIntersect(p0, p1, p2, p3))
346  {
347  return true;
348  }
349  }
350  }
351  return false;
352 } // XmBreaklinesImpl::BreaklinesIntersect
353 
354 //------------------------------------------------------------------------------
357 //------------------------------------------------------------------------------
358 BSHP<XmBreaklines> XmBreaklines::New()
359 {
360  BSHP<XmBreaklines> p(new XmBreaklinesImpl());
361  return p;
362 } // XmBreaklines::New
363 //------------------------------------------------------------------------------
365 //------------------------------------------------------------------------------
366 XmBreaklines::XmBreaklines()
367 {
368 } // XmBreaklines::XmBreaklines
369 //------------------------------------------------------------------------------
371 //------------------------------------------------------------------------------
372 XmBreaklines::~XmBreaklines()
373 {
374 } // XmBreaklines::~XmBreaklines
375 
376 } // namespace xms
boost::geometry::model::box< Pt3d > GmBstBox3d
std::vector< int > VecInt
void GetEndCapEndPoints(cs3dPtIdx &a_ptIdx, VecInt &a_firstEndCapEndPts, VecInt &a_lastEndCapEndPts, XmStamperIo &a_io)
creates a breakline representing the outer polygon of the stamp
Implementaion of XmBreaklines.
VecInt2d m_outBreakLines
break lines that are honored in the TIN
Definition: XmStamperIo.h:205
bool BreaklinesIntersect(const VecInt2d &a_bl, const VecPt3d &a_pts) override
Check if any breakline segments intersect.
virtual bool CreateBreaklines(XmStamperIo &a_io, cs3dPtIdx &a_ptIdx, VecInt &a_blTypes) override
Creates breaklines.
BSHP< XmGuideBankUtil > m_guideBank
utility class for Guidebank End Caps
XmStamperEndCap m_firstEndCap
end cap at beginnig of polyline
Definition: XmStamperIo.h:195
Creates breaklines for the stamp operation.
Definition: XmBreaklines.h:37
Converts sloped abutment to 3d points.
std::vector< VecInt > VecInt2d
bool gmLinesIntersect(const Pt3d &one1, const Pt3d &one2, const Pt3d &two1, const Pt3d &two2)
virtual const VecInt & GetOuterPolygon() override
Returns the outer polygon of the stamp operation.
helper struct to store point indexes
void CreateOuterPolygonBreakline(cs3dPtIdx &a_ptIdx, VecInt &a_leftCsEndPts, VecInt &a_rightCsEndPts, VecInt &a_firstXsPts, VecInt &a_lastXsPts, XmStamperIo &a_io)
creates a breakline representing the outer polygon of the stamp
int m_type
type of end cap: 0- guidebank, 1- sloped abutment, 2- wing wall
Definition: XmStamperIo.h:129
Stamping inputs/outputs class.
Definition: XmStamperIo.h:171
csPtIdx m_xsPts
helper struct to store point indexes
BSHP< RtreeBox > m_rtree
spatial index to check intersections of breaklines
Converts sloped abutment to 3d points.
std::vector< XmStampCrossSection > m_cs
cross sections along the polyLine
Definition: XmStamperIo.h:193
std::pair< GmBstBox3d, int > ValueBox
Pair used in rtree.
bgi::rtree< ValueBox, bgi::quadratic< 8 > > RtreeBox
Rtree typedef.
VecInt2d m_right
indexes of cross section points
VecInt2d m_left
indexes of cross section points
static BSHP< XmBreaklines > New()
Creates a XmStampInterpCrossSection class.
VecInt m_centerLine
indexes of cross section points
BSHP< XmSlopedAbutmentUtil > m_slopedAbutment
utility class for Sloped Abutment End Caps
std::vector< Pt3d > VecPt3d