DeSiGNAR  0.5a
Data Structures General Library
polygon.H
Go to the documentation of this file.
1 /*
2  This file is part of Designar.
3  Copyright (C) 2017 by Alejandro J. Mujica
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  Any user request of this software, write to
19 
20  Alejandro Mujica
21 
22  aledrums@gmail.com
23 */
24 
25 # ifndef DSGPOLYGON_H
26 # define DSGPOLYGON_H
27 
28 # include <segment.H>
29 # include <nodesdef.H>
30 # include <italgorithms.H>
31 
32 namespace Designar
33 {
34 
35  template <typename PointT>
36  class GenPolygon
37  {
38  using Vertex = DLNode<PointT>;
39 
40  static Vertex * dl_to_vertex(DL * v)
41  {
42  return static_cast<Vertex *>(v);
43  }
44 
45  static Vertex * to_vertex(PointT & p)
46  {
47  Vertex * zero = 0;
48  nat_t off_set = (nat_t) &zero->get_item();
49  nat_t point_address = (nat_t) &p;
50  return (Vertex *) (point_address - off_set);
51  }
52 
53  void copy(const GenPolygon &);
54 
55  nat_t num_vertices;
56  DL vertex_list;
57 
58  public:
59  using PointType = PointT;
61 
63  : num_vertices(0), vertex_list()
64  {
65  // empty
66  }
67 
68  GenPolygon(const std::initializer_list<PointT> &);
69 
71  : GenPolygon()
72  {
73  copy(p);
74  }
75 
77  : GenPolygon()
78  {
79  swap(p);
80  }
81 
83  {
84  clear();
85  }
86 
88  {
89  if (this == &p)
90  return *this;
91 
92  clear();
93  copy(p);
94 
95  return *this;
96  }
97 
99  {
100  swap(p);
101  return *this;
102  }
103 
104  void swap(GenPolygon & p)
105  {
106  std::swap(num_vertices, p.num_vertices);
107  vertex_list.swap(p.vertex_list);
108  }
109 
110  void clear();
111 
112  void add_vertex(const PointT & p)
113  {
114  vertex_list.insert_prev(new Vertex(p));
115  ++num_vertices;
116  }
117 
118  void add_vertex(PointT && p)
119  {
120  vertex_list.insert_prev(new Vertex(std::forward<PointT>(p)));
121  ++num_vertices;
122  }
123 
124  PointT & get_first_vertex()
125  {
126  if (num_vertices == 0)
127  throw std::length_error("Polygon has not vertices");
128 
129  return dl_to_vertex(vertex_list.get_next())->get_item();
130  }
131 
132  const PointT & get_first_vertex() const
133  {
134  if (num_vertices == 0)
135  throw std::length_error("Polygon has not vertices");
136 
137  return dl_to_vertex(const_cast<DL *>(vertex_list.get_next()))->get_item();
138  }
139 
140  PointT & get_last_vertex()
141  {
142  if (num_vertices == 0)
143  throw std::length_error("Polygon has not vertices");
144 
145  return dl_to_vertex(vertex_list.get_prev())->get_item();
146  }
147 
148  const PointT & get_last_vertex() const
149  {
150  if (num_vertices == 0)
151  throw std::length_error("Polygon has not vertices");
152 
153  return dl_to_vertex(const_cast<DL *>(vertex_list.get_prev()))->get_item();
154  }
155 
157  {
158  if (num_vertices < 2)
159  throw std::length_error("Polygon has not segments");
160 
161  const PointT & s =
162  dl_to_vertex(const_cast<DL *>(vertex_list.get_next()))->get_item();
163  const PointT & t =
164  dl_to_vertex(const_cast<DL *>(vertex_list.get_next()->get_next()))
165  ->get_item();
166  return SegmentType(s, t);
167  }
168 
170  {
171  if (num_vertices < 2)
172  throw std::length_error("Polygon has not segments");
173 
174  const PointT & s =
175  dl_to_vertex(const_cast<DL *>(vertex_list.get_prev())->get_prev())
176  ->get_item();
177  const PointT & t =
178  dl_to_vertex(const_cast<DL *>(vertex_list.get_prev()))->get_item();
179 
180  return SegmentType(s, t);
181  }
182 
183  bool is_empty() const
184  {
185  return num_vertices == 0;
186  }
187 
188  nat_t size() const
189  {
190  return num_vertices;
191  }
192 
193  class VertexIterator : public DL::Iterator,
194  public BidirectionalIterator<VertexIterator, PointT>
195  {
196  friend class BasicIterator<VertexIterator, PointT>;
197 
198  using Base = DL::Iterator;
199 
200  GenPolygon * p_ptr;
201  nat_t pos;
202 
203  void locate_position();
204 
205  public:
207  : Base(), p_ptr(nullptr)
208  {
209  // empty
210  }
211 
213  : Base(const_cast<DL *>(&p.vertex_list)),
214  p_ptr(const_cast<GenPolygon *>(&p)), pos(0)
215  {
216  // empty
217  }
218 
219  VertexIterator(const GenPolygon & p, DL * curr)
220  : Base(const_cast<DL *>(&p.vertex_list), curr),
221  p_ptr(const_cast<GenPolygon *>(&p)), pos(0)
222  {
223  locate_position();
224  }
225 
227  : Base(it), p_ptr(it.p_ptr)
228  {
229  // empty
230  }
231 
233  : VertexIterator()
234  {
235  swap(it);
236  }
237 
239  {
240  if (this == &it)
241  return *this;
242 
243  (Base &) *this = it;
244  p_ptr = it.p_ptr;
245 
246  return *this;
247  }
248 
250  {
251  swap(it);
252  }
253 
254  void swap(VertexIterator & it)
255  {
256  Base::swap(it);
257  std::swap(p_ptr, it.p_ptr);
258  }
259 
260  PointT & get_current()
261  {
262  return dl_to_vertex(Base::get_current())->get_item();
263  }
264 
265  const PointT & get_current() const
266  {
267  return dl_to_vertex(Base::get_current())->get_item();
268  }
269 
270  void del()
271  {
272  if (not Base::has_current())
273  throw std::overflow_error("There is not current element");
274 
275  Vertex * v = dl_to_vertex(Base::get_current());
276  Base::next();
277  --p_ptr->num_vertices;
278  v->del();
279  delete v;
280  }
281 
282  void next()
283  {
284  Base::next();
285  ++pos;
286  }
287 
288  void prev()
289  {
290  Base::prev();
291  --pos;
292  }
293 
295  {
296  return pos;
297  }
298  };
299 
301  : public BidirectionalIterator<SegmentIterator, SegmentType, true>
302  {
304 
305  GenPolygon * p_ptr;
306  Vertex * head;
307  Vertex * curr;
308  nat_t pos;
309 
310  void locate_position();
311 
312  protected:
314  {
315  return curr;
316  }
317 
318  public:
320  : head(nullptr), curr(nullptr)
321  {
322  // empty
323  }
324 
326  : head(dl_to_vertex(const_cast<DL *>(&p.vertex_list))),
327  curr(head->get_next()), pos(0)
328  {
329  if (p.size() < 2)
330  throw std::length_error("There are no segments in polygon");
331  }
332 
333  SegmentIterator(const GenPolygon & p, DL * c)
334  : head(dl_to_vertex(const_cast<DL *>(&p.vertex_list))),
335  curr(dl_to_vertex(c)), pos(0)
336  {
337  if (p.size() < 2)
338  throw std::length_error("There are no segments in polygon");
339 
340  locate_position();
341  }
342 
344  : head(it.head), curr(it.curr)
345  {
346  // empty
347  }
348 
350  : SegmentIterator()
351  {
352  swap(it);
353  }
354 
356  {
357  std::swap(head, it.head);
358  std::swap(curr, it.curr);
359  }
360 
361  bool has_current() const
362  {
363  return head != curr;
364  }
365 
367  {
368  if (not has_current())
369  throw std::overflow_error("There is not current element");
370 
371  Vertex * next = curr->get_next() == head ?
372  head->get_next() : curr->get_next();
373 
374  return SegmentType(curr->get_item(), next->get_item());
375  }
376 
378  {
379  if (not has_current())
380  throw std::overflow_error("There is not current element");
381 
382  Vertex * next = curr->get_next() == head ?
383  head->get_next() : curr->get_next();
384 
385  return SegmentType(curr->get_item(), next->get_item());
386  }
387 
388  void next()
389  {
390  if (not has_current())
391  throw std::out_of_range("There is not next element");
392 
393  ++pos;
394  curr = curr->get_next();
395  }
396 
397  void prev()
398  {
399  if (curr == head->get_next())
400  throw std::out_of_range("There is not previous element");
401 
402  --pos;
403  curr = curr->get_prev();
404  }
405 
406  void del()
407  {
408  if (not has_current())
409  throw std::overflow_error("There is not current element");
410 
411  Vertex * c = curr;
412  Vertex * n = nullptr;
413 
414  if (c->get_next() == head)
415  {
416  n = head->get_next();
417  curr = head;
418  }
419  else
420  {
421  next();
422  n = curr;
423  next();
424  }
425 
426  p_ptr->num_vertices -= 2;
427 
428  c->del();
429  n->del();
430 
431  delete c;
432  delete n;
433  }
434 
435  void reset()
436  {
437  curr = head->get_next();
438  pos = 0;
439  }
440 
442  {
443  return pos;
444  }
445  };
446 
448  {
449  return VertexIterator(*this);
450  }
451 
453  {
454  return VertexIterator(*this);
455  }
456 
458  {
459  return VertexIterator(*this, &vertex_list);
460  }
461 
463  {
464  return VertexIterator(*this, const_cast<DL *>(&vertex_list));
465  }
466 
467  SegmentIterator segments_begin()
468  {
469  return SegmentIterator(*this);
470  }
471 
472  SegmentIterator segments_begin() const
473  {
474  return SegmentIterator(*this);
475  }
476 
477  SegmentIterator segments_end()
478  {
479  return SegmentIterator(*this, &vertex_list);
480  }
481 
482  SegmentIterator segments_end() const
483  {
484  return SegmentIterator(*this, const_cast<DL *>(&vertex_list));
485  }
486 
487  template <class Op>
488  void for_each_vertex(Op & op) const
489  {
491  }
492 
493  template <class Op>
494  void for_each_vertex(Op && op = Op()) const
495  {
496  for_each_it(vertices_begin(), vertices_end(), std::forward<Op>(op));
497  }
498 
499  template <class Pred>
500  bool all_vertex(Pred & pred) const
501  {
502  return all_it(vertices_begin(), vertices_end(), pred);
503  }
504 
505  template <class Pred>
506  bool all_vertex(Pred && pred = Pred()) const
507  {
508  return all_it(vertices_begin(), vertices_end(), std::forward<Pred>(pred));
509  }
510 
511  template <class Pred>
512  bool exists_vertex(Pred & pred) const
513  {
514  return exists_it(vertices_begin(), vertices_end(), pred);
515  }
516 
517  template <class Pred>
518  bool exists_vertex(Pred && pred = Pred()) const
519  {
521  std::forward<Pred>(pred));
522  }
523 
524  template <class Pred>
525  bool none_vertex(Pred & pred) const
526  {
527  return none_it(vertices_begin(), vertices_end(), pred);
528  }
529 
530  template <class Pred>
531  bool none_vertex(Pred && pred = Pred()) const
532  {
533  return none_it(vertices_begin(), vertices_end(),
534  std::forward<Pred>(pred));
535  }
536 
537  template <class Op>
538  void for_each_segment(Op & op) const
539  {
541  }
542 
543  template <class Op>
544  void for_each_segment(Op && op = Op()) const
545  {
546  for_each_it(segments_begin(), segments_end(), std::forward<Op>(op));
547  }
548 
549  template <class Pred>
550  bool all_segment(Pred & pred) const
551  {
552  return all_it(segments_begin(), segments_end(), pred);
553  }
554 
555  template <class Pred>
556  bool all_segment(Pred && pred = Pred()) const
557  {
558  return all_it(segments_begin(), segments_end(), std::forward<Pred>(pred));
559  }
560 
561  template <class Pred>
562  bool exists_segment(Pred & pred) const
563  {
564  return exists_it(segments_begin(), segments_end(), pred);
565  }
566 
567  template <class Pred>
568  bool exists_segment(Pred && pred = Pred()) const
569  {
571  std::forward<Pred>(pred));
572  }
573 
574  template <class Pred>
575  bool none_segment(Pred & pred) const
576  {
577  return none_it(segments_begin(), segments_end(), pred);
578  }
579 
580  template <class Pred>
581  bool none_segment(Pred && pred = Pred()) const
582  {
583  return none_it(segments_begin(), segments_end(),
584  std::forward<Pred>(pred));
585  }
586  };
587 
588  template <class PointT>
589  void GenPolygon<PointT>::copy(const GenPolygon & p)
590  {
591  Vertex * v = dl_to_vertex(const_cast<DL *>(p.vertex_list.get_next()));
592 
593  while (v != &p.vertex_list)
594  {
595  vertex_list.insert_prev(new Vertex(v->get_item()));
596  v = v->get_next();
597  ++num_vertices;
598  }
599  }
600 
601  template <class PointT>
602  GenPolygon<PointT>::GenPolygon(const std::initializer_list<PointT> & l)
603  : GenPolygon()
604  {
605  for (const PointT & p : l)
606  add_vertex(p);
607  }
608 
609  template <class PointT>
611  {
612  while (not vertex_list.is_empty())
613  delete vertex_list.remove_next();
614 
615  num_vertices = 0;
616  }
617 
618  template <class PointT>
620  {
621  DL * ptr = Base::get_head()->get_next();
622 
623  while (ptr != Base::get_location())
624  {
625  ptr = ptr->get_next();
626  ++pos;
627  }
628  }
629 
630  template <class PointT>
632  {
633  DL * ptr = head->get_next();
634 
635  while (ptr != curr)
636  {
637  ptr = ptr->get_next();
638  ++pos;
639  }
640  }
641 
642  class PolygonInt : public GenPolygon<PointInt2D>
643  {
645  using Base::Base;
646  };
647 
648  class Polygon : public GenPolygon<Point2D>
649  {
650  using Base = GenPolygon<Point2D>;
651  using Base::Base;
652  };
653 
654 } // end namespace Designar
655 
656 # endif // DSGPOLYGON_H
void prev()
Definition: polygon.H:288
nat_t get_position() const
Definition: polygon.H:294
bool none_segment(Pred &&pred=Pred()) const
Definition: polygon.H:581
void next()
Definition: polygon.H:388
VertexIterator(const VertexIterator &it)
Definition: polygon.H:226
bool all_vertex(Pred &&pred=Pred()) const
Definition: polygon.H:506
bool all_vertex(Pred &pred) const
Definition: polygon.H:500
SegmentIterator(const GenPolygon &p)
Definition: polygon.H:325
~GenPolygon()
Definition: polygon.H:82
SegmentIterator segments_begin()
Definition: polygon.H:467
DLNode *& get_prev()
Definition: nodesdef.H:474
VertexIterator vertices_begin() const
Definition: polygon.H:452
Definition: polygon.H:193
const PointT & get_first_vertex() const
Definition: polygon.H:132
bool none_it(const It &, const It &, Pred &)
Definition: italgorithms.H:325
void add_vertex(PointT &&p)
Definition: polygon.H:118
bool is_empty() const
Definition: nodesdef.H:153
SegmentIterator(const GenPolygon &p, DL *c)
Definition: polygon.H:333
VertexIterator vertices_begin()
Definition: polygon.H:447
bool has_current() const
Definition: polygon.H:361
Definition: nodesdef.H:113
VertexIterator vertices_end()
Definition: polygon.H:457
void swap(GenPolygon &p)
Definition: polygon.H:104
PointT & get_current()
Definition: polygon.H:260
T & get_item()
Definition: nodesdef.H:454
void next()
Definition: polygon.H:282
void next()
Definition: nodesdef.H:383
void swap(SegmentIterator &it)
Definition: polygon.H:355
void swap(VertexIterator &it)
Definition: polygon.H:254
SegmentType get_last_segment() const
Definition: polygon.H:169
void prev()
Definition: nodesdef.H:391
Definition: iterator.H:36
SegmentIterator(const SegmentIterator &it)
Definition: polygon.H:343
VertexIterator(const GenPolygon &p)
Definition: polygon.H:212
void for_each_vertex(Op &&op=Op()) const
Definition: polygon.H:494
bool none_vertex(Pred &&pred=Pred()) const
Definition: polygon.H:531
void add_vertex(const PointT &p)
Definition: polygon.H:112
GenPolygon(const GenPolygon &p)
Definition: polygon.H:70
Definition: polygon.H:300
Vertex * get_location() const
Definition: polygon.H:313
VertexIterator(const GenPolygon &p, DL *curr)
Definition: polygon.H:219
bool none_vertex(Pred &pred) const
Definition: polygon.H:525
DL *& get_prev()
Definition: nodesdef.H:178
void del()
Definition: nodesdef.H:208
GenPolygon(GenPolygon &&p)
Definition: polygon.H:76
bool exists_it(const It &, const It &, Pred &)
Definition: italgorithms.H:310
SegmentIterator segments_begin() const
Definition: polygon.H:472
SegmentIterator segments_end() const
Definition: polygon.H:482
Definition: point2D.H:241
bool has_current() const
Definition: nodesdef.H:362
bool none_segment(Pred &pred) const
Definition: polygon.H:575
void for_each_it(const It &, const It &, Op &)
Definition: italgorithms.H:183
Definition: nodesdef.H:415
Definition: polygon.H:642
SegmentType get_current()
Definition: polygon.H:366
void swap(Iterator &it)
Definition: nodesdef.H:356
void del()
Definition: polygon.H:406
bool all_segment(Pred &pred) const
Definition: polygon.H:550
SegmentIterator(SegmentIterator &&it)
Definition: polygon.H:349
bool exists_segment(Pred &pred) const
Definition: polygon.H:562
const PointT & get_last_vertex() const
Definition: polygon.H:148
GenPolygon()
Definition: polygon.H:62
void for_each_segment(Op &&op=Op()) const
Definition: polygon.H:544
GenSegment< PointT > SegmentType
Definition: polygon.H:60
Definition: polygon.H:36
SegmentType get_current() const
Definition: polygon.H:377
VertexIterator & operator=(const VertexIterator &it)
Definition: polygon.H:238
SegmentIterator segments_end()
Definition: polygon.H:477
nat_t get_position() const
Definition: polygon.H:441
DL * remove_next()
Definition: nodesdef.H:215
bool exists_vertex(Pred &pred) const
Definition: polygon.H:512
DLNode *& get_next()
Definition: nodesdef.H:464
PointT & get_first_vertex()
Definition: polygon.H:124
GenPolygon & operator=(const GenPolygon &p)
Definition: polygon.H:87
void reset()
Definition: polygon.H:435
void for_each_segment(Op &op) const
Definition: polygon.H:538
SegmentIterator()
Definition: polygon.H:319
Definition: iterator.H:112
VertexIterator(VertexIterator &&it)
Definition: polygon.H:232
Definition: array.H:32
SegmentType get_first_segment() const
Definition: polygon.H:156
unsigned long int nat_t
Definition: types.H:50
void for_each_vertex(Op &op) const
Definition: polygon.H:488
bool exists_vertex(Pred &&pred=Pred()) const
Definition: polygon.H:518
VertexIterator()
Definition: polygon.H:206
VertexIterator vertices_end() const
Definition: polygon.H:462
void prev()
Definition: polygon.H:397
Definition: polygon.H:648
bool exists_segment(Pred &&pred=Pred()) const
Definition: polygon.H:568
bool all_segment(Pred &&pred=Pred()) const
Definition: polygon.H:556
DL * get_current()
Definition: nodesdef.H:367
PointT & get_last_vertex()
Definition: polygon.H:140
nat_t size() const
Definition: polygon.H:188
void clear()
Definition: polygon.H:610
const PointT & get_current() const
Definition: polygon.H:265
bool is_empty() const
Definition: polygon.H:183
void del()
Definition: polygon.H:270
DL *& get_next()
Definition: nodesdef.H:168
void insert_prev(DL *node)
Definition: nodesdef.H:198
Definition: nodesdef.H:293
void swap(DL *node)
Definition: nodesdef.H:229
bool all_it(const It &, const It &, Pred &)
Definition: italgorithms.H:295