etk/etk/math/Plane.hpp

180 lines
4.9 KiB
C++

/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#pragma once
#include <etk/debug.hpp>
#include <vector>
namespace etk {
/**
* @brief Plane equation template: define a plane equation
* @todo Validate it, this is a !!! PROTOTYPE !!!
*/
template <typename T> class Plane {
private:
etk::Vector3D<T> m_normal; //!< X.N+intercept=0
T m_intercept; //!< interception value
public:
/**
* @brief Constructor of a Plane
*/
Plane() :
m_normal(0, 0, 0),
m_intercept(0) {
}
/**
* @brief Constructor of a Plane
* @param[in] _normal Normal of the plane
* @param[in] _intercept Interception value of the plane
*/
Plane(etk::Vector3D<T> _normal, T _intercept=0) :
m_normal(_normal),
m_intercept(_intercept) {
}
/**
* @brief Copy constructor of a Plane
* @param[in] _obj Plane object to copy
*/
Plane(const Plane& _obj) :
m_normal(_obj.m_normal),
m_intercept(_obj.m_intercept) {
}
/**
* @brief Set the normal of the plane
* @param[in] _obj Vector of the normal
*/
void setNormal(const etk::Vector3D<T>& _obj) {
m_normal = _obj;
}
/**
* @brief Set interception value of the plane
* @param[in] _intercept Value of the intercept
*/
void setIntercept(float _intercept) {
m_intercept=_intercept;
}
/**
* @brief Set the plane with 3 points in the space
* @param[in] _p0 First point
* @param[in] _p1 Second point
* @param[in] _p2 Thrid point
*/
void setFromPoints(const etk::Vector3D<T>& _p0,
const etk::Vector3D<T>& _p1,
const etk::Vector3D<T>& _p2) {
m_normal = (_p1 - _p0).cross(_p2 - _p0);
m_normal.normalize();
calculateIntercept(_p0);
}
/**
* @brief Calculate interception value with a point in the plane
* @param[in] _pointOnPlane Point in the plane
*/
void calculateIntercept(const etk::Vector3D<T>& _pointOnPlane) {
m_intercept=-m_normal.dot(_pointOnPlane);
}
/**
* @brief Normalize tha plane properties
*/
void normalize() {
float normalLength = m_normal.getLength();
if (normalLength == 0) {
return;
}
m_normal /= normalLength;
m_intercept /= normalLength;
}
/**
* @brief Get the normal of the plane
* @return Vector of the normal
*/
const etk::Vector3D<T>& getNormal() const {
return m_normal;
}
/**
* @brief Get intercept Value of the plane
* @return The Intercept value
*/
T getIntercept() const {
return m_intercept;
}
/**
* @brief Get the intersection between 3 planes
* @param[in] _p2 Second plane
* @param[in] _p3 Third plane
* @return vec3(0,0,0) No Intersection find, else when find
*/
etk::Vector3D<T> intersect3(const Plane<T>& _p2,
const Plane<T>& _p3) {
float denominator = m_normal.dot((_p2.m_normal).cross(_p3.m_normal));
//scalar triple product of normals
if(denominator==0.0f) {
//no intersection
return etk::Vector3D<T>(0,0,0);
}
etk::Vector3D<T> temp1, temp2, temp3;
temp1 = (_p2.m_normal.cross(_p3.m_normal))*m_intercept;
temp2 = (_p3.m_normal.cross(m_normal)) * _p2.m_intercept;
temp3 = (m_normal.cross(_p2.m_normal)) * _p3.m_intercept;
return (temp1+temp2+temp3) / (-denominator);
}
/**
* @brief Get distance from a point to the plane
* @param[in] _point Point to calculate the distance
* @return distance of the Point
*/
float getDistance(const etk::Vector3D<T>& _point) const {
return _point.x() * m_normal.x()
+ _point.y() * m_normal.y()
+ _point.z() * m_normal.z()
+ m_intercept;
}
/**
* @brief Create a linear interpolation of the plane with an other
* @param[in] _p2 Second plane
* @param[in] _factor Factor to scale
* @return New plane equation
*/
Plane<T> linearInterpolate(const Plane<T>& _p2, float _factor) {
Plane<T> result;
result.m_normal=m_normal*(1.0f-_factor) + _p2.m_normal*_factor;
result.m_normal.normalize();
result.m_intercept=m_intercept*(1.0f-_factor) + _p2.m_intercept*_factor;
return result;
}
/**
* @brief Equality compare operator with an other object.
* @param[in] _obj Reference on the comparing object
* @return true The Objects are identical
* @return false The Objects are NOT identical
*/
bool operator==(const Plane<T>& _obj) const {
if( m_normal == _obj.m_normal
&& m_intercept == _obj.m_intercept) {
return true;
}
return false;
}
/**
* @brief In-Equality compare operator with an other object.
* @param[in] _obj Reference on the comparing object
* @return true The Objects are NOT identical
* @return false The Objects are identical
*/
bool operator!=(const Plane<T>& _obj) const {
return!((*this) == _obj);
}
};
}