/* This file is part of dolt. dolt is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. dolt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dolt; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA $Id: geometry.h,v 1.7 2004/01/13 16:01:05 whuang Exp $ */ #ifndef _GEOMETRY_H #define _GEOMETRY_H #include #include // if USE_CGAL is defined, we'll use CGAL typedefs for // geometry representations #ifdef USE_CGAL #include #include #include #include #include #include #include #include #include #include namespace dolt { typedef CGAL::Cartesian RepClass; typedef CGAL::Point_2 Point; typedef CGAL::Segment_2 Segment; typedef CGAL::Vector_2 Vector; typedef CGAL::Ray_2 Ray; typedef CGAL::Direction_2 Direction; typedef CGAL::Triangle_2 Triangle; typedef CGAL::Circle_2 Circle; typedef CGAL::Bbox_2 Bbox; // update for CGAL 3.0 // // typedef CGAL::Polygon_traits_2 Polygon_traits; // typedef std::vector< Point > Polygon_Container; // typedef CGAL::Polygon_2< Polygon_traits, Polygon_Container > Polygon; // // Polygon_2 now defaults to using a vector container // typedef CGAL::Polygon_2< RepClass > Polygon; typedef CGAL::Aff_transformation_2 Transformation; } #else // USE_CGAL /* Very simple geometric representations (meant almost solely for drawing) of: bounding boxes, points, line segments, line strips, polygons, ellipses and circles; these are meant to have very similar (though limited) interfaces to their counterparts in CGAL */ namespace dolt { // simple bounding box class class Bbox { private: double ixMin, iyMin, ixMax, iyMax; public: Bbox() {} Bbox( const double &xMin, const double &yMin, const double &xMax, const double &yMax ) : ixMin(xMin), iyMin(yMin), ixMax(xMax), iyMax(yMax) {} double xmin() const { return ixMin; } double ymin() const { return iyMin; } double xmax() const { return ixMax; } double ymax() const { return iyMax; } }; // simple point class class Point { private: double ix, iy; public: Point() {} Point( const double &px, const double &py ) : ix(px), iy(py) {} bool operator==( const Point &p ) const; bool operator!=( const Point &p ) const; double x() const { return ix; } double y() const { return iy; } // The following operators are provided for convenience in the // non-CGAL version. CGAL does not support these operators because // of the disctinction between Points and Vectors. Point operator+(const Point &p) const { return Point(ix+p.ix, iy+p.iy); } Point operator-(const Point &p) const { return Point(ix-p.ix, iy-p.iy); } Point operator+=(const Point &p) { ix+=p.ix; iy+=p.iy; return *this; } Point operator-=(const Point &p) { ix-=p.ix; iy-=p.iy; return *this; } Point operator-() { return Point(-ix, -iy); } Point rotate(double th) const; Point rotate90() const { return Point(-iy,ix); } double length() const; Point normal() const { return *this/length(); } // right multiplication and division by a scalar Point operator*(double s) const { return Point(ix*s, iy*s); } Point operator/(double s) const { return Point(ix/s, iy/s); } Point operator*=(double s) { ix*=s; iy*=s; return *this; } Point operator/=(double s) { ix/=s; iy/=s; return *this; } }; //////////////// // other Point utilities // // dot product double dot(const Point &p, const Point &q); // planar cross product (returns magnitude of cross product) double cross(const Point &p, const Point &q); // create a unit normal Point unitNormal(double th); std::ostream & operator<<(std::ostream &out, const dolt::Point &p); std::istream & operator>>(std::istream &in, dolt::Point &p); // simple line segment class class Segment { protected: Point pStart, pEnd; public: Segment() {} Segment( const Point &startPoint, const Point &endPoint ) : pStart(startPoint), pEnd(endPoint) {} Point start() const { return pStart; } Point end() const { return pEnd; } }; std::ostream & operator<<(std::ostream &out, const dolt::Segment &s); std::istream & operator>>(std::istream &in, dolt::Segment &s); // simple polygon class // in order to provide an edge iterator, we have // to make this somewhat complicated; the way this // is done is largely from CGAL // (Polygon_2_edge_iterator.h) class Polygon : public std::vector { public: Polygon() {} typedef std::vector::iterator Vertex_iterator; typedef std::vector::const_iterator Vertex_const_iterator; class Polygon_segment_ptr { private: Segment seg; public: Polygon_segment_ptr( const Segment &s ) : seg(s) {} Segment * operator->() { return &seg; } }; class Edge_const_iterator { private: const std::vector *container; std::vector::const_iterator cur; public: Edge_const_iterator() : container(0) {} Edge_const_iterator( const std::vector *c, std::vector::const_iterator i ) : container(c), cur(i) {} Edge_const_iterator & operator=( const Edge_const_iterator &i ) { container = i.container; cur = i.cur; return *this; } bool operator==( const Edge_const_iterator &i ) { return cur == i.cur; } bool operator!=( const Edge_const_iterator &i ) { return cur != i.cur; } Edge_const_iterator & operator++() { cur++; return *this; } Edge_const_iterator operator++( int ); Polygon_segment_ptr operator->() { return Polygon_segment_ptr(operator*()); } Segment operator*(); }; Vertex_iterator vertices_begin() { return begin(); } Vertex_iterator vertices_end() { return end(); } Vertex_const_iterator vertices_begin() const { return begin(); } Vertex_const_iterator vertices_end() const { return end(); } Edge_const_iterator edges_begin() const; Edge_const_iterator edges_end() const; Bbox bbox() const; }; std::ostream & operator<<(std::ostream &out, const dolt::Polygon &p); std::istream& operator>> (std::istream& i, dolt::Polygon& p); // simple circle class class Circle { private: Point pos; double sqRadius; public: Circle() {} Circle( const Point ¢er, const double &squaredRad ) : pos(center), sqRadius(squaredRad) {} inline Point center() const { return pos; } inline double squared_radius() const { return sqRadius; } inline void setCenter( const Point &c ) { pos = c; } inline void setRadiusSquared( const double &r2 ) { sqRadius = r2; } }; } // end namespace dolt #endif // USE_CGAL namespace dolt { /* utility method; cannot be a member of Bbox without breaking CGAL compatibility. expand box by given scaling factors; > 1.0 expands, 0 to 1.0 contracts, negative inverts. the center of the Bbox remains the same. returns the modified Bbox (doesn't modify the original). */ Bbox stretchBbox( const Bbox &box, float scaleX, float scaleY ); /* lineStrip, Ellipse, Square, Rectangle: none of these is provided by CGAL, so we have our own implementations */ // all a lineStrip is is a series of points typedef std::vector lineStrip; // simple ellipse class class Ellipse { private: Point pos; double orientation, majRadius, minRadius; public: Ellipse() {} Ellipse( const Point &p, const double &orient, const double &majorRadius, const double &minorRadius ) : pos(p), orientation(orient), majRadius(majorRadius), minRadius(minorRadius) {} inline void setPos( const Point &p ) { pos = p; } inline void setOrientation( const double &o ) { orientation = o; } inline void setMajorRadius( const double &r ) { majRadius = r; } inline void setMinorRadius( const double &r ) { minRadius = r; } inline Point getPos() const { return pos; } inline double getOrientation() const { return orientation; } inline double getMajorRadius() const { return majRadius; } inline double getMinorRadius() const { return minRadius; } }; // both Rectangle and Square are axis-aligned (no // orientation) class Rectangle : public Bbox { public: Rectangle() : Bbox() {} Rectangle( const Point ¢er, const double &width, const double &height ) { double halfw = width / 2.0; double halfh = height / 2.0; Bbox(center.x() - halfw, center.y() - halfh, center.x() + halfw, center.y() + halfh); } Rectangle( const Point &lowerLeft, const Point &upperRight ) : Bbox(lowerLeft.x(), lowerLeft.y(), upperRight.x(), upperRight.y()) {} Rectangle( const Bbox &b ) : Bbox(b) {} inline Point getMinPoint() const { return Point(xmin(),ymin()); } inline Point getMaxPoint() const { return Point(xmax(),ymax()); } }; class Square : public Rectangle { public: Square() {} Square( const Point &lowerLeft, const double &sideLen ) : Rectangle(lowerLeft, Point(lowerLeft.x() + sideLen,lowerLeft.y() + sideLen)) {} Square( const Bbox &b ) : Rectangle(b) {} }; class Arc : public Circle { protected: double min, max; public: Arc() {} Arc( const Point ¢er, const double &squaredRad, const double &minAngle, const double &maxAngle ) : Circle(center,squaredRad), min(minAngle), max(maxAngle) {} inline double getMinAngle() const { return min; } inline double getMaxAngle() const { return max; } inline void setMinAngle( const double &m ) { min = m; } inline void setMaxAngle( const double &m ) { max = m; } }; } // end namespace dolt #endif // _GEOMETRY_H