Open
Graph Drawing
Framework

 v.2010.10
 

geometry.h

Go to the documentation of this file.
00001 /*
00002  * $Revision: 2027 $
00003  *
00004  * last checkin:
00005  *   $Author: gutwenger $
00006  *   $Date: 2010-09-01 11:55:17 +0200 (Wed, 01 Sep 2010) $
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> // for DBL_MAX
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 // Important: be careful, if compared values are (+/-)DBL_MAX !!!
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 };//class GenericPoint
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 };//class IPoint
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, //start point of the edge
00376                     DPoint tgt); //end point of the edge
00377 
00379     void convertToInt();
00380 
00381     //void reConvertToDouble();
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) { // don't assign myself
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 // gives the intersection with the vertical axis 'verAxis', returns the number of intersections
00482 // 0 = no, 1 = one, 2 = infinity or both end-points, e.g. parallel on this axis
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) { // don't assign myself
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 } // end namespace ogdf
00795 
00796 #endif