// shape.h (A general base class for shapes) // // The WorldForge Project // Copyright (C) 2001 The WorldForge Project // // This program 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. // // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // For information about WorldForge and its authors, please contact // the Worldforge Web Site at http://www.worldforge.org. // // Author: Ron Steinke // This class borrows heavily from the base shape class in libCoal, // plus certain intersection ideas from stage/shepherd/sylvanus #ifndef WFMATH_SHAPE_H #define WFMATH_SHAPE_H #include #include #include #include #include #include #include namespace WFMath { /// A fake class which documents the generic parts of the WFMath interface /** * This fake class documents two parts of the WFMath generic * class interface. With a few exceptions (e.g. classes derived * from std::exception), every class in WFMath implements * the part of the interface labeled as 'generic'. The 'shape' * interface is implemented by several classes, which identify * themselves in their own documentation. Every class which * implements the 'shape' interface also implements the 'generic' * interface. Classes will not generally document their * generic and shape interface functions. **/ template class Shape { public: // The first things in the Shape class are the functions required // by CLASS_LAYOUT for all classes /// Shape() {} /// Shape(const Shape& s) {} /// ~Shape() {} /// generic: Print an instance to a stream friend std::ostream& operator<< (std::ostream& os, const Shape& s); /// generic: Parse an instance from a stream friend std::istream& operator>> (std::istream& is, Shape& s); /// Shape& operator=(const Shape& a); /// generic: check if two classes are equal, up to a given tolerance bool isEqualTo(const Shape& s, double tolerance = WFMATH_EPSILON) const; /// generic: check if two classes are equal, up to tolerance WFMATH_EPSILON bool operator==(const Shape& s) const {return isEqualTo(s);} /// generic: check if two classes are not equal, up to tolerance WFMATH_EPSILON bool operator!=(const Shape& s) const {return !isEqualTo(s);} /// generic: returns true if the class instance has been initialized bool isValid() const {return m_valid;} // Now we begin with the functions in the shape interface // Descriptive characteristics /// shape: return the number of corners in the shape. /** * For many shape classes, this is a fixed constant **/ int numCorners() const; // The number of corners, returns zero for Ball<> /// shape: return the position of the i'th corner, where 0 <= i < numCorners() Point getCorner(int i) const; // Must have i >= 0 && i < numCorners() /// shape: return the position of the center of the shape Point getCenter() const; // Returns the barycenter of the object // Movement functions /// shape: move the shape by an amount given by the Vector v Shape& shift(const Vector& v); // Move the shape a certain distance /// shape: move the shape, moving the given corner to the Point p /** * The corner in question is getCorner(corner). **/ Shape& moveCornerTo(const Point& p, int corner) {return shift(p - getCorner(corner));} /// shape: move the shape, moving the center to the Point p /** * The center is defined by getCenter() **/ Shape& moveCenterTo(const Point& p) {return shift(p - getCenter());} /// shape: rotate the shape while holding the given corner fixed /** * The corner in question is getCorner(corner). **/ Shape& rotateCorner(const RotMatrix& m, int corner) {return rotatePoint(m, getCorner(corner));} /// shape: rotate the shape while holding the center fixed /** * The center is defined by getCenter() **/ Shape& rotateCenter(const RotMatrix& m) {return rotatePoint(m, getCenter());} /// shape: rotate the shape while holding the Point p fixed. /** * Note that p can be any Point, it does not have to lie within * the shape. **/ Shape& rotatePoint(const RotMatrix& m, const Point& p); // Intersection functions /// shape: return the minimal axis-aligned bounding box AxisBox boundingBox() const; /// shape: return the minimal bounding sphere Ball boundingSphere() const; /// shape: return an approximate bounding sphere, guaranteed /// to contain the minimal bounding sphere /** * boundingSphereSloppy() uses * SloppyDistance() instead of Distance() to calculate it's * radius, except in cases like Point<> and Ball<> where it * would be silly. Thus, the result of boundingSphereSloppy() * is guaranteed to contain the result of boundingSphere(). **/ Ball boundingSphereSloppy() const; /// shape: Returns true if the two shapes intersect. /** * If the 'proper' argument is true, shapes which only touch on their * boundary do not count as intersecting. If it is false, they do. * This function is symmetric in its first two arguments * (Intersect(a, b, proper) == Intersect(b, a, proper)). * The two shapes do * not have to be the same class, but must have the same dimension. **/ friend bool Intersect(Shape& s1, Shape& s2, bool proper); /// shape: Returns true if the first shape contains the second. /** * If the 'proper' argument is true, the inner shape is not contained * if it touches the boundary of the outer shape. Otherwise, it * does. Therefore, any shape contains itself * (Contains(foo, foo, false) == true), but no shape contains itself * properly (Contains(foo, foo, true) == false). Because of this, * an empty shape (e.g. a Polygon with zero corners) * is properly contained by any other shape. A Point, or any single * point shape (e.g. a Segment where the endpoints are equal) * properly contains an empty shape, and contains (but not properly) * any other single point shape which occupies the same point. * The two shapes do * not have to be the same class, but must have the same dimension. **/ friend bool Contains(Shape& s1, Shape& s2, bool proper); private: bool m_valid; }; //#include } // namespace WFMath #endif // WFMATH_SHAPE_H