SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PositionVector.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A list of positions
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <queue>
35 #include <cmath>
36 #include <iostream>
37 #include <algorithm>
38 #include <cassert>
39 #include <iterator>
40 #include <limits>
41 #include <utils/common/StdDefs.h>
43 #include <utils/common/ToString.h>
44 #include "AbstractPoly.h"
45 #include "Position.h"
46 #include "PositionVector.h"
47 #include "GeomHelper.h"
48 #include "Line.h"
49 #include "Helper_ConvexHull.h"
50 #include "Boundary.h"
51 
52 #ifdef CHECK_MEMORY_LEAKS
53 #include <foreign/nvwa/debug_new.h>
54 #endif // CHECK_MEMORY_LEAKS
55 
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
61 
62 
63 PositionVector::PositionVector(const std::vector<Position>& v) {
64  std::copy(v.begin(), v.end(), std::back_inserter(myCont));
65 }
66 
67 
69 
70 
71 // ------------ Adding items to the container
72 void
74  myCont.push_back(p);
75 }
76 
77 
78 void
80  copy(p.myCont.begin(), p.myCont.end(), back_inserter(myCont));
81 }
82 
83 
84 void
86  myCont.insert(myCont.begin(), p);
87 }
88 
89 
90 bool
91 PositionVector::around(const Position& p, SUMOReal offset) const {
92  if (offset != 0) {
93  //throw 1; // !!! not yet implemented
94  }
95  SUMOReal angle = 0;
96  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
97  Position p1(
98  (*i).x() - p.x(),
99  (*i).y() - p.y());
100  Position p2(
101  (*(i + 1)).x() - p.x(),
102  (*(i + 1)).y() - p.y());
103  angle += GeomHelper::Angle2D(p1.x(), p1.y(), p2.x(), p2.y());
104  }
105  Position p1(
106  (*(myCont.end() - 1)).x() - p.x(),
107  (*(myCont.end() - 1)).y() - p.y());
108  Position p2(
109  (*(myCont.begin())).x() - p.x(),
110  (*(myCont.begin())).y() - p.y());
111  angle += GeomHelper::Angle2D(p1.x(), p1.y(), p2.x(), p2.y());
112  return (!(fabs(angle) < PI));
113 }
114 
115 
116 bool
118  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
119  if (poly.around(*i, offset)) {
120  return true;
121  }
122  }
123  return false;
124 }
125 
126 
127 bool
128 PositionVector::intersects(const Position& p1, const Position& p2) const {
129  if (size() < 2) {
130  return false;
131  }
132  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
133  if (GeomHelper::intersects(*i, *(i + 1), p1, p2)) {
134  return true;
135  }
136  }
137  //return GeomHelper::intersects(*(myCont.end()-1), *(myCont.begin()), p1, p2);
138  return false;
139 }
140 
141 
142 bool
144  if (size() < 2) {
145  return false;
146  }
147  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
148  if (v1.intersects(*i, *(i + 1))) {
149  return true;
150  }
151  }
152  //return v1.intersects(*(myCont.end()-1), *(myCont.begin()));
153  return false;
154 }
155 
156 
157 Position
159  const Position& p2) const {
160  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
161  if (GeomHelper::intersects(*i, *(i + 1), p1, p2)) {
162  return GeomHelper::intersection_position2D(*i, *(i + 1), p1, p2);
163  }
164  }
165  return Position(-1, -1);
166 }
167 
168 
169 Position
171  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
172  if (v1.intersects(*i, *(i + 1))) {
173  return v1.intersectsAtPoint(*i, *(i + 1));
174  }
175  }
176  /*
177  if(v1.intersects(*(myCont.end()-1), *(myCont.begin()))) {
178  return v1.intersectsAtPoint(*(myCont.end()-1), *(myCont.begin()));
179  }
180  */
181  return Position(-1, -1);
182 }
183 
184 
185 void
187  myCont.clear();
188 }
189 
190 
191 const Position&
192 PositionVector::operator[](int index) const {
193  if (index >= 0) {
194  return myCont[index];
195  } else {
196  return myCont[myCont.size() + index];
197  }
198 }
199 
200 
201 Position&
203  if (index >= 0) {
204  return myCont[index];
205  } else {
206  return myCont[myCont.size() + index];
207  }
208 }
209 
210 
211 size_t
213  return myCont.size();
214 }
215 
216 
217 Position
219  ContType::const_iterator i = myCont.begin();
220  SUMOReal seenLength = 0;
221  do {
222  const SUMOReal nextLength = (*i).distanceTo(*(i + 1));
223  if (seenLength + nextLength > pos) {
224  return positionAtLengthPosition(*i, *(i + 1), pos - seenLength);
225  }
226  seenLength += nextLength;
227  } while (++i != myCont.end() - 1);
228  return myCont.back();
229 }
230 
231 
232 Position
234  ContType::const_iterator i = myCont.begin();
235  SUMOReal seenLength = 0;
236  do {
237  const SUMOReal nextLength = (*i).distanceTo2D(*(i + 1));
238  if (seenLength + nextLength > pos) {
239  return positionAtLengthPosition2D(*i, *(i + 1), pos - seenLength);
240  }
241  seenLength += nextLength;
242  } while (++i != myCont.end() - 1);
243  return myCont.back();
244 }
245 
246 
247 SUMOReal
249  ContType::const_iterator i = myCont.begin();
250  SUMOReal seenLength = 0;
251  do {
252  SUMOReal nextLength = (*i).distanceTo(*(i + 1));
253  if (seenLength + nextLength > pos) {
254  Line l(*i, *(i + 1));
255  return l.atan2DegreeAngle();
256  }
257  seenLength += nextLength;
258  } while (++i != myCont.end() - 1);
259  Line l(*(myCont.end() - 2), *(myCont.end() - 1));
260  return l.atan2DegreeAngle();
261 }
262 
263 SUMOReal
265  ContType::const_iterator i = myCont.begin();
266  SUMOReal seenLength = 0;
267  do {
268  SUMOReal nextLength = (*i).distanceTo(*(i + 1));
269  if (seenLength + nextLength > pos) {
270  Line l(*i, *(i + 1));
271  return l.atan2DegreeSlope();
272  }
273  seenLength += nextLength;
274  } while (++i != myCont.end() - 1);
275  Line l(*(myCont.end() - 2), *(myCont.end() - 1));
276  return l.atan2DegreeSlope();
277 }
278 
279 Position
281  const Position& p2,
282  SUMOReal pos) {
283  const SUMOReal dist = p1.distanceTo(p2);
284  if (dist < pos) {
285  return Position(-1, -1);
286  }
287  return p1 + (p2 - p1) * (pos / dist);
288 }
289 
290 
291 Position
293  const Position& p2,
294  SUMOReal pos) {
295  const SUMOReal dist = p1.distanceTo2D(p2);
296  if (dist < pos) {
297  return Position(-1, -1);
298  }
299  return p1 + (p2 - p1) * (pos / dist);
300 }
301 
302 
303 Boundary
305  Boundary ret;
306  for (ContType::const_iterator i = myCont.begin(); i != myCont.end(); i++) {
307  ret.add(*i);
308  }
309  return ret;
310 }
311 
312 
313 Position
315  SUMOReal x = 0;
316  SUMOReal y = 0;
317  for (ContType::const_iterator i = myCont.begin(); i != myCont.end(); i++) {
318  x += (*i).x();
319  y += (*i).y();
320  }
321  return Position(x / (SUMOReal) myCont.size(), y / (SUMOReal) myCont.size());
322 }
323 
324 
325 Position
327  PositionVector tmp = *this;
328  if (!isClosed()) { // make sure its closed
329  tmp.push_back(tmp[0]);
330  }
331  const int endIndex = (int)tmp.size() - 1;
332  SUMOReal div = 0; // 6 * area including sign
333  SUMOReal x = 0;
334  SUMOReal y = 0;
335  if (tmp.area() != 0) { // numerical instability ?
336  // http://en.wikipedia.org/wiki/Polygon
337  for (int i = 0; i < endIndex; i++) {
338  const SUMOReal z = tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
339  div += z; // area formula
340  x += (tmp[i].x() + tmp[i + 1].x()) * z;
341  y += (tmp[i].y() + tmp[i + 1].y()) * z;
342  }
343  div *= 3; // 6 / 2, the 2 comes from the area formula
344  return Position(x / div, y / div);
345  } else {
346  // compute by decomposing into line segments
347  // http://en.wikipedia.org/wiki/Centroid#By_geometric_decomposition
348  SUMOReal lengthSum = 0;
349  for (int i = 0; i < endIndex; i++) {
350  SUMOReal length = tmp[i].distanceTo(tmp[i + 1]);
351  x += (tmp[i].x() + tmp[i + 1].x()) * length / 2;
352  y += (tmp[i].y() + tmp[i + 1].y()) * length / 2;
353  lengthSum += length;
354  }
355  return Position(x / lengthSum, y / lengthSum);
356  }
357 }
358 
359 
360 void
362  Position centroid = getCentroid();
363  for (size_t i = 0; i < size(); i++) {
364  myCont[i] = centroid + ((myCont[i] - centroid) * factor);
365  }
366 }
367 
368 
369 Position
371  if (myCont.size() == 1) {
372  return myCont[0];
373  }
374  return positionAtLengthPosition(SUMOReal((length() / 2.)));
375 }
376 
377 
378 SUMOReal
380  SUMOReal len = 0;
381  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
382  len += (*i).distanceTo(*(i + 1));
383  }
384  return len;
385 }
386 
387 
388 SUMOReal
390  SUMOReal area = 0;
391  PositionVector tmp = *this;
392  if (!isClosed()) { // make sure its closed
393  tmp.push_back(tmp[0]);
394  }
395  const int endIndex = (int)tmp.size() - 1;
396  // http://en.wikipedia.org/wiki/Polygon
397  for (int i = 0; i < endIndex; i++) {
398  area += tmp[i].x() * tmp[i + 1].y() - tmp[i + 1].x() * tmp[i].y();
399  }
400  if (area < 0) { // we whether we had cw or ccw order
401  area *= -1;
402  }
403  return area / 2;
404 }
405 
406 
407 bool
409  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
410  if (poly.around(*i, offset)) {
411  return true;
412  }
413  }
414  return false;
415 }
416 
417 
418 bool
419 PositionVector::crosses(const Position& p1, const Position& p2) const {
420  return intersects(p1, p2);
421 }
422 
423 
424 std::pair<PositionVector, PositionVector>
426  if (size() < 2) {
427  throw InvalidArgument("Vector to short for splitting");
428  }
429  if (where <= POSITION_EPS || where >= length() - POSITION_EPS) {
430  WRITE_WARNING("Splitting vector close to end (pos: " + toString(where) + ", length: " + toString(length()) + ")");
431  }
432  PositionVector first, second;
433  first.push_back(myCont[0]);
434  SUMOReal seen = 0;
435  ContType::const_iterator it = myCont.begin() + 1;
436  SUMOReal next = first.back().distanceTo(*it);
437  // see how many points we can add to first
438  while (where >= seen + next + POSITION_EPS) {
439  seen += next;
440  first.push_back(*it);
441  it++;
442  next = first.back().distanceTo(*it);
443  }
444  if (fabs(where - (seen + next)) > POSITION_EPS || it == myCont.end() - 1) {
445  // we need to insert a new point because 'where' is not close to an
446  // existing point or it is to close to the endpoint
447  Line tmpL(first.back(), *it);
448  Position p = tmpL.getPositionAtDistance(where - seen);
449  first.push_back(p);
450  second.push_back(p);
451  } else {
452  first.push_back(*it);
453  }
454  // add the remaining points to second
455  for (; it != myCont.end(); it++) {
456  second.push_back(*it);
457  }
458  assert(first.size() >= 2);
459  assert(second.size() >= 2);
460  assert(first.back() == second.front());
461  assert(fabs(first.length() + second.length() - length()) < 2 * POSITION_EPS);
462  return std::pair<PositionVector, PositionVector>(first, second);
463 }
464 
465 
466 std::ostream&
467 operator<<(std::ostream& os, const PositionVector& geom) {
468  for (PositionVector::ContType::const_iterator i = geom.myCont.begin(); i != geom.myCont.end(); i++) {
469  if (i != geom.myCont.begin()) {
470  os << " ";
471  }
472  os << (*i);
473  }
474  return os;
475 }
476 
477 
478 void
480  std::sort(myCont.begin(), myCont.end(), as_poly_cw_sorter());
481 }
482 
483 
484 void
486  for (size_t i = 0; i < size(); i++) {
487  myCont[i].add(xoff, yoff, zoff);
488  }
489 }
490 
491 
492 void
494  for (size_t i = 0; i < size(); i++) {
495  myCont[i].reshiftRotate(xoff, yoff, rot);
496  }
497 }
498 
499 
500 int
502  const Position& p2) const {
503  return atan2(p1.x(), p1.y()) < atan2(p2.x(), p2.y());
504 }
505 
506 
507 
508 void
510  std::sort(myCont.begin(), myCont.end(), increasing_x_y_sorter());
511 }
512 
513 
514 
516 
517 
518 
519 int
521  const Position& p2) const {
522  if (p1.x() != p2.x()) {
523  return p1.x() < p2.x();
524  }
525  return p1.y() < p2.y();
526 }
527 
528 
529 
530 SUMOReal
532  const Position& P2) const {
533  return (P1.x() - P0.x()) * (P2.y() - P0.y()) - (P2.x() - P0.x()) * (P1.y() - P0.y());
534 }
535 
536 
539  PositionVector ret = *this;
540  ret.sortAsPolyCWByAngle();
541  return simpleHull_2D(ret);
542 }
543 
544 
545 void
546 PositionVector::set(size_t pos, const Position& p) {
547  myCont[pos] = p;
548 }
549 
550 
553  PositionVector ret;
554  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
555  if (GeomHelper::intersects(*i, *(i + 1), line.p1(), line.p2())) {
557  *i, *(i + 1), line.p1(), line.p2()));
558  }
559  }
560  return ret;
561 }
562 
563 
564 int
566  if (myCont.back().distanceTo(v.myCont[0]) < 2) { // !!! heuristic
567  copy(v.myCont.begin() + 1, v.myCont.end(), back_inserter(myCont));
568  return 1;
569  }
570  //
571  Line l1(myCont[myCont.size() - 2], myCont.back());
572  l1.extrapolateBy(100);
573  Line l2(v.myCont[0], v.myCont[1]);
574  l2.extrapolateBy(100);
575  if (l1.intersects(l2) && l1.intersectsAtLength2D(l2) < l1.length2D() - 100) { // !!! heuristic
576  Position p = l1.intersectsAt(l2);
577  myCont[myCont.size() - 1] = p;
578  copy(v.myCont.begin() + 1, v.myCont.end(), back_inserter(myCont));
579  return 2;
580  } else {
581  copy(v.myCont.begin(), v.myCont.end(), back_inserter(myCont));
582  return 3;
583  }
584 }
585 
586 
587 void
589  if (myCont.back().distanceTo(v.myCont[0]) < 2) {
590  copy(v.myCont.begin() + 1, v.myCont.end(), back_inserter(myCont));
591  } else {
592  copy(v.myCont.begin(), v.myCont.end(), back_inserter(myCont));
593  }
594 }
595 
596 
599  PositionVector ret;
600  Position begPos = myCont.front();
601  if (begin > POSITION_EPS) {
602  begPos = positionAtLengthPosition(begin);
603  }
604  Position endPos = myCont.back();
605  if (end < length() - POSITION_EPS) {
606  endPos = positionAtLengthPosition(end);
607  }
608  ret.push_back(begPos);
609 
610  SUMOReal seen = 0;
611  ContType::const_iterator i = myCont.begin();
612  // skip previous segments
613  while ((i + 1) != myCont.end()
614  &&
615  seen + (*i).distanceTo(*(i + 1)) < begin) {
616  seen += (*i).distanceTo(*(i + 1));
617  i++;
618  }
619  // append segments in between
620  while ((i + 1) != myCont.end()
621  &&
622  seen + (*i).distanceTo(*(i + 1)) < end) {
623 
624  ret.push_back_noDoublePos(*(i + 1));
625  /*
626  if(ret.at(-1)!=*(i+1)) {
627  ret.push_back(*(i+1));
628  }
629  */
630  seen += (*i).distanceTo(*(i + 1));
631  i++;
632  }
633  // append end
634  ret.push_back_noDoublePos(endPos);
635  return ret;
636 }
637 
638 
641  PositionVector ret;
642  Position begPos = myCont.front();
643  if (begin > POSITION_EPS) {
644  begPos = positionAtLengthPosition2D(begin);
645  }
646  Position endPos = myCont.back();
647  if (end < length() - POSITION_EPS) {
648  endPos = positionAtLengthPosition2D(end);
649  }
650  ret.push_back(begPos);
651 
652  SUMOReal seen = 0;
653  ContType::const_iterator i = myCont.begin();
654  // skip previous segments
655  while ((i + 1) != myCont.end()
656  &&
657  seen + (*i).distanceTo2D(*(i + 1)) < begin) {
658  seen += (*i).distanceTo2D(*(i + 1));
659  i++;
660  }
661  // append segments in between
662  while ((i + 1) != myCont.end()
663  &&
664  seen + (*i).distanceTo2D(*(i + 1)) < end) {
665 
666  ret.push_back_noDoublePos(*(i + 1));
667  /*
668  if(ret.at(-1)!=*(i+1)) {
669  ret.push_back(*(i+1));
670  }
671  */
672  seen += (*i).distanceTo2D(*(i + 1));
673  i++;
674  }
675  // append end
676  ret.push_back_noDoublePos(endPos);
677  return ret;
678 }
679 
680 
681 void
683  // find minimum distance (from the begin)
684  size_t pos = 0;
685  SUMOReal dist = 1000000;
686  size_t currPos = 0;
688  GeomHelper::extrapolate_first(*(myCont.begin()), *(myCont.begin() + 1), 100),
689  *(myCont.begin() + 1));
690 // assert(currDist>=0);
691  if (currDist >= 0 && currDist < dist) {
692  dist = currDist;
693  pos = currPos;
694  }
695 
696  for (ContType::iterator i = myCont.begin(); i != myCont.end() - 1; i++, currPos++) {
697  SUMOReal currDist = GeomHelper::distancePointLine(p, *i, *(i + 1));
698  if (currDist >= 0 && currDist < dist) {
699  dist = currDist;
700  pos = currPos;
701  }
702  }
703  // remove leading items
704  for (size_t j = 0; j < pos; j++) {
705  myCont.erase(myCont.begin());
706  }
707  // replace first item by the new position
709  myCont[0], myCont[1], p);
710  if (lpos == -1) {
711  return;
712  }
714  if (np != *(myCont.begin())) {
715  myCont.erase(myCont.begin());
716  if (np != *(myCont.begin())) {
717  myCont.insert(myCont.begin(), p);
718  assert(myCont.size() > 1);
719  assert(*(myCont.begin()) != *(myCont.end() - 1));
720  }
721  }
722 }
723 
724 
725 void
727  // find minimum distance (from the end)
728  size_t pos = 0;
729  SUMOReal dist = 1000000;
730  size_t currPos = 0;
732  *(myCont.end() - 1),
733  GeomHelper::extrapolate_second(*(myCont.end() - 2), *(myCont.end() - 1), 100));
734 // assert(currDist>=0);
735  if (currDist >= 0 && currDist < dist) {
736  dist = currDist;
737  pos = currPos;
738  }
739 
740  for (ContType::reverse_iterator i = myCont.rbegin(); i != myCont.rend() - 1; i++, currPos++) {
741  SUMOReal currDist = GeomHelper::distancePointLine(p, *(i), *(i + 1));
742  if (currDist >= 0 && currDist < dist) {
743  dist = currDist;
744  pos = currPos;
745  }
746  }
747  // remove trailing items
748  for (size_t j = 0; j < pos; j++) {
749  myCont.erase(myCont.end() - 1);
750  }
751  // replace last item by the new position
752  SUMOReal lpos =
754  myCont[myCont.size() - 1], myCont[myCont.size() - 2], p);
755  if (lpos == -1) {
756  return;
757  }
759  length() - lpos);
760  if (np != *(myCont.end() - 1)) {
761  myCont.erase(myCont.end() - 1);
762  if (np != *(myCont.end() - 1)) {
763  myCont.push_back(np);
764  assert(myCont.size() > 1);
765  assert(*(myCont.begin()) != *(myCont.end() - 1));
766  }
767  }
768 }
769 
770 
771 SUMOReal
773  Line tmp(front(), back());
774  return tmp.atan2Angle();
775 }
776 
777 
778 void
780  if (i >= 0) {
781  myCont.erase(myCont.begin() + i);
782  } else {
783  myCont.erase(myCont.end() + i);
784  }
785 }
786 
787 
788 SUMOReal
791  SUMOReal nearestPos = -1;
792  SUMOReal seen = 0;
793  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
794  const SUMOReal pos =
795  GeomHelper::nearest_position_on_line_to_point2D(*i, *(i + 1), p, perpendicular);
796  const SUMOReal dist = pos < 0 ? minDist : p.distanceTo2D(Line(*i, *(i + 1)).getPositionAtDistance(pos));
797  if (dist < minDist) {
798  nearestPos = pos + seen;
799  minDist = dist;
800  }
801  seen += (*i).distanceTo2D(*(i + 1));
802  }
803  return nearestPos;
804 }
805 
806 
807 int
809  assert(size() > 0);
811  SUMOReal dist;
812  int closest = 0;
813  for (int i = 0; i < (int)size(); i++) {
814  dist = p.distanceTo(myCont[i]);
815  if (dist < minDist) {
816  closest = i;
817  minDist = dist;
818  }
819  }
820  return closest;
821 }
822 
823 
824 int
826  Position outIntersection = Position();
828  SUMOReal dist;
829  int insertionIndex = 1;
830  for (int i = 0; i < (int)size() - 1; i++) {
831  dist = GeomHelper::closestDistancePointLine(p, myCont[i], myCont[i + 1], outIntersection);
832  if (dist < minDist) {
833  insertionIndex = i + 1;
834  minDist = dist;
835  }
836  }
837  insertAt(insertionIndex, p);
838  return insertionIndex;
839 }
840 
841 
842 SUMOReal
844  if (size() == 1) {
845  return myCont.front().distanceTo(p);
846  }
847  Position outIntersection;
849  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
850  minDist = MIN2(minDist, GeomHelper::closestDistancePointLine(
851  p, *i, *(i + 1), outIntersection));
852  }
853  return minDist;
854 }
855 
856 
857 std::vector<SUMOReal>
859  std::vector<SUMOReal> ret;
860  for (ContType::const_iterator i = other.myCont.begin(); i != other.myCont.end() - 1; i++) {
861  std::vector<SUMOReal> atSegment = intersectsAtLengths2D(Line(*i, *(i + 1)));
862  copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
863  }
864  return ret;
865 }
866 
867 
868 std::vector<SUMOReal>
870  std::vector<SUMOReal> ret;
871  SUMOReal pos = 0;
872  for (ContType::const_iterator i = myCont.begin(); i != myCont.end() - 1; i++) {
873  Line l((*i), *(i + 1));
874  if (GeomHelper::intersects(l.p1(), l.p2(), line.p1(), line.p2())) {
875  Position p =
876  GeomHelper::intersection_position2D(l.p1(), l.p2(), line.p1(), line.p2());
877  SUMOReal atLength = p.distanceTo2D(l.p1());
878  ret.push_back(atLength + pos);
879  }
880  pos += l.length2D();
881  }
882  return ret;
883 }
884 
885 
886 void
888  assert(myCont.size() > 1);
889  Position nb =
891  Position ne =
893  myCont[myCont.size() - 2], myCont[myCont.size() - 1], val);
894  myCont.erase(myCont.begin());
895  push_front(nb);
896  myCont.erase(myCont.end() - 1);
897  push_back(ne);
898 }
899 
900 
903  PositionVector ret;
904  for (ContType::const_reverse_iterator i = myCont.rbegin(); i != myCont.rend(); i++) {
905  ret.push_back(*i);
906  }
907  return ret;
908 }
909 
910 
911 void
913  if (myCont.size() < 2) {
914  return;
915  }
916  PositionVector shape;
917  for (size_t i = 0; i < myCont.size(); i++) {
918  if (i == 0) {
919  Position from = myCont[i];
920  Position to = myCont[i + 1];
921  std::pair<SUMOReal, SUMOReal> offsets =
922  GeomHelper::getNormal90D_CW(from, to, amount);
923  shape.push_back(Position(from.x() - offsets.first,
924  from.y() - offsets.second, from.z()));
925  } else if (i == myCont.size() - 1) {
926  Position from = myCont[i - 1];
927  Position to = myCont[i];
928  std::pair<SUMOReal, SUMOReal> offsets =
929  GeomHelper::getNormal90D_CW(from, to, amount);
930  shape.push_back(Position(to.x() - offsets.first,
931  to.y() - offsets.second, to.z()));
932  } else {
933  Position from = myCont[i - 1];
934  Position me = myCont[i];
935  Position to = myCont[i + 1];
936  const double sinAngle = sin(GeomHelper::Angle2D(from.x() - me.x(), from.y() - me.y(),
937  me.x() - to.x(), me.y() - to.y()) / 2);
938  const double maxDev = 2 * (from.distanceTo2D(me) + me.distanceTo2D(to)) * sinAngle;
939  if (fabs(maxDev) < POSITION_EPS) {
940  // parallel case, just shift the middle point
941  std::pair<SUMOReal, SUMOReal> off =
942  GeomHelper::getNormal90D_CW(from, to, amount);
943  shape.push_back(Position(me.x() - off.first, me.y() - off.second, me.z()));
944  continue;
945  }
946  std::pair<SUMOReal, SUMOReal> offsets =
947  GeomHelper::getNormal90D_CW(from, me, amount);
948  std::pair<SUMOReal, SUMOReal> offsets2 =
949  GeomHelper::getNormal90D_CW(me, to, amount);
950  Line l1(
951  Position(from.x() - offsets.first, from.y() - offsets.second),
952  Position(me.x() - offsets.first, me.y() - offsets.second));
953  l1.extrapolateBy(100);
954  Line l2(
955  Position(me.x() - offsets2.first, me.y() - offsets2.second),
956  Position(to.x() - offsets2.first, to.y() - offsets2.second));
957  l2.extrapolateBy(100);
958  if (l1.intersects(l2)) {
959  shape.push_back(l1.intersectsAt(l2));
960  } else {
961  throw InvalidArgument("no line intersection");
962  }
963  }
964  }
965 
966  /*
967  ContType newCont;
968  std::pair<SUMOReal, SUMOReal> p;
969  Position newPos;
970  // first point
971  newPos = (*(myCont.begin()));
972  p = GeomHelper::getNormal90D_CW(*(myCont.begin()), *(myCont.begin()+1), amount);
973  newPos.add(p.first, p.second);
974  newCont.push_back(newPos);
975  // middle points
976  for(ContType::const_iterator i=myCont.begin()+1; i!=myCont.end()-1; i++) {
977  std::pair<SUMOReal, SUMOReal> oldp = p;
978  newPos = *i;
979  newPos.add(p.first, p.second);
980  newCont.push_back(newPos);
981  p = GeomHelper::getNormal90D_CW(*i, *(i+1), amount);
982  // Position newPos(*i);
983  // newPos.add((p.first+oldp.first)/2.0, (p.second+oldp.second)/2.0);
984  // newCont.push_back(newPos);
985  }
986  // last point
987  newPos = (*(myCont.end()-1));
988  newPos.add(p.first, p.second);
989  newCont.push_back(newPos);
990  myCont = newCont;
991  */
992  myCont = shape.myCont;
993 }
994 
995 
996 Line
997 PositionVector::lineAt(size_t pos) const {
998  assert(myCont.size() > pos + 1);
999  return Line(myCont[pos], myCont[pos + 1]);
1000 }
1001 
1002 
1003 Line
1005  return lineAt(0);
1006 }
1007 
1008 
1009 Line
1011  return lineAt(myCont.size() - 2);
1012 }
1013 
1014 
1015 void
1017  if (myCont[0] == myCont.back()) {
1018  return;
1019  }
1020  push_back(myCont[0]);
1021 }
1022 
1023 
1024 std::vector<SUMOReal>
1026  std::vector<SUMOReal> ret;
1027  ContType::const_iterator i;
1028  for (i = myCont.begin(); i != myCont.end(); i++) {
1029  ret.push_back(s.distance(*i));
1030  }
1031  for (i = s.myCont.begin(); i != s.myCont.end(); i++) {
1032  ret.push_back(distance(*i));
1033  }
1034  return ret;
1035 }
1036 
1037 
1038 Position
1040  Position last = myCont.back();
1041  myCont.erase(myCont.end() - 1);
1042  return last;
1043 }
1044 
1045 
1046 Position
1048  Position first = myCont.front();
1049  myCont.erase(myCont.begin());
1050  return first;
1051 }
1052 
1053 
1054 void
1055 PositionVector::insertAt(int index, const Position& p) {
1056  if (index >= 0) {
1057  myCont.insert(myCont.begin() + index, p);
1058  } else {
1059  myCont.insert(myCont.end() + index, p);
1060  }
1061 }
1062 
1063 
1064 void
1066  if (size() == 0 || !p.almostSame(myCont.back())) {
1067  myCont.push_back(p);
1068  }
1069 }
1070 
1071 
1072 void
1074  if (size() == 0 || !p.almostSame(myCont.front())) {
1075  myCont.insert(myCont.begin(), p);
1076  }
1077 }
1078 
1079 
1080 void
1081 PositionVector::replaceAt(size_t index, const Position& by) {
1082  assert(size() > index);
1083  myCont[index] = by;
1084 }
1085 
1086 
1087 bool
1089  return myCont.size() >= 2 && myCont[0] == myCont.back();
1090 }
1091 
1092 
1093 void
1094 PositionVector::removeDoublePoints(SUMOReal minDist, bool assertLength) {
1095  if (myCont.size() > 1) {
1096  ContType::iterator last = myCont.begin();
1097  for (ContType::iterator i = myCont.begin() + 1; i != myCont.end() && (!assertLength || myCont.size() > 2);) {
1098  if (last->almostSame(*i, minDist)) {
1099  i = myCont.erase(i);
1100  } else {
1101  last = i;
1102  ++i;
1103  }
1104  }
1105  }
1106 }
1107 
1108 
1109 void
1111  if (myCont.size() > 2) {
1112  Position& last = myCont.front();
1113  for (ContType::iterator i = myCont.begin() + 1; i != myCont.end() - 1;) {
1114  if (GeomHelper::distancePointLine(*i, last, *(i + 1)) < 0.001) {
1115  i = myCont.erase(i);
1116  } else {
1117  last = *i;
1118  ++i;
1119  }
1120  }
1121  }
1122 }
1123 
1124 
1125 bool
1127  if (size() == v2.size()) {
1128  for (int i = 0; i < (int)size(); i++) {
1129  if ((*this)[i] != v2[i]) {
1130  return false;
1131  }
1132  }
1133  return true;
1134  } else {
1135  return false;
1136  }
1137 }
1138 
1139 
1140 
1141 /****************************************************************************/
1142