Position2DVector.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // A list of 2D-positions
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright 2001-2010 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 
00020 
00021 // ===========================================================================
00022 // included modules
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 // method definitions
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 // ------------ Adding items to the container
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         //throw 1; // !!! not yet implemented
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     //return GeomHelper::intersects(*(myCont.end()-1), *(myCont.begin()), p1, p2);
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     //return v1.intersects(*(myCont.end()-1), *(myCont.begin()));
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     if(v1.intersects(*(myCont.end()-1), *(myCont.begin()))) {
00168         return v1.intersectsAtPoint(*(myCont.end()-1), *(myCont.begin()));
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 //    return positionAtLengthPosition(*(myCont.end()-1),
00221 //        *(myCont.begin()), pos-seenLength);
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 //    Line2D l(*(myCont.end()-1), *(myCont.begin()));
00240 //    return l.atan2DegreeAngle();
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) { // !!! heuristic
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) { // !!! heuristic
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     // skip previous segments
00508     while ((i+1)!=myCont.end()
00509             &&
00510             seen+(*i).distanceTo(*(i+1))<begin) {
00511         seen += (*i).distanceTo(*(i+1));
00512         i++;
00513     }
00514     // append segments in between
00515     while ((i+1)!=myCont.end()
00516             &&
00517             seen+(*i).distanceTo(*(i+1))<end) {
00518 
00519         ret.push_back_noDoublePos(*(i+1));
00520         /*
00521         if(ret.at(-1)!=*(i+1)) {
00522             ret.push_back(*(i+1));
00523         }
00524         */
00525         seen += (*i).distanceTo(*(i+1));
00526         i++;
00527     }
00528     // append end
00529     ret.push_back_noDoublePos(endPos);
00530     return ret;
00531 }
00532 
00533 
00534 void
00535 Position2DVector::pruneFromBeginAt(const Position2D &p) {
00536     // find minimum distance (from the begin)
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 //    assert(currDist>=0);
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     // remove leading items
00557     for (size_t j=0; j<pos; j++) {
00558         myCont.erase(myCont.begin());
00559     }
00560     // replace first item by the new position
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     // find minimum distance (from the end)
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 //    assert(currDist>=0);
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     // remove trailing items
00601     for (size_t j=0; j<pos; j++) {
00602         myCont.erase(myCont.end()-1);
00603     }
00604     // replace last item by the new position
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 (/*i==myGeom.size()-2||*/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==myGeom.size()-2||*/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(//.push_back(
00795                 // (methode umbenennen; was heisst hier "-")
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(//.push_back(
00803                 // (methode umbenennen; was heisst hier "-")
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                 // parallel case, just shift the middle point
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(//.push_back(
00833                     // (methode umbenennen; was heisst hier "-")
00834                     l1.intersectsAt(l2));
00835             } else {
00836                 throw InvalidArgument("no line intersection");
00837             }
00838         }
00839     }
00840 
00841     /*
00842     ContType newCont;
00843     std::pair<SUMOReal, SUMOReal> p;
00844     Position2D newPos;
00845     // first point
00846     newPos = (*(myCont.begin()));
00847     p = GeomHelper::getNormal90D_CW(*(myCont.begin()), *(myCont.begin()+1), amount);
00848     newPos.add(p.first, p.second);
00849     newCont.push_back(newPos);
00850     // middle points
00851     for(ContType::const_iterator i=myCont.begin()+1; i!=myCont.end()-1; i++) {
00852         std::pair<SUMOReal, SUMOReal> oldp = p;
00853         newPos = *i;
00854         newPos.add(p.first, p.second);
00855         newCont.push_back(newPos);
00856         p = GeomHelper::getNormal90D_CW(*i, *(i+1), amount);
00857     //        Position2D newPos(*i);
00858     //        newPos.add((p.first+oldp.first)/2.0, (p.second+oldp.second)/2.0);
00859     //        newCont.push_back(newPos);
00860     }
00861     // last point
00862     newPos = (*(myCont.end()-1));
00863     newPos.add(p.first, p.second);
00864     newCont.push_back(newPos);
00865     myCont = newCont;
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         // !!! aeh, possible at the ends?
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         // !!! aeh, possible at the ends?
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         // !!! aeh, possible at the ends?
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         // !!! aeh, possible at the ends?
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 

Generated on Wed May 5 00:06:35 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6