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 <cmath>
00031 #include <algorithm>
00032 #include <iostream>
00033 #include "GeomHelper.h"
00034 #include <utils/common/StdDefs.h>
00035 #include <utils/common/ToString.h>
00036
00037 #ifdef CHECK_MEMORY_LEAKS
00038 #include <foreign/nvwa/debug_new.h>
00039 #endif // CHECK_MEMORY_LEAKS
00040
00041
00042
00043
00044
00045 bool
00046 GeomHelper::intersects(SUMOReal x1, SUMOReal y1, SUMOReal x2, SUMOReal y2,
00047 SUMOReal x3, SUMOReal y3, SUMOReal x4, SUMOReal y4) {
00048
00049
00050
00051 SUMOReal a1 = y2 - y1;
00052 SUMOReal b1 = x1 - x2;
00053 SUMOReal c1 = x2 * y1 - x1 * y2;
00054
00055
00056
00057 SUMOReal r3 = SUMOReal(a1 * x3 + b1 * y3 + c1);
00058 SUMOReal r4 = SUMOReal(a1 * x4 + b1 * y4 + c1);
00059
00060
00061
00062
00063 if (r3 != 0 &&
00064 r4 != 0 &&
00065 ((r3<0&&r4<0)||(r3>0&&r4>0)))
00066 return (false);
00067
00068
00069 SUMOReal a2 = y4 - y3;
00070 SUMOReal b2 = x3 - x4;
00071 SUMOReal c2 = x4 * y3 - x3 * y4;
00072
00073
00074 SUMOReal r1 = a2 * x1 + b2 * y1 + c2;
00075 SUMOReal r2 = a2 * x2 + b2 * y2 + c2;
00076
00077
00078
00079
00080
00081 if (r1 != 0 &&
00082 r2 != 0 &&
00083 ((r1<0&&r2<0)||(r1>0&&r2>0)))
00084 return (false);
00085
00086
00087
00088 SUMOReal denom = a1 * b2 - a2 * b1;
00089 if (denom == 0)
00090 return (false);
00091
00092
00093 return true;
00094 }
00095
00096
00097
00098
00099 bool
00100 GeomHelper::intersects(const Position2D &p11, const Position2D &p12,
00101 const Position2D &p21, const Position2D &p22) {
00102 return intersects(p11.x(), p11.y(), p12.x(), p12.y(),
00103 p21.x(), p21.y(), p22.x(), p22.y());
00104 }
00105
00106
00107 Position2D
00108 GeomHelper::intersection_position(const Position2D &p11,
00109 const Position2D &p12,
00110 const Position2D &p21,
00111 const Position2D &p22) {
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 double a1,b1,c1,
00124 a2,b2,c2,
00125 det_inv, m1, m2;
00126
00127
00128
00129
00130 if ((p12.x()-p11.x())!=0)
00131 m1 = (p12.y()-p11.y())/(p12.x()-p11.x());
00132 else
00133 m1 = (SUMOReal)1e+10;
00134
00135 if ((p22.x()-p21.x())!=0)
00136 m2 = (p22.y()-p21.y())/(p22.x()-p21.x());
00137 else
00138 m2 = (SUMOReal)1e+10;
00139
00140
00141
00142 a1 = m1;
00143 a2 = m2;
00144
00145 b1 = -1;
00146 b2 = -1;
00147
00148 c1 = (p11.y()-m1*p11.x());
00149 c2 = (p21.y()-m2*p21.x());
00150
00151
00152 det_inv = 1/(a1*b2 - a2*b1);
00153
00154
00155 return Position2D(
00156 ((b1*c2 - b2*c1)*det_inv),
00157 ((a2*c1 - a1*c2)*det_inv));
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167 SUMOReal
00168 GeomHelper::Angle2D(SUMOReal x1, SUMOReal y1, SUMOReal x2, SUMOReal y2) {
00169 SUMOReal dtheta,theta1,theta2;
00170
00171 theta1 = atan2(y1,x1);
00172 theta2 = atan2(y2,x2);
00173 dtheta = theta2 - theta1;
00174 while (dtheta > (SUMOReal) PI)
00175 dtheta -= (SUMOReal)(2.0*PI);
00176 while (dtheta < (SUMOReal) -PI)
00177 dtheta += (SUMOReal)(2.0*PI);
00178
00179 return(dtheta);
00180 }
00181
00182
00183 Position2D
00184 GeomHelper::interpolate(const Position2D &p1,
00185 const Position2D &p2, SUMOReal length) {
00186 SUMOReal oldlen = p1.distanceTo(p2);
00187 SUMOReal x = p1.x() + (p2.x() - p1.x()) * length / oldlen;
00188 SUMOReal y = p1.y() + (p2.y() - p1.y()) * length / oldlen;
00189 return Position2D(x, y);
00190 }
00191
00192
00193 Position2D
00194 GeomHelper::extrapolate_first(const Position2D &p1,
00195 const Position2D &p2, SUMOReal length) {
00196 SUMOReal oldlen = p1.distanceTo(p2);
00197 SUMOReal x = p1.x() - (p2.x() - p1.x()) * (length) / oldlen;
00198 SUMOReal y = p1.y() - (p2.y() - p1.y()) * (length) / oldlen;
00199 return Position2D(x, y);
00200 }
00201
00202
00203 Position2D
00204 GeomHelper::extrapolate_second(const Position2D &p1,
00205 const Position2D &p2, SUMOReal length) {
00206 SUMOReal oldlen = p1.distanceTo(p2);
00207 SUMOReal x = p2.x() - (p1.x() - p2.x()) * (length) / oldlen;
00208 SUMOReal y = p2.y() - (p1.y() - p2.y()) * (length) / oldlen;
00209 return Position2D(x, y);
00210 }
00211
00212
00213 SUMOReal
00214 GeomHelper::nearest_position_on_line_to_point(const Position2D &LineStart,
00215 const Position2D &LineEnd,
00216 const Position2D &Point) {
00217 SUMOReal u = (((Point.x() - LineStart.x()) * (LineEnd.x() - LineStart.x())) +
00218 ((Point.y() - LineStart.y()) * (LineEnd.y() - LineStart.y()))
00219 ) / LineStart.distanceSquaredTo(LineEnd);
00220 if (u < 0.0f || u > 1.0f)
00221 return -1;
00222 return u * LineStart.distanceTo(LineEnd);
00223 }
00224
00225
00226 SUMOReal
00227 GeomHelper::distancePointLine(const Position2D &point,
00228 const Position2D &lineStart,
00229 const Position2D &lineEnd) {
00230 SUMOReal u = (((point.x() - lineStart.x()) * (lineEnd.x() - lineStart.x())) +
00231 ((point.y() - lineStart.y()) * (lineEnd.y() - lineStart.y()))
00232 ) / lineStart.distanceSquaredTo(lineEnd);
00233 if (u < 0.0f || u > 1.0f)
00234 return -1;
00235 Position2D intersection(
00236 lineStart.x() + u *(lineEnd.x() - lineStart.x()),
00237 lineStart.y() + u *(lineEnd.y() - lineStart.y()));
00238 return point.distanceTo(intersection);
00239 }
00240
00241
00242
00243 SUMOReal
00244 GeomHelper::closestDistancePointLine(const Position2D &point,
00245 const Position2D &lineStart,
00246 const Position2D &lineEnd,
00247 Position2D& outIntersection) {
00248 Position2D directVec(lineEnd.x()-lineStart.x(), lineEnd.y()-lineStart.y());
00249 SUMOReal u = (((point.x() - lineStart.x()) * directVec.x()) +
00250 ((point.y() - lineStart.y()) * directVec.y())) /
00251 (directVec.x() * directVec.x() +
00252 directVec.y() * directVec.y());
00253
00254
00255
00256
00257 if (u >= 0.0f && u <= 1.0f) {
00258 outIntersection.set(
00259 lineStart.x() + u * directVec.x(),
00260 lineStart.y() + u * directVec.y());
00261 } else {
00262 if (u < 0.0f) {
00263 outIntersection = lineStart;
00264 }
00265 if (u > 1.0f) {
00266 outIntersection = lineEnd;
00267 }
00268 }
00269 return point.distanceTo(outIntersection);
00270 }
00271
00272
00273
00274 Position2D
00275 GeomHelper::transfer_to_side(Position2D &p,
00276 const Position2D &lineBeg,
00277 const Position2D &lineEnd,
00278 SUMOReal amount) {
00279 SUMOReal dx = lineBeg.x() - lineEnd.x();
00280 SUMOReal dy = lineBeg.y() - lineEnd.y();
00281 SUMOReal length = sqrt(
00282 (lineBeg.x() - lineEnd.x())*(lineBeg.x() - lineEnd.x())
00283 +
00284 (lineBeg.y() - lineEnd.y())*(lineBeg.y() - lineEnd.y()));
00285 if (dx<0) {
00286 if (dy>0) {
00287 p.add(dy*amount/length, -dx*amount/length);
00288 } else if (dy<0) {
00289 p.add(dy*amount/length, -dx*amount/length);
00290 } else {
00291 p.add(0, -dx*amount/length);
00292 }
00293 } else if (dx>0) {
00294 if (dy>0) {
00295 p.add(dy*amount/length, -dx*amount/length);
00296 } else if (dy<0) {
00297 p.add(dy*amount/length, -dx*amount/length);
00298 } else {
00299 p.add(0, -dx*amount/length);
00300 }
00301 } else {
00302 if (dy>0) {
00303 p.add(dy*amount/length, 0);
00304 } else if (dy<0) {
00305 p.add(dy*amount/length, 0);
00306 } else {
00307 throw 1;
00308 }
00309 }
00310 return p;
00311 }
00312
00313
00314
00315 Position2D
00316 GeomHelper::crossPoint(const Boundary &b, const Position2DVector &v) {
00317 if (v.intersects(Position2D(b.xmin(), b.ymin()), Position2D(b.xmin(), b.ymax()))) {
00318 return v.intersectsAtPoint(
00319 Position2D(b.xmin(), b.ymin()),
00320 Position2D(b.xmin(), b.ymax()));
00321 }
00322 if (v.intersects(Position2D(b.xmax(), b.ymin()), Position2D(b.xmax(), b.ymax()))) {
00323 return v.intersectsAtPoint(
00324 Position2D(b.xmax(), b.ymin()),
00325 Position2D(b.xmax(), b.ymax()));
00326 }
00327 if (v.intersects(Position2D(b.xmin(), b.ymin()), Position2D(b.xmax(), b.ymin()))) {
00328 return v.intersectsAtPoint(
00329 Position2D(b.xmin(), b.ymin()),
00330 Position2D(b.xmax(), b.ymin()));
00331 }
00332 if (v.intersects(Position2D(b.xmin(), b.ymax()), Position2D(b.xmax(), b.ymax()))) {
00333 return v.intersectsAtPoint(
00334 Position2D(b.xmin(), b.ymax()),
00335 Position2D(b.xmax(), b.ymax()));
00336 }
00337 throw 1;
00338 }
00339
00340 std::pair<SUMOReal, SUMOReal>
00341 GeomHelper::getNormal90D_CW(const Position2D &beg,
00342 const Position2D &end,
00343 SUMOReal wanted_offset) {
00344 SUMOReal length = sqrt((beg.x()-end.x())*(beg.x()-end.x()) + (beg.y()-end.y())*(beg.y()-end.y()));
00345 return getNormal90D_CW(beg, end, length, wanted_offset);
00346 }
00347
00348
00349 std::pair<SUMOReal, SUMOReal>
00350 GeomHelper::getNormal90D_CW(const Position2D &beg,
00351 const Position2D &end,
00352 SUMOReal length, SUMOReal wanted_offset) {
00353 if (beg == end) {
00354 throw InvalidArgument("same points at " + toString(beg));
00355 }
00356 return std::pair<SUMOReal, SUMOReal>
00357 ((beg.y()-end.y())*wanted_offset/length, (end.x()-beg.x())*wanted_offset/length);
00358 }
00359
00360
00361 SUMOReal
00362 GeomHelper::getCCWAngleDiff(SUMOReal angle1, SUMOReal angle2) throw() {
00363 if (angle1<0) {
00364 angle1 = 360 + angle1;
00365 }
00366 if (angle2<0) {
00367 angle2 = 360 + angle2;
00368 }
00369 if (angle1>=angle2) {
00370 return angle1 - angle2;
00371 }
00372 return angle1 + 360 - angle2;
00373 }
00374
00375
00376 SUMOReal
00377 GeomHelper::getCWAngleDiff(SUMOReal angle1, SUMOReal angle2) throw() {
00378 if (angle1<0) {
00379 angle1 = 360 + angle1;
00380 }
00381 if (angle2<0) {
00382 angle2 = 360 + angle2;
00383 }
00384 if (angle1<=angle2) {
00385 return angle2 - angle1;
00386 }
00387 return 360 - angle1 + angle2;
00388 }
00389
00390
00391 SUMOReal
00392 GeomHelper::getMinAngleDiff(SUMOReal angle1, SUMOReal angle2) throw() {
00393 return MIN2(getCWAngleDiff(angle1, angle2), getCCWAngleDiff(angle1, angle2));
00394 }
00395
00396
00397 SUMOReal
00398 GeomHelper::getMaxAngleDiff(SUMOReal angle1, SUMOReal angle2) throw() {
00399 return MAX2(getCWAngleDiff(angle1, angle2), getCCWAngleDiff(angle1, angle2));
00400 }
00401
00402
00403
00404
00405