00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029
00030 #include <queue>
00031 #include <cmath>
00032 #include <iostream>
00033 #include <algorithm>
00034 #include <cassert>
00035 #include "AbstractPoly.h"
00036 #include "Position2D.h"
00037 #include "Position2DVector.h"
00038 #include "GeomHelper.h"
00039 #include "Line2D.h"
00040 #include "Helper_ConvexHull.h"
00041
00042 #ifdef CHECK_MEMORY_LEAKS
00043 #include <foreign/nvwa/debug_new.h>
00044 #endif // CHECK_MEMORY_LEAKS
00045
00046
00047
00048
00049
00050 Position2DVector::Position2DVector() throw() {}
00051
00052
00053 Position2DVector::Position2DVector(const std::vector<Position2D> &v) throw() {
00054 std::copy(v.begin(), v.end(), std::back_inserter(myCont));
00055 }
00056
00057
00058 Position2DVector::~Position2DVector() throw() {}
00059
00060
00061
00062 void
00063 Position2DVector::push_back(const Position2D &p) throw() {
00064 myCont.push_back(p);
00065 }
00066
00067
00068 void
00069 Position2DVector::push_back(const Position2DVector &p) throw() {
00070 copy(p.myCont.begin(), p.myCont.end(), back_inserter(myCont));
00071 }
00072
00073
00074 void
00075 Position2DVector::push_front(const Position2D &p) {
00076 myCont.push_front(p);
00077 }
00078
00079
00080 bool
00081 Position2DVector::around(const Position2D &p, SUMOReal offset) const {
00082 if (offset!=0) {
00083
00084 }
00085 SUMOReal angle=0;
00086 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00087 Position2D p1(
00088 (*i).x() - p.x(),
00089 (*i).y() - p.y());
00090 Position2D p2(
00091 (*(i+1)).x() - p.x(),
00092 (*(i+1)).y() - p.y());
00093 angle += GeomHelper::Angle2D(p1.x(), p1.y(), p2.x(), p2.y());
00094 }
00095 Position2D p1(
00096 (*(myCont.end()-1)).x() - p.x(),
00097 (*(myCont.end()-1)).y() - p.y());
00098 Position2D p2(
00099 (*(myCont.begin())).x() - p.x(),
00100 (*(myCont.begin())).y() - p.y());
00101 angle += GeomHelper::Angle2D(p1.x(), p1.y(), p2.x(), p2.y());
00102 return (!(fabs(angle) < PI));
00103 }
00104
00105
00106 bool
00107 Position2DVector::overlapsWith(const AbstractPoly &poly, SUMOReal offset) const {
00108 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00109 if (poly.around(*i, offset)) {
00110 return true;
00111 }
00112 }
00113 return false;
00114 }
00115
00116
00117 bool
00118 Position2DVector::intersects(const Position2D &p1, const Position2D &p2) const {
00119 if (size()<2) {
00120 return false;
00121 }
00122 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00123 if (GeomHelper::intersects(*i, *(i+1), p1, p2)) {
00124 return true;
00125 }
00126 }
00127
00128 return false;
00129 }
00130
00131
00132 bool
00133 Position2DVector::intersects(const Position2DVector &v1) const {
00134 if (size()<2) {
00135 return false;
00136 }
00137 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00138 if (v1.intersects(*i, *(i+1))) {
00139 return true;
00140 }
00141 }
00142
00143 return false;
00144 }
00145
00146
00147 Position2D
00148 Position2DVector::intersectsAtPoint(const Position2D &p1,
00149 const Position2D &p2) const {
00150 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00151 if (GeomHelper::intersects(*i, *(i+1), p1, p2)) {
00152 return GeomHelper::intersection_position(*i, *(i+1), p1, p2);
00153 }
00154 }
00155 return Position2D(-1, -1);
00156 }
00157
00158
00159 Position2D
00160 Position2DVector::intersectsAtPoint(const Position2DVector &v1) const {
00161 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00162 if (v1.intersects(*i, *(i+1))) {
00163 return v1.intersectsAtPoint(*i, *(i+1));
00164 }
00165 }
00166
00167
00168
00169
00170
00171 return Position2D(-1, -1);
00172 }
00173
00174
00175 void
00176 Position2DVector::clear() {
00177 myCont.clear();
00178 }
00179
00180
00181 const Position2D &
00182 Position2DVector::operator[](int index) const {
00183 if (index>=0) {
00184 return myCont[index];
00185 } else {
00186 return myCont[myCont.size()+index];
00187 }
00188 }
00189
00190
00191 Position2D &
00192 Position2DVector::operator[](int index) {
00193 if (index>=0) {
00194 return myCont[index];
00195 } else {
00196 return myCont[myCont.size()+index];
00197 }
00198 }
00199
00200
00201 size_t
00202 Position2DVector::size() const {
00203 return myCont.size();
00204 }
00205
00206
00207
00208 Position2D
00209 Position2DVector::positionAtLengthPosition(SUMOReal pos) const {
00210 ContType::const_iterator i=myCont.begin();
00211 SUMOReal seenLength = 0;
00212 do {
00213 SUMOReal nextLength = (*i).distanceTo(*(i+1));
00214 if (seenLength+nextLength>pos) {
00215 return positionAtLengthPosition(*i, *(i+1), pos-seenLength);
00216 }
00217 seenLength += nextLength;
00218 } while (++i!=myCont.end()-1);
00219 return myCont.back();
00220
00221
00222 }
00223
00224
00225 SUMOReal
00226 Position2DVector::rotationDegreeAtLengthPosition(SUMOReal pos) const {
00227 ContType::const_iterator i=myCont.begin();
00228 SUMOReal seenLength = 0;
00229 do {
00230 SUMOReal nextLength = (*i).distanceTo(*(i+1));
00231 if (seenLength+nextLength>pos) {
00232 Line2D l(*i, *(i+1));
00233 return l.atan2DegreeAngle();
00234 }
00235 seenLength += nextLength;
00236 } while (++i!=myCont.end()-1);
00237 Line2D l(*(myCont.end()-2), *(myCont.end()-1));
00238 return l.atan2DegreeAngle();
00239
00240
00241 }
00242
00243
00244 Position2D
00245 Position2DVector::positionAtLengthPosition(const Position2D &p1,
00246 const Position2D &p2,
00247 SUMOReal pos) {
00248 SUMOReal dist = p1.distanceTo(p2);
00249 if (dist<pos) {
00250 return Position2D(-1, -1);
00251 }
00252 SUMOReal x = p1.x() + (p2.x() - p1.x()) / dist * pos;
00253 SUMOReal y = p1.y() + (p2.y() - p1.y()) / dist * pos;
00254 return Position2D(x, y);
00255 }
00256
00257
00258 Boundary
00259 Position2DVector::getBoxBoundary() const {
00260 Boundary ret;
00261 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end(); i++) {
00262 ret.add(*i);
00263 }
00264 return ret;
00265 }
00266
00267
00268 Position2D
00269 Position2DVector::getPolygonCenter() const {
00270 SUMOReal x = 0;
00271 SUMOReal y = 0;
00272 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end(); i++) {
00273 x += (*i).x();
00274 y += (*i).y();
00275 }
00276 return Position2D(x/(SUMOReal) myCont.size(), y/(SUMOReal) myCont.size());
00277 }
00278
00279
00280 Position2D
00281 Position2DVector::getLineCenter() const {
00282 if (myCont.size()==1) {
00283 return myCont[0];
00284 }
00285 return positionAtLengthPosition(SUMOReal((length()/2.)));
00286 }
00287
00288
00289 SUMOReal
00290 Position2DVector::length() const {
00291 SUMOReal len = 0;
00292 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00293 len += (*i).distanceTo(*(i+1));
00294 }
00295 return len;
00296 }
00297
00298
00299 bool
00300 Position2DVector::partialWithin(const AbstractPoly &poly, SUMOReal offset) const {
00301 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00302 if (poly.around(*i, offset)) {
00303 return true;
00304 }
00305 }
00306 return false;
00307 }
00308
00309
00310
00311 bool
00312 Position2DVector::crosses(const Position2D &p1, const Position2D &p2) const {
00313 return intersects(p1, p2);
00314 }
00315
00316
00317
00318 const Position2D &
00319 Position2DVector::getBegin() const {
00320 return myCont[0];
00321 }
00322
00323
00324 const Position2D &
00325 Position2DVector::getEnd() const {
00326 return myCont.back();
00327 }
00328
00329
00330 std::pair<Position2DVector, Position2DVector>
00331 Position2DVector::splitAt(SUMOReal where) const {
00332 assert(size()>=2);
00333 assert(where!=0);
00334 Position2DVector one, two;
00335 Position2D last = myCont[0];
00336 Position2D curr = myCont[0];
00337 SUMOReal seen = 0;
00338 SUMOReal currdist = 0;
00339 one.push_back(myCont[0]);
00340 ContType::const_iterator i=myCont.begin()+1;
00341
00342 do {
00343 last = curr;
00344 curr = *i;
00345 currdist = last.distanceTo(curr);
00346 if (seen+currdist<where&&i!=myCont.begin()+1) {
00347 one.push_back(last);
00348 }
00349 i++;
00350 seen += currdist;
00351 } while (seen<where&&i!=myCont.end());
00352 seen -= currdist;
00353 i--;
00354
00355 if (fabs(seen+currdist-where)<POSITION_EPS) {
00356 one.push_back(curr);
00357 } else {
00358 Line2D tmpL(last, curr);
00359 assert(seen+currdist-where>POSITION_EPS);
00360 Position2D p = tmpL.getPositionAtDistance(seen+currdist-where);
00361 one.push_back(p);
00362 two.push_back(p);
00363 }
00364
00365 for (; i!=myCont.end(); i++) {
00366 two.push_back(*i);
00367 }
00368 assert(one.size()>=2);
00369 assert(two.size()>=2);
00370 return std::pair<Position2DVector, Position2DVector>(one, two);
00371 }
00372
00373
00374
00375 std::ostream &
00376 operator<<(std::ostream &os, const Position2DVector &geom) {
00377 for (Position2DVector::ContType::const_iterator i=geom.myCont.begin(); i!=geom.myCont.end(); i++) {
00378 if (i!=geom.myCont.begin()) {
00379 os << " ";
00380 }
00381 os << (*i).x() << "," << (*i).y();
00382 }
00383 return os;
00384 }
00385
00386
00387 void
00388 Position2DVector::sortAsPolyCWByAngle() {
00389 Position2D c = getPolygonCenter();
00390 std::sort(myCont.begin(), myCont.end(), as_poly_cw_sorter(c));
00391 }
00392
00393
00394 void
00395 Position2DVector::reshiftRotate(SUMOReal xoff, SUMOReal yoff, SUMOReal rot) {
00396 for (size_t i=0; i<size(); i++) {
00397 myCont[i].reshiftRotate(xoff, yoff, rot);
00398 }
00399 }
00400
00401
00402 Position2DVector::as_poly_cw_sorter::as_poly_cw_sorter(Position2D center)
00403 : myCenter(center) {}
00404
00405
00406
00407 int
00408 Position2DVector::as_poly_cw_sorter::operator()(const Position2D &p1,
00409 const Position2D &p2) const {
00410 return atan2(p1.x(), p1.y()) < atan2(p2.x(), p2.y());
00411 }
00412
00413
00414
00415 void
00416 Position2DVector::sortByIncreasingXY() {
00417 std::sort(myCont.begin(), myCont.end(), increasing_x_y_sorter());
00418 }
00419
00420
00421
00422 Position2DVector::increasing_x_y_sorter::increasing_x_y_sorter() {}
00423
00424
00425
00426 int
00427 Position2DVector::increasing_x_y_sorter::operator()(const Position2D &p1,
00428 const Position2D &p2) const {
00429 if (p1.x()!=p2.x()) {
00430 return p1.x()<p2.x();
00431 }
00432 return p1.y()<p2.y();
00433 }
00434
00435
00436
00437 SUMOReal
00438 Position2DVector::isLeft(const Position2D &P0, const Position2D &P1,
00439 const Position2D &P2) const {
00440 return (P1.x() - P0.x())*(P2.y() - P0.y()) - (P2.x() - P0.x())*(P1.y() - P0.y());
00441 }
00442
00443
00444 Position2DVector
00445 Position2DVector::convexHull() const {
00446 Position2DVector ret = *this;
00447 ret.sortAsPolyCWByAngle();
00448 return simpleHull_2D(ret);
00449 }
00450
00451
00452 void
00453 Position2DVector::set(size_t pos, const Position2D &p) {
00454 myCont[pos] = p;
00455 }
00456
00457
00458
00459 Position2DVector
00460 Position2DVector::intersectsAtPoints(const Position2D &p1,
00461 const Position2D &p2) const {
00462 Position2DVector ret;
00463 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00464 if (GeomHelper::intersects(*i, *(i+1), p1, p2)) {
00465 ret.push_back_noDoublePos(GeomHelper::intersection_position(*i, *(i+1), p1, p2));
00466 }
00467 }
00468 return ret;
00469 }
00470
00471
00472 int
00473 Position2DVector::appendWithCrossingPoint(const Position2DVector &v) {
00474 if (myCont.back().distanceTo(v.myCont[0])<2) {
00475 copy(v.myCont.begin()+1, v.myCont.end(), back_inserter(myCont));
00476 return 1;
00477 }
00478
00479 Line2D l1(myCont[myCont.size()-2], myCont.back());
00480 l1.extrapolateBy(100);
00481 Line2D l2(v.myCont[0], v.myCont[1]);
00482 l2.extrapolateBy(100);
00483 if (l1.intersects(l2)&&l1.intersectsAtLength(l2)<l1.length()-100) {
00484 Position2D p = l1.intersectsAt(l2);
00485 myCont[myCont.size()-1] = p;
00486 copy(v.myCont.begin()+1, v.myCont.end(), back_inserter(myCont));
00487 return 2;
00488 } else {
00489 copy(v.myCont.begin(), v.myCont.end(), back_inserter(myCont));
00490 return 3;
00491 }
00492 }
00493
00494
00495 Position2DVector
00496 Position2DVector::getSubpart(SUMOReal begin, SUMOReal end) const {
00497 Position2DVector ret;
00498 Position2D begPos = positionAtLengthPosition(begin);
00499 Position2D endPos = myCont.back();
00500 if (length()>end) {
00501 endPos = positionAtLengthPosition(end);
00502 }
00503 ret.push_back(begPos);
00504
00505 SUMOReal seen = 0;
00506 ContType::const_iterator i = myCont.begin();
00507
00508 while ((i+1)!=myCont.end()
00509 &&
00510 seen+(*i).distanceTo(*(i+1))<begin) {
00511 seen += (*i).distanceTo(*(i+1));
00512 i++;
00513 }
00514
00515 while ((i+1)!=myCont.end()
00516 &&
00517 seen+(*i).distanceTo(*(i+1))<end) {
00518
00519 ret.push_back_noDoublePos(*(i+1));
00520
00521
00522
00523
00524
00525 seen += (*i).distanceTo(*(i+1));
00526 i++;
00527 }
00528
00529 ret.push_back_noDoublePos(endPos);
00530 return ret;
00531 }
00532
00533
00534 void
00535 Position2DVector::pruneFromBeginAt(const Position2D &p) {
00536
00537 size_t pos = 0;
00538 SUMOReal dist = 1000000;
00539 size_t currPos = 0;
00540 SUMOReal currDist = GeomHelper::distancePointLine(p,
00541 GeomHelper::extrapolate_first(*(myCont.begin()), *(myCont.begin()+1), 100),
00542 *(myCont.begin()+1));
00543
00544 if (currDist>=0&&currDist<dist) {
00545 dist = currDist;
00546 pos = currPos;
00547 }
00548
00549 for (ContType::iterator i=myCont.begin(); i!=myCont.end()-1; i++, currPos++) {
00550 SUMOReal currDist = GeomHelper::distancePointLine(p, *i, *(i+1));
00551 if (currDist>=0&&currDist<dist) {
00552 dist = currDist;
00553 pos = currPos;
00554 }
00555 }
00556
00557 for (size_t j=0; j<pos; j++) {
00558 myCont.erase(myCont.begin());
00559 }
00560
00561 SUMOReal lpos = GeomHelper::nearest_position_on_line_to_point(
00562 myCont[0], myCont[1], p);
00563 if (lpos==-1) {
00564 return;
00565 }
00566 Position2D np = positionAtLengthPosition(lpos);
00567 if (np!=*(myCont.begin())) {
00568 myCont.erase(myCont.begin());
00569 if (np!=*(myCont.begin())) {
00570 myCont.push_front(np);
00571 assert(myCont.size()>1);
00572 assert(*(myCont.begin())!=*(myCont.end()-1));
00573 }
00574 }
00575 }
00576
00577
00578 void
00579 Position2DVector::pruneFromEndAt(const Position2D &p) {
00580
00581 size_t pos = 0;
00582 SUMOReal dist = 1000000;
00583 size_t currPos = 0;
00584 SUMOReal currDist = GeomHelper::distancePointLine(p,
00585 *(myCont.end()-1),
00586 GeomHelper::extrapolate_second(*(myCont.end()-2), *(myCont.end()-1), 100));
00587
00588 if (currDist>=0&&currDist<dist) {
00589 dist = currDist;
00590 pos = currPos;
00591 }
00592
00593 for (ContType::reverse_iterator i=myCont.rbegin(); i!=myCont.rend()-1; i++, currPos++) {
00594 SUMOReal currDist = GeomHelper::distancePointLine(p, *(i), *(i+1));
00595 if (currDist>=0&&currDist<dist) {
00596 dist = currDist;
00597 pos = currPos;
00598 }
00599 }
00600
00601 for (size_t j=0; j<pos; j++) {
00602 myCont.erase(myCont.end()-1);
00603 }
00604
00605 SUMOReal lpos =
00606 GeomHelper::nearest_position_on_line_to_point(
00607 myCont[myCont.size()-1], myCont[myCont.size()-2], p);
00608 if (lpos==-1) {
00609 return;
00610 }
00611 Position2D np = positionAtLengthPosition(
00612 length() - lpos);
00613 if (np!=*(myCont.end()-1)) {
00614 myCont.erase(myCont.end()-1);
00615 if (np!=*(myCont.end()-1)) {
00616 myCont.push_back(np);
00617 assert(myCont.size()>1);
00618 assert(*(myCont.begin())!=*(myCont.end()-1));
00619 }
00620 }
00621 }
00622
00623
00624 SUMOReal
00625 Position2DVector::beginEndAngle() const {
00626 Line2D tmp(getBegin(), getEnd());
00627 return tmp.atan2Angle();
00628 }
00629
00630
00631 void
00632 Position2DVector::eraseAt(int i) {
00633 if (i>=0) {
00634 myCont.erase(myCont.begin()+i);
00635 } else {
00636 myCont.erase(myCont.end()+i);
00637 }
00638 }
00639
00640
00641 SUMOReal
00642 Position2DVector::nearest_position_on_line_to_point(const Position2D &p) const {
00643 SUMOReal shortestDist = -1;
00644 SUMOReal nearestPos = -1;
00645 SUMOReal seen = 0;
00646 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00647 SUMOReal pos =
00648 GeomHelper::nearest_position_on_line_to_point(*i, *(i+1), p);
00649 SUMOReal dist =
00650 pos < 0 ? -1 : p.distanceTo(positionAtLengthPosition(pos+seen));
00651
00652 if (dist>=0&&(shortestDist<0||shortestDist>dist)) {
00653 nearestPos = pos+seen;
00654 shortestDist = dist;
00655 }
00656 seen += (*i).distanceTo(*(i+1));
00657
00658 }
00659 return nearestPos;
00660 }
00661
00662
00663 SUMOReal
00664 Position2DVector::distance(const Position2D &p) const {
00665 SUMOReal shortestDist = 10000000;
00666 SUMOReal nearestPos = 10000;
00667 SUMOReal seen = 0;
00668 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00669 SUMOReal pos = seen +
00670 GeomHelper::nearest_position_on_line_to_point(*i, *(i+1), p);
00671 SUMOReal dist = p.distanceTo(positionAtLengthPosition(pos));
00672
00673 if (shortestDist>dist) {
00674 nearestPos = pos;
00675 shortestDist = dist;
00676 }
00677
00678 }
00679 if (shortestDist==10000000) {
00680 return -1;
00681 }
00682 return shortestDist;
00683 }
00684
00685
00686 DoubleVector
00687 Position2DVector::intersectsAtLengths(const Position2DVector &s) const {
00688 DoubleVector ret;
00689 SUMOReal pos = 0;
00690 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00691 Line2D l((*i), *(i+1));
00692 DoubleVector atSegment = l.intersectsAtLengths(s);
00693 VectorHelper<SUMOReal>::add2All(atSegment, pos);
00694 copy(atSegment.begin(), atSegment.end(), back_inserter(ret));
00695 pos += l.length();
00696 }
00697 return ret;
00698 }
00699
00700
00701 DoubleVector
00702 Position2DVector::intersectsAtLengths(const Line2D &s) const {
00703 DoubleVector ret;
00704 SUMOReal pos = 0;
00705 for (ContType::const_iterator i=myCont.begin(); i!=myCont.end()-1; i++) {
00706 Line2D l((*i), *(i+1));
00707 if (GeomHelper::intersects(l.p1(), l.p2(), s.p1(), s.p2())) {
00708 Position2D p =
00709 GeomHelper::intersection_position(l.p1(), l.p2(), s.p1(), s.p2());
00710 SUMOReal atLength = p.distanceTo(l.p1());
00711 ret.push_back(atLength+pos);
00712 }
00713 pos += l.length();
00714 }
00715 return ret;
00716 }
00717
00718
00719 void
00720 Position2DVector::extrapolate(SUMOReal val) {
00721 assert(myCont.size()>1);
00722 Position2D nb =
00723 GeomHelper::extrapolate_first(myCont[0], myCont[1], val);
00724 Position2D ne =
00725 GeomHelper::extrapolate_second(
00726 myCont[myCont.size()-2], myCont[myCont.size()-1], val);
00727 myCont.erase(myCont.begin());
00728 push_front(nb);
00729 myCont.erase(myCont.end()-1);
00730 push_back(ne);
00731 }
00732
00733
00734 Position2DVector
00735 Position2DVector::reverse() const {
00736 Position2DVector ret;
00737 for (ContType::const_reverse_iterator i=myCont.rbegin(); i!=myCont.rend(); i++) {
00738 ret.push_back(*i);
00739 }
00740 return ret;
00741 }
00742
00743
00744 void
00745 Position2DVector::move2side(SUMOReal amount, int index) {
00746 if (index<0) {
00747 index = (int) myCont.size() + index;
00748 }
00749 if (index==0) {
00750 Position2D from = myCont[index];
00751 Position2D to = myCont[index+1];
00752 std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, to, amount);
00753 myCont[index] = Position2D(from.x()-offsets.first, from.y()-offsets.second);
00754 } else if (index==(int) myCont.size()-1) {
00755 Position2D from = myCont[index-1];
00756 Position2D to = myCont[index];
00757 std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, to, amount);
00758 myCont[index] = Position2D(to.x()-offsets.first, to.y()-offsets.second);
00759 } else {
00760 Position2D from = myCont[index-1];
00761 Position2D me = myCont[index];
00762 Position2D to = myCont[index+1];
00763 std::pair<SUMOReal, SUMOReal> offsets = GeomHelper::getNormal90D_CW(from, me, amount);
00764 std::pair<SUMOReal, SUMOReal> offsets2 = GeomHelper::getNormal90D_CW(me, to, amount);
00765 Line2D l1(
00766 Position2D(from.x()-offsets.first, from.y()-offsets.second),
00767 Position2D(me.x()-offsets.first, me.y()-offsets.second));
00768 l1.extrapolateBy(100);
00769 Line2D l2(
00770 Position2D(me.x()-offsets2.first, me.y()-offsets2.second),
00771 Position2D(to.x()-offsets2.first, to.y()-offsets2.second));
00772 l2.extrapolateBy(100);
00773 if (l1.intersects(l2)) {
00774 myCont[index] = l1.intersectsAt(l2);
00775 } else {
00776 throw InvalidArgument("no line intersection");
00777 }
00778 }
00779
00780 }
00781
00782 void
00783 Position2DVector::move2side(SUMOReal amount) {
00784 if (myCont.size()<2) {
00785 return;
00786 }
00787 Position2DVector shape;
00788 for (size_t i=0; i<myCont.size(); i++) {
00789 if (i==0) {
00790 Position2D from = myCont[i];
00791 Position2D to = myCont[i+1];
00792 std::pair<SUMOReal, SUMOReal> offsets =
00793 GeomHelper::getNormal90D_CW(from, to, amount);
00794 shape.push_back(
00795
00796 Position2D(from.x()-offsets.first, from.y()-offsets.second));
00797 } else if (i==myCont.size()-1) {
00798 Position2D from = myCont[i-1];
00799 Position2D to = myCont[i];
00800 std::pair<SUMOReal, SUMOReal> offsets =
00801 GeomHelper::getNormal90D_CW(from, to, amount);
00802 shape.push_back(
00803
00804 Position2D(to.x()-offsets.first, to.y()-offsets.second));
00805 } else {
00806 Position2D from = myCont[i-1];
00807 Position2D me = myCont[i];
00808 Position2D to = myCont[i+1];
00809 double sinAngle = sin(GeomHelper::Angle2D(from.x()-me.x(), from.y()-me.y(),
00810 me.x()-to.x(), me.y()-to.y())/2);
00811 double maxDev = 2 * (from.distanceTo(me) + me.distanceTo(to)) * sinAngle;
00812 if (fabs(maxDev)<POSITION_EPS) {
00813
00814 std::pair<SUMOReal, SUMOReal> off =
00815 GeomHelper::getNormal90D_CW(from, to, amount);
00816 shape.push_back(Position2D(me.x()-off.first, me.y()-off.second));
00817 continue;
00818 }
00819 std::pair<SUMOReal, SUMOReal> offsets =
00820 GeomHelper::getNormal90D_CW(from, me, amount);
00821 std::pair<SUMOReal, SUMOReal> offsets2 =
00822 GeomHelper::getNormal90D_CW(me, to, amount);
00823 Line2D l1(
00824 Position2D(from.x()-offsets.first, from.y()-offsets.second),
00825 Position2D(me.x()-offsets.first, me.y()-offsets.second));
00826 l1.extrapolateBy(100);
00827 Line2D l2(
00828 Position2D(me.x()-offsets2.first, me.y()-offsets2.second),
00829 Position2D(to.x()-offsets2.first, to.y()-offsets2.second));
00830 l2.extrapolateBy(100);
00831 if (l1.intersects(l2)) {
00832 shape.push_back(
00833
00834 l1.intersectsAt(l2));
00835 } else {
00836 throw InvalidArgument("no line intersection");
00837 }
00838 }
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867 myCont = shape.myCont;
00868 }
00869
00870
00871 Line2D
00872 Position2DVector::lineAt(size_t pos) const {
00873 assert(myCont.size()>pos+1);
00874 return Line2D(myCont[pos], myCont[pos+1]);
00875 }
00876
00877
00878 Line2D
00879 Position2DVector::getBegLine() const {
00880 return lineAt(0);
00881 }
00882
00883
00884 Line2D
00885 Position2DVector::getEndLine() const {
00886 return lineAt(myCont.size()-2);
00887 }
00888
00889
00890 void
00891 Position2DVector::closePolygon() {
00892 if (myCont[0]==myCont.back()) {
00893 return;
00894 }
00895 push_back(myCont[0]);
00896 }
00897
00898 DoubleVector
00899 Position2DVector::distances(const Position2DVector &s) const {
00900 DoubleVector ret;
00901 ContType::const_iterator i;
00902 for (i=myCont.begin(); i!=myCont.end(); i++) {
00903 SUMOReal dist = s.distance(*i);
00904
00905 if (dist!=-1) {
00906 ret.push_back(dist);
00907 }
00908 }
00909 for (i=s.myCont.begin(); i!=s.myCont.end(); i++) {
00910 SUMOReal dist = distance(*i);
00911
00912 if (dist!=-1) {
00913 ret.push_back(dist);
00914 }
00915 }
00916 return ret;
00917 }
00918
00919
00920 DoubleVector
00921 Position2DVector::distancesExt(const Position2DVector &s) const {
00922 DoubleVector ret = distances(s);
00923 ContType::const_iterator i;
00924 for (i=myCont.begin(); i!=myCont.end()-1; i++) {
00925 Position2D p = Position2D(*i);
00926 p.add(*(i+1));
00927 p.mul(0.5);
00928 SUMOReal dist = s.distance(p);
00929
00930 if (dist!=-1) {
00931 ret.push_back(dist);
00932 }
00933 }
00934 for (i=s.myCont.begin(); i!=s.myCont.end()-1; i++) {
00935 Position2D p = Position2D(*i);
00936 p.add(*(i+1));
00937 p.mul(0.5);
00938 SUMOReal dist = s.distance(p);
00939
00940 if (dist!=-1) {
00941 ret.push_back(dist);
00942 }
00943 }
00944 return ret;
00945 }
00946
00947
00948 Position2D
00949 Position2DVector::pop_back() {
00950 Position2D last = myCont.back();
00951 myCont.erase(myCont.end()-1);
00952 return last;
00953 }
00954
00955
00956 Position2D
00957 Position2DVector::pop_front() {
00958 Position2D first = myCont.front();
00959 myCont.erase(myCont.begin());
00960 return first;
00961 }
00962
00963
00964 void
00965 Position2DVector::insertAt(int index, const Position2D &p) {
00966 if (index>=0) {
00967 myCont.insert(myCont.begin()+index, p);
00968 } else {
00969 myCont.insert(myCont.end()+index, p);
00970 }
00971 }
00972
00973
00974 void
00975 Position2DVector::push_back_noDoublePos(const Position2D &p) {
00976 if (size()==0 || !p.almostSame(myCont.back())) {
00977 myCont.push_back(p);
00978 }
00979 }
00980
00981
00982 void
00983 Position2DVector::push_front_noDoublePos(const Position2D &p) {
00984 if (size()==0 || !p.almostSame(myCont.front())) {
00985 myCont.push_front(p);
00986 }
00987 }
00988
00989
00990 void
00991 Position2DVector::replaceAt(size_t index, const Position2D &by) {
00992 assert(size()>index);
00993 myCont[index] = by;
00994 }
00995
00996
00997 bool
00998 Position2DVector::isClosed() const {
00999 return myCont.size()>=2&&myCont[0]==myCont.back();
01000 }
01001
01002
01003 void
01004 Position2DVector::removeDoublePoints() {
01005 if (myCont.size() > 1) {
01006 ContType::iterator last = myCont.begin();
01007 for (ContType::iterator i=myCont.begin()+1; i!=myCont.end();) {
01008 if (last->almostSame(*i)) {
01009 i = myCont.erase(i);
01010 } else {
01011 last = i;
01012 ++i;
01013 }
01014 }
01015 }
01016 }
01017
01018
01019 void
01020 Position2DVector::removeColinearPoints() {
01021 if (myCont.size() > 2) {
01022 Position2D& last = myCont.front();
01023 for (ContType::iterator i=myCont.begin()+1; i!=myCont.end()-1;) {
01024 if (GeomHelper::distancePointLine(*i, last, *(i+1)) < 0.001) {
01025 i = myCont.erase(i);
01026 } else {
01027 last = *i;
01028 ++i;
01029 }
01030 }
01031 }
01032 }
01033
01034
01035
01036