mirror of
https://github.com/worldforge/worldforge
synced 2026-08-17 16:26:05 -04:00
190 lines
7 KiB
C++
190 lines
7 KiB
C++
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <wfmath/vector.h>
|
|
#include <wfmath/point.h>
|
|
#include <wfmath/const.h>
|
|
#include <wfmath/rotmatrix.h>
|
|
#include <wfmath/axisbox.h>
|
|
#include <wfmath/ball.h>
|
|
#include <wfmath/intersect_decls.h>
|
|
|
|
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<const int dim>
|
|
class Shape
|
|
{
|
|
public:
|
|
// The first things in the Shape class are the functions required
|
|
// by CLASS_LAYOUT for all classes
|
|
|
|
///
|
|
Shape() {}
|
|
///
|
|
Shape(const Shape<dim>& s) {}
|
|
///
|
|
~Shape() {}
|
|
|
|
/// generic: Print an instance to a stream
|
|
friend std::ostream& operator<< <dim>(std::ostream& os, const Shape& s);
|
|
/// generic: Parse an instance from a stream
|
|
friend std::istream& operator>> <dim>(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, CoordType tolerance = numeric_constants<CoordType>::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
|
|
**/
|
|
size_t numCorners() const; // The number of corners, returns zero for Ball<>
|
|
/// shape: return the position of the i'th corner, where 0 <= i < numCorners()
|
|
Point<dim> getCorner(size_t i) const; // Must have i >= 0 && i < numCorners()
|
|
/// shape: return the position of the center of the shape
|
|
Point<dim> 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<dim>& 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<dim>& p, size_t 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<dim>& 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<dim>& m, size_t 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<dim>& 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<dim>& m, const Point<dim>& p);
|
|
|
|
// Intersection functions
|
|
|
|
/// shape: return the minimal axis-aligned bounding box
|
|
AxisBox<dim> boundingBox() const;
|
|
/// shape: return the minimal bounding sphere
|
|
Ball<dim> 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<dim> 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<dim>(Shape<dim>& s1, Shape<dim>& 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<dim>(Shape<dim>& s1, Shape<dim>& s2, bool proper);
|
|
|
|
private:
|
|
bool m_valid;
|
|
};
|
|
|
|
//#include<wfmath/shape_funcs.h>
|
|
|
|
} // namespace WFMath
|
|
|
|
#endif // WFMATH_SHAPE_H
|