00001
00002
00003
00004
00005
00006
00007
00008
00050 #ifdef _MSC_VER
00051 #pragma once
00052 #endif
00053
00054 #ifndef OGDF_GEOMETRIC_H
00055 #define OGDF_GEOMETRIC_H
00056
00057 #include <float.h>
00058 #include <math.h>
00059
00060 #include <ogdf/basic/List.h>
00061 #include <ogdf/basic/Hashing.h>
00062
00063 #define GEOMETRIC_CMP_EPS 1e-06
00064
00065 namespace ogdf {
00066
00068 enum Orientation {
00069 topToBottom,
00070 bottomToTop,
00071 leftToRight,
00072 rightToLeft
00073 };
00074
00075
00076
00077
00078 inline
00079 bool DIsEqual(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00080 {
00081 return (a < (b + eps) && a > (b - eps));
00082 }
00083
00084 inline
00085 bool DIsGreaterEqual(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00086 {
00087 return (a > (b - eps));
00088 }
00089
00090 inline
00091 bool DIsGreater(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00092 {
00093 return (a > (b + eps));
00094 }
00095
00096 inline
00097 bool DIsLessEqual(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00098 {
00099 return (a < (b + eps));
00100 }
00101
00102 inline
00103 bool DIsLess(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00104 {
00105 return (a < (b - eps));
00106 }
00107
00108 inline
00109 double DRound(const double &d, int prec = 0)
00110 {
00111 if (prec == 0)
00112 return floor(d + 0.5);
00113 double factor = pow(10.0, ((double) prec));
00114 return DRound(d * factor, 0) / factor;
00115 }
00116
00125 template <class NUMBER>
00126 class GenericPoint
00127 {
00128 public:
00130 typedef NUMBER numberType;
00131
00132 NUMBER m_x;
00133 NUMBER m_y;
00134
00136
00140 GenericPoint() { }
00141
00143 GenericPoint(NUMBER x, NUMBER y) : m_x(x), m_y(y) { }
00144
00146 GenericPoint(const GenericPoint &ip) : m_x(ip.m_x), m_y(ip.m_y) { }
00147
00149 GenericPoint operator=(const GenericPoint &ip) {
00150 m_x = ip.m_x;
00151 m_y = ip.m_y;
00152 return *this;
00153 }
00154
00156 bool operator==(const GenericPoint &ip) const {
00157 return m_x == ip.m_x && m_y == ip.m_y;
00158 }
00159
00161 bool operator!=(const GenericPoint &ip) const {
00162 return m_x != ip.m_x || m_y != ip.m_y;
00163 }
00164
00165 };
00166
00167
00173 class IPoint : public GenericPoint<int>
00174 {
00175 public:
00177 IPoint() : GenericPoint<int>(0,0) { }
00178
00180 IPoint(int x, int y) : GenericPoint<int>(x,y) { }
00181
00183 IPoint(const IPoint &ip) : GenericPoint<int>(ip) { }
00184
00186 double distance(const IPoint &p) const;
00187 };
00188
00189
00191 ostream &operator<<(ostream &os, const IPoint &ip);
00192
00193
00194 template<> class DefHashFunc<IPoint>
00195 {
00196 public:
00197 int hash(const IPoint &ip) const {
00198 return 7*ip.m_x + 23*ip.m_y;
00199 }
00200 };
00201
00202
00211 class IPolyline : public List<IPoint> {
00212 public:
00214 IPolyline() { }
00215
00217 IPolyline(const IPolyline &ipl) : List<IPoint>(ipl) { }
00218
00220 IPolyline &operator=(const IPolyline &ipl) {
00221 List<IPoint>::operator =(ipl);
00222 return *this;
00223 }
00224
00226 double length() const;
00227 };
00228
00229
00230
00236 class DPoint : public GenericPoint<double>
00237 {
00238 public:
00240 DPoint() : GenericPoint<double>(0,0) { }
00241
00243 DPoint(double x, double y) : GenericPoint<double>(x,y) { }
00244
00246 DPoint(const DPoint &dp) : GenericPoint<double>(dp) { }
00247
00249 bool operator==(const DPoint &dp) const {
00250 return DIsEqual(m_x, dp.m_x) && DIsEqual(m_y,dp.m_y);
00251 }
00252
00254 DPoint operator+(const DPoint &p) const;
00255
00257 DPoint operator-(const DPoint &p) const;
00258
00260 double distance(const DPoint &p) const;
00261 };
00262
00264 ostream &operator<<(ostream &os, const DPoint &dp);
00265
00266
00270 class DVector : public DPoint {
00271 public:
00272
00274 DVector() : DPoint() { }
00275
00277 DVector(double x, double y) : DPoint(x, y) { }
00278
00280 DVector(const DVector &dv) : DPoint(dv) { }
00281
00283 DVector operator=(const DPoint &ip) {
00284 if (this != &ip)
00285 {
00286 m_x = ip.m_x;
00287 m_y = ip.m_y;
00288 }
00289 return *this;
00290 }
00291
00293 DVector operator*(const double val) const;
00294
00296 DVector operator/(const double val) const;
00297
00299 double length() const;
00300
00302 double operator^(const DVector &dv) const;
00303
00305 double operator*(const DVector &dv) const;
00306
00313 DVector operator++() const;
00314
00321 DVector operator--() const;
00322
00323
00324 };
00325
00326
00327
00335 class DPolyline : public List<DPoint> {
00336 static const double s_prec;
00337 public:
00339 DPolyline() { }
00340
00342 DPolyline(const DPolyline &dpl) : List<DPoint>(dpl) { }
00343
00345 DPolyline &operator=(const DPolyline &dpl) {
00346 List<DPoint>::operator =(dpl);
00347 return *this;
00348 }
00349
00351 double length() const;
00352
00360 DPoint position(const double fraction, double len = -1.0) const;
00361
00363 void writeGML(const char* filename) const;
00364
00366 void writeGML(ostream &stream) const;
00367
00369 void unify();
00370
00372 void normalize();
00373
00375 void convertToInt();
00376
00377
00378 };
00379
00380
00384 class DLine {
00385
00386 protected:
00387 DPoint m_start;
00388 DPoint m_end;
00389
00390 public:
00391
00393 DLine() : m_start(), m_end() {}
00394
00396 DLine(const DPoint &p1, const DPoint &p2) : m_start(p1), m_end(p2) {}
00397
00399 DLine(const DLine &dl) : m_start(dl.m_start), m_end(dl.m_end) {}
00400
00402 DLine(double x1, double y1, double x2, double y2) {
00403 m_start.m_x = x1; m_start.m_y = y1; m_end.m_x = x2; m_end.m_y = y2;
00404 }
00405
00407 bool operator==(const DLine &dl) const {
00408 return m_start == dl.m_start && m_end == dl.m_end;
00409 }
00410
00412 bool operator!=(const DLine &dl) const {
00413 return !(*this == dl);
00414 }
00415
00417 DLine &operator= (const DLine &dl) {
00418 if (this != &dl) {
00419 m_start = dl.m_start;
00420 m_end = dl.m_end;
00421 }
00422 return *this;
00423 }
00424
00426 const DPoint &start() const { return m_start; }
00427
00429 const DPoint &end() const { return m_end; }
00430
00432 double dx() const { return m_end.m_x - m_start.m_x; }
00433
00435 double dy() const { return m_end.m_y - m_start.m_y; }
00436
00438 double slope() const { return (dx() == 0) ? DBL_MAX : dy()/dx(); }
00439
00441 double yAbs() const { return (dx() == 0) ? DBL_MAX : m_start.m_y - (slope() * m_start.m_x); }
00442
00444 bool isVertical() const { return (DIsEqual(dx(), 0.0)); }
00445
00447 bool isHorizontal() const { return (DIsEqual(dy(), 0.0)); }
00448
00456 bool intersection(const DLine &line, DPoint &inter, bool endpoints = true) const;
00457
00459 bool contains(const DPoint &p) const;
00460
00462 double length() const {
00463 return m_start.distance(m_end);
00464 }
00465
00475 int horIntersection(const double horAxis, double &crossing) const;
00476
00477
00478
00488 int verIntersection(const double verAxis, double &crossing) const;
00489 };
00490
00492 ostream &operator<<(ostream &os, const DLine &dl);
00493
00494
00498 class DRect {
00499
00500 private:
00501 DPoint m_p1;
00502 DPoint m_p2;
00503
00504 public:
00506 DRect() : m_p1(), m_p2() {}
00507
00509 DRect(const DPoint &p1, const DPoint &p2) : m_p1(p1), m_p2(p2)
00510 { normalize(); }
00511
00513 DRect(double x1, double y1, double x2, double y2) {
00514 m_p1.m_x = x1; m_p1.m_y = y1; m_p2.m_x = x2; m_p2.m_y = y2;
00515 normalize();
00516 }
00517
00519 DRect(const DLine &dl) : m_p1(dl.start()), m_p2(dl.end())
00520 { normalize(); }
00521
00523 DRect(const DRect &dr) : m_p1(dr.m_p1), m_p2(dr.m_p2)
00524 { normalize(); }
00525
00527 bool operator==(const DRect &dr) const {
00528 return m_p1 == dr.m_p1 && m_p2 == dr.m_p2;
00529 }
00530
00532 bool operator!=(const DRect &dr) const {
00533 return !(*this == dr);
00534 }
00535
00537 DRect &operator= (const DRect &dr) {
00538 if (this != &dr) {
00539 m_p1 = dr.m_p1;
00540 m_p2 = dr.m_p2;
00541 }
00542 return *this;
00543 }
00544
00546 double width() const {
00547 return m_p2.m_x - m_p1.m_x;
00548 }
00549
00551 double height() const {
00552 return m_p2.m_y - m_p1.m_y;
00553 }
00554
00561 void normalize() {
00562 if (width() < 0) swap(m_p2.m_x, m_p1.m_x);
00563 if (height() < 0) swap(m_p2.m_y, m_p1.m_y);
00564 }
00565
00567 const DPoint &p1() const { return m_p1; }
00568
00570 const DPoint &p2() const { return m_p2; }
00571
00573 const DLine topLine() const {
00574 return DLine( DPoint(m_p1.m_x, m_p2.m_y), DPoint(m_p2.m_x, m_p2.m_y));
00575 }
00576
00578 const DLine rightLine() const {
00579 return DLine( DPoint(m_p2.m_x, m_p2.m_y), DPoint(m_p2.m_x, m_p1.m_y));
00580 }
00581
00583 const DLine leftLine() const {
00584 return DLine( DPoint(m_p1.m_x, m_p1.m_y), DPoint(m_p1.m_x, m_p2.m_y));
00585 }
00586
00588 const DLine bottomLine() const {
00589 return DLine( DPoint(m_p2.m_x, m_p1.m_y), DPoint(m_p1.m_x, m_p1.m_y));
00590 }
00591
00593 void yInvert() { swap(m_p1.m_y, m_p2.m_y); }
00594
00596 void xInvert() { swap(m_p1.m_x, m_p2.m_x); }
00597
00599 bool contains(const DPoint &p) const {
00600 if (DIsLess (p.m_x, m_p1.m_x) ||
00601 DIsGreater(p.m_x, m_p2.m_x) ||
00602 DIsLess (p.m_y, m_p1.m_y) ||
00603 DIsGreater(p.m_y, m_p2.m_y))
00604 return false;
00605 return true;
00606 }
00607 };
00608
00610 ostream &operator<<(ostream &os, const DRect &dr);
00611
00612
00616 class DScaler {
00617
00618 private:
00619
00620 const DRect *m_from;
00621 const DRect *m_to;
00622
00623 double m_factorX;
00624 double m_factorY;
00625 double m_offsetX;
00626 double m_offsetY;
00627
00628 public:
00630 DScaler(const DRect &from, const DRect &to) :
00631 m_from(&from),
00632 m_to(&to),
00633 m_factorX(to.width()/from.width()),
00634 m_factorY(to.height()/from.height()),
00635 m_offsetX(to.p1().m_x - from.p1().m_x * m_factorX),
00636 m_offsetY(to.p1().m_y - from.p1().m_y * m_factorY)
00637 {}
00638
00639 ~DScaler() {}
00640
00642 const DRect &from() const { return *m_from; }
00643
00645 const DRect &to() const { return *m_to; }
00646
00648 double scaleToX(double x) { return x * m_factorX + m_offsetX; }
00649
00651 double scaleToY(double y) { return y * m_factorY + m_offsetY; }
00652
00654 double scaleWidth(double width) { return width * m_to->width() /m_from->width(); }
00655
00657 double scaleHeight(double height) { return height * m_to->height()/m_from->height(); }
00658 };
00659
00661 ostream &operator<<(ostream &os, const DScaler &ds);
00662
00663
00667 class DSegment : public DLine {
00668
00669 protected:
00670
00671 public:
00672
00674 DSegment() : DLine() {}
00675
00677 DSegment(const DPoint &p1, const DPoint &p2) : DLine(p1, p2) {}
00678
00680 DSegment(const DLine &dl) : DLine(dl) {}
00681
00683 DSegment(double x1, double y1, double x2, double y2) : DLine(x1, y1, x2, y2) {}
00684
00686 DSegment(const DSegment &ds) : DLine(ds) {}
00687
00688
00695 double det(const DSegment &segment) const {
00696 return (dx() * segment.dy() - dy() * segment.dx());
00697 }
00698 };
00699
00700
00704 class DPolygon : public DPolyline {
00705
00706 protected:
00707
00708 bool m_counterclock;
00709
00710 public:
00717 DPolygon(bool cc = true) : m_counterclock(cc) { }
00718
00720 DPolygon(const DRect &rect, bool cc = true) : m_counterclock(cc) {
00721 operator=(rect);
00722 }
00723
00725 DPolygon(const DPolygon &dop) : DPolyline(dop), m_counterclock(dop.m_counterclock) { }
00726
00728 bool counterclock() { return m_counterclock; }
00729
00731 DPolygon &operator=(const DPolygon &dop) {
00732 List<DPoint>::operator =(dop);
00733 m_counterclock = dop.m_counterclock;
00734 return *this;
00735 }
00736
00738 DPolygon &operator=(const DRect &rect);
00739
00741 DSegment segment(ListConstIterator<DPoint> it) const;
00742
00743
00745 ListIterator<DPoint> insertPoint(const DPoint &p) {
00746 return insertPoint(p, begin(), begin());
00747 }
00748
00754 ListIterator<DPoint> insertPoint(const DPoint &p,
00755 ListIterator<DPoint> p1,
00756 ListIterator<DPoint> p2);
00757
00759 void insertCrossPoint(const DPoint &p);
00760
00762 int getCrossPoints(const DPolygon &p, List<DPoint> &crossPoints) const;
00763
00765 void unify();
00766
00768 void normalize();
00769
00771 void writeGML(const char* filename) const;
00772
00774 void writeGML(ostream &stream) const;
00775 };
00776
00778 ostream &operator<<(ostream &os, const DPolygon &dop);
00779
00780
00781
00782 }
00783
00784 #endif