G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsAAPolyline.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsHSplines/gsVSegment.h>
17 
18 namespace gismo
19 {
20 
21 template<class T>
22 class gsAAPolyline
23 {
29 public:
30 
31  gsAAPolyline()
32  {
33  m_closed = false;
34  }
35 
36  gsAAPolyline(gsVSegment<T> VSeg)
37  {
38  std::vector<T> newPoint(2);
39  newPoint[0] = VSeg.getX();
40  newPoint[1] = VSeg.getYDown();
41  m_vertices.push_back( newPoint );
42  newPoint[1] = VSeg.getYUp();
43  m_vertices.push_back( newPoint );
44  m_closed = false;
45  }
46 
48  std::vector< std::vector< index_t > > writeParasolid();
49 
51  std::vector< std::vector<unsigned int > > writeParasolidUnsigned();
52 
54  inline bool addVerticalSegment( int x, int y0, int y1 )
55  {
56  return ((pushBack(x, y0, y1)) ||
57  (pushBack(x, y1, y0)) ||
58  (pushFront(x, y0, y1)) ||
59  (pushFront(x, y1, y0)));
60  }
61 
63  inline bool canBeExtended( gsVSegment<T> vert_seg )
64  {
65  return addVerticalSegment( vert_seg.getX(), vert_seg.getYDown(), vert_seg.getYUp() );
66  }
67 
70  bool almostClosed()
71  {
72  if ( frontY() == backY() )
73  {
74  // It could have happened that the vertices forming the last and first line are colinear.
75  if( frontX() == backX() ) // WARNING: Assumes the last end first line to be vertical.
76  {
77  m_vertices.pop_back();
78  m_vertices.front()[1] = backY();
79  m_vertices.pop_back();
80  }
81  return true;
82  }
83  return false;
84  }
85 
87  bool mergeWith( gsAAPolyline<T>& other_poly );
88 
89  inline std::list< std::vector<T> > getVertices()
90  {
91  return m_vertices;
92  }
93 
94  inline T frontX()
95  {
96  return m_vertices.front()[0];
97  }
98 
99  inline T backX()
100  {
101  return m_vertices.back()[0];
102  }
103 
104  inline T frontY()
105  {
106  return m_vertices.front()[1];
107  }
108 
109  inline T backY()
110  {
111  return m_vertices.back()[1];
112  }
113 
114 protected:
115 
117  std::list< std::vector<T> > m_vertices;
118 
120  bool m_closed;
121 
123  bool pushBack( T x, T y0, T y1 );
124 
126  bool pushFront( T x, T y0, T y1 );
127 };
128 
129 template <class T>
130 bool gsAAPolyline<T>::pushBack( T x, T y0, T y1 )
131 {
132  if( m_vertices.empty() || (y0 == backY() ))
133  {
134  if( m_vertices.empty() || x != backX() ) // new segment
135  {
136  std::vector< T > newVertex (2);
137 
138  newVertex[0] = x;
139  newVertex[1] = y0;
140  m_vertices.push_back( newVertex );
141 
142  newVertex[1] = y1; // x coord is the same
143  m_vertices.push_back( newVertex );
144  }
145  else // prolongation of the last segment
146  m_vertices.back()[1] = y1;
147 
148  m_closed = almostClosed(); // This also looks, if the last and first segment can be merged.
149  return true;
150  }
151 
152  else // appending would not be axis aligned
153  return false;
154 }
155 
156 template <class T>
157 bool gsAAPolyline<T>::pushFront( T x, T y0, T y1 ) // Symmetric case to push_back
158 {
159  if( m_vertices.empty() || y0 == frontY() )
160  {
161  if( m_vertices.empty() || x != frontX() ) // Adding a segment with a different x coordinate
162  {
163  std::vector< T > newVertex (2);
164 
165  newVertex[0] = x;
166  newVertex[1] = y0;
167  m_vertices.push_front( newVertex );
168 
169  newVertex[1] = y1;
170  m_vertices.push_front( newVertex );
171  }
172  else
173  m_vertices.front()[1] = y1; // Adding a colinear point is just a prolongation.
174 
175  m_closed = almostClosed();
176  return true;
177  }
178  else
179  return false;
180 }
181 
182 template<class T>
183 std::vector< std::vector< index_t > > gsAAPolyline<T>::writeParasolid()
184 {
185  std::vector< std::vector< index_t > > result;
186 
187  if( m_vertices.size() < 4 )
188  {
189  gsWarn << "Function write_parasolid() says: only " << m_vertices.size() << " vertices.\n";
190  return result;
191  }
192 
193  if( !almostClosed() )
194  {
195  gsWarn << "Function write_parasolid() says: your curve should be closed but it isn't.";
196  return result;
197  }
198 
199  std::vector< index_t > item(4);
200 
201  // it will go through m_vertices; it_fwd will be pointing always to it's next % m_vertices.size().
202  auto it_fwd = m_vertices.begin();
203  ++it_fwd;
204  for(auto it = m_vertices.begin(); it != m_vertices.end(); ++it, ++it_fwd)
205  {
206  if( it_fwd == m_vertices.end() ) // cyclic list
207  it_fwd = m_vertices.begin();
208 
209  // The lines are expected oriented from left to right, from bottom up.
210  item[0] = std::min( (*it)[0], (*it_fwd)[0] );
211  item[1] = std::min( (*it)[1], (*it_fwd)[1] );
212  item[2] = std::max( (*it)[0], (*it_fwd)[0] );
213  item[3] = std::max( (*it)[1], (*it_fwd)[1] );
214 
215  result.push_back( item );
216  }
217  return result;
218 }
219 
220 
221 template<class T>
222 std::vector< std::vector< unsigned int > > gsAAPolyline<T>::writeParasolidUnsigned()
223 {
224  std::vector< std::vector<unsigned int > > result;
225 
226  if( m_vertices.size() < 4 )
227  {
228  gsWarn << "write_parasolid() says: only " << m_vertices.size() << " vertices.\n";
229  return result;
230  }
231 
232  if( !almostClosed() )
233  {
234  gsWarn << "write_parasolid() says: your curve should be closed but it isn't.";
235  return result;
236  }
237 
238  std::vector< unsigned int > item(4,0);
239 
240  // it will go through m_vertices; it_fwd will be pointing always to it's next % m_vertices.size().
241  auto it_fwd = m_vertices.begin();
242  ++it_fwd;
243  for(auto it = m_vertices.begin(); it != m_vertices.end(); ++it, ++it_fwd)
244  {
245  if( it_fwd == m_vertices.end() ) // cyclic list
246  it_fwd = m_vertices.begin();
247 
248  // The lines are expected oriented from left to right, from bottom up.
249  item[0] = std::min( (*it)[0], (*it_fwd)[0] );
250  item[1] = std::min( (*it)[1], (*it_fwd)[1] );
251  item[2] = std::max( (*it)[0], (*it_fwd)[0] );
252  item[3] = std::max( (*it)[1], (*it_fwd)[1] );
253 
254  result.push_back( item );
255  }
256  return result;
257 }
258 
259 template <class T>
260 bool gsAAPolyline<T>::mergeWith( gsAAPolyline<T>& otherPoly )
261 {
262  // We assume both polylines to be ending with a vertical segment (!).
263  std::list< std::vector<T> > newVertices;
264 
265  // adding in front of m_vertices
266  if( otherPoly.backY() == frontY() )
267  {
268  newVertices = otherPoly.getVertices();
269  if( newVertices.back() == m_vertices.front() )
270  {
271  newVertices.pop_back();
272  m_vertices.pop_front();
273  }
274  m_vertices.splice( m_vertices.begin(), newVertices );
275  m_closed = almostClosed();
276  return true;
277  }
278  // adding behind vertices in reverse order
279  else if( otherPoly.backY() == backY() )
280  {
281  newVertices = otherPoly.getVertices();
282  newVertices.reverse();
283  if( newVertices.front() == m_vertices.back() )
284  {
285  newVertices.pop_front();
286  m_vertices.pop_back();
287  }
288  m_vertices.splice( m_vertices.end(), newVertices );
289  m_closed = almostClosed();
290  return true;
291  }
292  // adding in front of m_vertices in reverse order
293  else if( otherPoly.frontY() == frontY() )
294  {
295  newVertices = otherPoly.getVertices();
296  newVertices.reverse();
297  if( newVertices.back() == m_vertices.front() )
298  {
299  newVertices.pop_back();
300  m_vertices.pop_front();
301  }
302  m_vertices.splice( m_vertices.begin(), newVertices );
303  m_closed = almostClosed();
304  return true;
305  }
306  // adding behind m_vertices
307  else if( otherPoly.frontY() == backY() )
308  {
309  newVertices = otherPoly.getVertices();
310  if( newVertices.front() == m_vertices.back() )
311  {
312  newVertices.pop_front();
313  m_vertices.pop_back();
314  }
315  m_vertices.splice( m_vertices.end(), newVertices );
316  m_closed = almostClosed();
317  return true;
318  }
319  // none of the previous was possible
320  else
321  return false;
322 }
323 
324 
325 } // namespace gismo
Helper class for gsAAPolyline.
#define gsWarn
Definition: gsDebug.h:50