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