00001
00002
00003
00004
00005
00006
00007
00008
00052 #ifdef _MSC_VER
00053 #pragma once
00054 #endif
00055
00056 #ifndef OGDF_GEOMETRIC_H
00057 #define OGDF_GEOMETRIC_H
00058
00059 #include <float.h>
00060 #include <math.h>
00061
00062 #include <ogdf/basic/List.h>
00063 #include <ogdf/basic/Hashing.h>
00064
00065 #define GEOMETRIC_CMP_EPS 1e-06
00066
00067 namespace ogdf {
00068
00070 enum Orientation {
00071 topToBottom,
00072 bottomToTop,
00073 leftToRight,
00074 rightToLeft
00075 };
00076
00077
00078
00079
00080 inline
00081 bool DIsEqual(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00082 {
00083 return (a < (b + eps) && a > (b - eps));
00084 }
00085
00086 inline
00087 bool DIsGreaterEqual(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00088 {
00089 return (a > (b - eps));
00090 }
00091
00092 inline
00093 bool DIsGreater(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00094 {
00095 return (a > (b + eps));
00096 }
00097
00098 inline
00099 bool DIsLessEqual(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00100 {
00101 return (a < (b + eps));
00102 }
00103
00104 inline
00105 bool DIsLess(const double &a, const double &b, const double eps = GEOMETRIC_CMP_EPS)
00106 {
00107 return (a < (b - eps));
00108 }
00109
00110 inline
00111 double DRound(const double &d, int prec = 0)
00112 {
00113 if (prec == 0)
00114 return floor(d + 0.5);
00115 double factor = pow(10.0, ((double) prec));
00116 return DRound(d * factor, 0) / factor;
00117 }
00118
00127 template <class NUMBER>
00128 class GenericPoint
00129 {
00130 public:
00132 typedef NUMBER numberType;
00133
00134 NUMBER m_x;
00135 NUMBER m_y;
00136
00138
00142 GenericPoint() { }
00143
00145 GenericPoint(NUMBER x, NUMBER y) : m_x(x), m_y(y) { }
00146
00148 GenericPoint(const GenericPoint &ip) : m_x(ip.m_x), m_y(ip.m_y) { }
00149
00151 GenericPoint operator=(const GenericPoint &ip) {
00152 m_x = ip.m_x;
00153 m_y = ip.m_y;
00154 return *this;
00155 }
00156
00158 bool operator==(const GenericPoint &ip) const {
00159 return m_x == ip.m_x && m_y == ip.m_y;
00160 }
00161
00163 bool operator!=(const GenericPoint &ip) const {
00164 return m_x != ip.m_x || m_y != ip.m_y;
00165 }
00166
00167 };
00168
00169
00175 class OGDF_EXPORT IPoint : public GenericPoint<int>
00176 {
00177 public:
00179 IPoint() : GenericPoint<int>(0,0) { }
00180
00182 IPoint(int x, int y) : GenericPoint<int>(x,y) { }
00183
00185 IPoint(const IPoint &ip) : GenericPoint<int>(ip) { }
00186
00188 double distance(const IPoint &p) const;
00189 };
00190
00191
00193 OGDF_EXPORT ostream &operator<<(ostream &os, const IPoint &ip);
00194
00195
00196 template<> class DefHashFunc<IPoint>
00197 {
00198 public:
00199 int hash(const IPoint &ip) const {
00200 return 7*ip.m_x + 23*ip.m_y;
00201 }
00202 };
00203
00204
00213 class OGDF_EXPORT IPolyline : public List<IPoint> {
00214 public:
00216 IPolyline() { }
00217
00219 IPolyline(const IPolyline &ipl) : List<IPoint>(ipl) { }
00220
00222 IPolyline &operator=(const IPolyline &ipl) {
00223 List<IPoint>::operator =(ipl);
00224 return *this;
00225 }
00226
00228 double length() const;
00229 };
00230
00231
00232
00238 class OGDF_EXPORT DPoint : public GenericPoint<double>
00239 {
00240 public:
00242 DPoint() : GenericPoint<double>(0,0) { }
00243
00245 DPoint(double x, double y) : GenericPoint<double>(x,y) { }
00246
00248 DPoint(const DPoint &dp) : GenericPoint<double>(dp) { }
00249
00251 bool operator==(const DPoint &dp) const {
00252 return DIsEqual(m_x, dp.m_x) && DIsEqual(m_y,dp.m_y);
00253 }
00254
00256 DPoint operator+(const DPoint &p) const;
00257
00259 DPoint operator-(const DPoint &p) const;
00260
00262 double distance(const DPoint &p) const;
00263 };
00264
00266 OGDF_EXPORT ostream &operator<<(ostream &os, const DPoint &dp);
00267
00268
00272 class OGDF_EXPORT DVector : public DPoint {
00273 public:
00274
00276 DVector() : DPoint() { }
00277
00279 DVector(double x, double y) : DPoint(x, y) { }
00280
00282 DVector(const DVector &dv) : DPoint(dv) { }
00283
00285 DVector operator=(const DPoint &ip) {
00286 if (this != &ip)
00287 {
00288 m_x = ip.m_x;
00289 m_y = ip.m_y;
00290 }
00291 return *this;
00292 }
00293
00295 DVector operator*(const double val) const;
00296
00298 DVector operator/(const double val) const;
00299
00301 double length() const;
00302
00304 double operator^(const DVector &dv) const;
00305
00307 double operator*(const DVector &dv) const;
00308
00315 DVector operator++() const;
00316
00323 DVector operator--() const;
00324 };
00325
00326
00327
00335 class OGDF_EXPORT 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 normalize(DPoint src,
00376 DPoint tgt);
00377
00379 void convertToInt();
00380
00381
00382 };
00383
00384
00388 class OGDF_EXPORT DLine {
00389
00390 protected:
00391 DPoint m_start;
00392 DPoint m_end;
00393
00394 public:
00395
00397 DLine() : m_start(), m_end() {}
00398
00400 DLine(const DPoint &p1, const DPoint &p2) : m_start(p1), m_end(p2) {}
00401
00403 DLine(const DLine &dl) : m_start(dl.m_start), m_end(dl.m_end) {}
00404
00406 DLine(double x1, double y1, double x2, double y2) {
00407 m_start.m_x = x1; m_start.m_y = y1; m_end.m_x = x2; m_end.m_y = y2;
00408 }
00409
00411 bool operator==(const DLine &dl) const {
00412 return m_start == dl.m_start && m_end == dl.m_end;
00413 }
00414
00416 bool operator!=(const DLine &dl) const {
00417 return !(*this == dl);
00418 }
00419
00421 DLine &operator= (const DLine &dl) {
00422 if (this != &dl) {
00423 m_start = dl.m_start;
00424 m_end = dl.m_end;
00425 }
00426 return *this;
00427 }
00428
00430 const DPoint &start() const { return m_start; }
00431
00433 const DPoint &end() const { return m_end; }
00434
00436 double dx() const { return m_end.m_x - m_start.m_x; }
00437
00439 double dy() const { return m_end.m_y - m_start.m_y; }
00440
00442 double slope() const { return (dx() == 0) ? DBL_MAX : dy()/dx(); }
00443
00445 double yAbs() const { return (dx() == 0) ? DBL_MAX : m_start.m_y - (slope() * m_start.m_x); }
00446
00448 bool isVertical() const { return (DIsEqual(dx(), 0.0)); }
00449
00451 bool isHorizontal() const { return (DIsEqual(dy(), 0.0)); }
00452
00460 bool intersection(const DLine &line, DPoint &inter, bool endpoints = true) const;
00461
00463 bool contains(const DPoint &p) const;
00464
00466 double length() const {
00467 return m_start.distance(m_end);
00468 }
00469
00479 int horIntersection(const double horAxis, double &crossing) const;
00480
00481
00482
00492 int verIntersection(const double verAxis, double &crossing) const;
00493 };
00494
00496 ostream &operator<<(ostream &os, const DLine &dl);
00497
00498
00502 class OGDF_EXPORT DRect {
00503
00504 private:
00505 DPoint m_p1;
00506 DPoint m_p2;
00507
00508 public:
00510 DRect() : m_p1(), m_p2() {}
00511
00513 DRect(const DPoint &p1, const DPoint &p2) : m_p1(p1), m_p2(p2)
00514 { normalize(); }
00515
00517 DRect(double x1, double y1, double x2, double y2) {
00518 m_p1.m_x = x1; m_p1.m_y = y1; m_p2.m_x = x2; m_p2.m_y = y2;
00519 normalize();
00520 }
00521
00523 DRect(const DLine &dl) : m_p1(dl.start()), m_p2(dl.end())
00524 { normalize(); }
00525
00527 DRect(const DRect &dr) : m_p1(dr.m_p1), m_p2(dr.m_p2)
00528 { normalize(); }
00529
00531 bool operator==(const DRect &dr) const {
00532 return m_p1 == dr.m_p1 && m_p2 == dr.m_p2;
00533 }
00534
00536 bool operator!=(const DRect &dr) const {
00537 return !(*this == dr);
00538 }
00539
00541 DRect &operator= (const DRect &dr) {
00542 if (this != &dr) {
00543 m_p1 = dr.m_p1;
00544 m_p2 = dr.m_p2;
00545 }
00546 return *this;
00547 }
00548
00550 double width() const {
00551 return m_p2.m_x - m_p1.m_x;
00552 }
00553
00555 double height() const {
00556 return m_p2.m_y - m_p1.m_y;
00557 }
00558
00565 void normalize() {
00566 if (width() < 0) swap(m_p2.m_x, m_p1.m_x);
00567 if (height() < 0) swap(m_p2.m_y, m_p1.m_y);
00568 }
00569
00571 const DPoint &p1() const { return m_p1; }
00572
00574 const DPoint &p2() const { return m_p2; }
00575
00577 const DLine topLine() const {
00578 return DLine( DPoint(m_p1.m_x, m_p2.m_y), DPoint(m_p2.m_x, m_p2.m_y));
00579 }
00580
00582 const DLine rightLine() const {
00583 return DLine( DPoint(m_p2.m_x, m_p2.m_y), DPoint(m_p2.m_x, m_p1.m_y));
00584 }
00585
00587 const DLine leftLine() const {
00588 return DLine( DPoint(m_p1.m_x, m_p1.m_y), DPoint(m_p1.m_x, m_p2.m_y));
00589 }
00590
00592 const DLine bottomLine() const {
00593 return DLine( DPoint(m_p2.m_x, m_p1.m_y), DPoint(m_p1.m_x, m_p1.m_y));
00594 }
00595
00597 void yInvert() { swap(m_p1.m_y, m_p2.m_y); }
00598
00600 void xInvert() { swap(m_p1.m_x, m_p2.m_x); }
00601
00603 bool contains(const DPoint &p) const {
00604 if (DIsLess (p.m_x, m_p1.m_x) ||
00605 DIsGreater(p.m_x, m_p2.m_x) ||
00606 DIsLess (p.m_y, m_p1.m_y) ||
00607 DIsGreater(p.m_y, m_p2.m_y))
00608 return false;
00609 return true;
00610 }
00611 };
00612
00614 OGDF_EXPORT ostream &operator<<(ostream &os, const DRect &dr);
00615
00616
00620 class OGDF_EXPORT DScaler {
00621
00622 private:
00623
00624 const DRect *m_from;
00625 const DRect *m_to;
00626
00627 double m_factorX;
00628 double m_factorY;
00629 double m_offsetX;
00630 double m_offsetY;
00631
00632 public:
00634 DScaler(const DRect &from, const DRect &to) :
00635 m_from(&from),
00636 m_to(&to),
00637 m_factorX(to.width()/from.width()),
00638 m_factorY(to.height()/from.height()),
00639 m_offsetX(to.p1().m_x - from.p1().m_x * m_factorX),
00640 m_offsetY(to.p1().m_y - from.p1().m_y * m_factorY)
00641 {}
00642
00643 ~DScaler() {}
00644
00646 const DRect &from() const { return *m_from; }
00647
00649 const DRect &to() const { return *m_to; }
00650
00652 double scaleToX(double x) { return x * m_factorX + m_offsetX; }
00653
00655 double scaleToY(double y) { return y * m_factorY + m_offsetY; }
00656
00658 double scaleWidth(double width) { return width * m_to->width() /m_from->width(); }
00659
00661 double scaleHeight(double height) { return height * m_to->height()/m_from->height(); }
00662 };
00663
00665 OGDF_EXPORT ostream &operator<<(ostream &os, const DScaler &ds);
00666
00667
00671 class OGDF_EXPORT DSegment : public DLine {
00672
00673 protected:
00674
00675 public:
00676
00678 DSegment() : DLine() {}
00679
00681 DSegment(const DPoint &p1, const DPoint &p2) : DLine(p1, p2) {}
00682
00684 DSegment(const DLine &dl) : DLine(dl) {}
00685
00687 DSegment(double x1, double y1, double x2, double y2) : DLine(x1, y1, x2, y2) {}
00688
00690 DSegment(const DSegment &ds) : DLine(ds) {}
00691
00692
00699 double det(const DSegment &segment) const {
00700 return (dx() * segment.dy() - dy() * segment.dx());
00701 }
00702 };
00703
00704
00708 class OGDF_EXPORT DPolygon : public DPolyline {
00709
00710 protected:
00711
00712 bool m_counterclock;
00713
00714 public:
00721 DPolygon(bool cc = true) : m_counterclock(cc) { }
00722
00724 DPolygon(const DRect &rect, bool cc = true) : m_counterclock(cc) {
00725 operator=(rect);
00726 }
00727
00729 DPolygon(const DPolygon &dop) : DPolyline(dop), m_counterclock(dop.m_counterclock) { }
00730
00732 bool counterclock() { return m_counterclock; }
00733
00735 DPolygon &operator=(const DPolygon &dop) {
00736 List<DPoint>::operator =(dop);
00737 m_counterclock = dop.m_counterclock;
00738 return *this;
00739 }
00740
00742 DPolygon &operator=(const DRect &rect);
00743
00745 DSegment segment(ListConstIterator<DPoint> it) const;
00746
00747
00749 ListIterator<DPoint> insertPoint(const DPoint &p) {
00750 return insertPoint(p, begin(), begin());
00751 }
00752
00758 ListIterator<DPoint> insertPoint(const DPoint &p,
00759 ListIterator<DPoint> p1,
00760 ListIterator<DPoint> p2);
00761
00763 void insertCrossPoint(const DPoint &p);
00764
00766 int getCrossPoints(const DPolygon &p, List<DPoint> &crossPoints) const;
00767
00769 void unify();
00770
00772 void normalize();
00773
00775 void writeGML(const char* filename) const;
00776
00778 void writeGML(ostream &stream) const;
00779
00786 bool containsPoint(DPoint &p) const;
00787 };
00788
00790 OGDF_EXPORT ostream &operator<<(ostream &os, const DPolygon &dop);
00791
00792
00793
00794 }
00795
00796 #endif