/** @file Plane.cpp @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2003-02-06 \edited 2011-02-29 */ #include "G3D/platform.h" #include "G3D/Plane.h" #include "G3D/BinaryOutput.h" #include "G3D/BinaryInput.h" #include "G3D/stringutils.h" #include "G3D/Any.h" namespace G3D { Plane::Plane(const Any& a) { a.verifyName("Plane"); a.verifySize(2); a.verifyType(Any::ARRAY); *this = Plane(Vector3(a[0]), Point3(a[1])); } Any Plane::toAny() const { Any a(Any::ARRAY, "Plane"); a.append(normal(), normal() * _distance); return a; } Plane::Plane(class BinaryInput& b) { deserialize(b); } void Plane::serialize(class BinaryOutput& b) const { _normal.serialize(b); b.writeFloat64(_distance); } void Plane::deserialize(class BinaryInput& b) { _normal.deserialize(b); _distance = (float)b.readFloat64(); } Plane::Plane (Vector4 point0, Vector4 point1, Vector4 point2) { debugAssertM( point0.w != 0 || point1.w != 0 || point2.w != 0, "At least one point must be finite."); // Rotate the points around so that the finite points come first. while ((point0.w == 0) && ((point1.w == 0) || (point2.w != 0))) { Vector4 temp = point0; point0 = point1; point1 = point2; point2 = temp; } Vector3 dir1; Vector3 dir2; if (point1.w == 0) { // 1 finite, 2 infinite points; the plane must contain // the direction of the two direcitons dir1 = point1.xyz(); dir2 = point2.xyz(); } else if (point2.w != 0) { // 3 finite points, the plane must contain the directions // betwseen the points. dir1 = point1.xyz() - point0.xyz(); dir2 = point2.xyz() - point0.xyz(); } else { // 2 finite, 1 infinite point; the plane must contain // the direction between the first two points and the // direction of the third point. dir1 = point1.xyz() - point0.xyz(); dir2 = point2.xyz(); } _normal = dir1.cross(dir2).direction(); _distance = _normal.dot(point0.xyz()); } Plane::Plane( const Vector3& point0, const Vector3& point1, const Vector3& point2) { _normal = (point1 - point0).cross(point2 - point0).direction(); _distance = _normal.dot(point0); } Plane::Plane( const Vector3& __normal, const Vector3& point) { _normal = __normal.direction(); _distance = _normal.dot(point); } Plane Plane::fromEquation(float a, float b, float c, float d) { Vector3 n(a, b, c); float magnitude = n.magnitude(); d /= magnitude; n /= magnitude; return Plane(n, -d); } void Plane::flip() { _normal = -_normal; _distance = -_distance; } void Plane::getEquation(Vector3& n, float& d) const { double _d; getEquation(n, _d); d = (float)_d; } void Plane::getEquation(Vector3& n, double& d) const { n = _normal; d = -_distance; } void Plane::getEquation(float& a, float& b, float& c, float& d) const { double _a, _b, _c, _d; getEquation(_a, _b, _c, _d); a = (float)_a; b = (float)_b; c = (float)_c; d = (float)_d; } void Plane::getEquation(double& a, double& b, double& c, double& d) const { a = _normal.x; b = _normal.y; c = _normal.z; d = -_distance; } std::string Plane::toString() const { return format("Plane(%g, %g, %g, %g)", _normal.x, _normal.y, _normal.z, _distance); } }