#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2015 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library 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 IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_GEOMETRY_AREAS_TRIANGLE3_H #define NUCLEX_GEOMETRY_AREAS_TRIANGLE3_H #include "Nuclex/Geometry/Config.h" #include "Nuclex/Geometry/Point3.h" #include "Nuclex/Geometry/Vector3.h" namespace Nuclex { namespace Geometry { namespace Areas { // ------------------------------------------------------------------------------------------- // /// Triangle in 3D space constructed from its 3 corner vertices template struct Triangle3 { /// Initializes a triangle using the specified corner points /// First corner of the triangle /// Second corner of the triangle /// Third corner of the triangle public: Triangle3( const Point3 &a, const Point3 &b, const Point3 &c ) : A(a), B(b), C(c) {} /// Returns the center point of the triangle /// The center of the triangle public: Point3 GetCenter() const { return Point3( (this->A.X + this->B.X + this->C.X) / 3, (this->A.Y + this->B.Y + this->C.Y) / 3, (this->A.Z + this->B.Z + this->C.Z) / 3 ); } /// Calculates the area of the triangle /// The area of the triangle /// /// Heron's triangle area formular states that, given s = (a + b + c) / 2 /// (semiperimeter), the area of a triangle can be calculated as /// /// /// _________________________________ /// area = \/ s * (s - a) * (s - b) * (s - c) /// /// /// /// In a paper by W. Kahan this method is proven to be numerically unstable /// for floating point numbers. He recommends to use the following formula /// instead, where the lengths a, b and c have to be sorted in ascending order. /// /// /// ______________________________________________________________ /// area = 0.25 * \/ (a + (b + c)) * (c - (a - b)) * (c + (a - b)) * (a + b - c)) /// /// /// public: TScalar GetArea() const { TScalar a = Point3::DistanceBetween(A, B); TScalar b = Point3::DistanceBetween(B, C); TScalar c = Point3::DistanceBetween(C, A); TScalar s = (a + b + c) / 2; return Math::SquareRoot(s * (s - a) * (s - b) * (s - c)); } /// Calculates the perimeter of the triangle /// The triangle's perimeter public: TScalar GetPerimeter() const { return ( Point3::DistanceBetween(A, B) + Point3::DistanceBetween(B, C) + Point3::DistanceBetween(C, A) ); } /// Offsets the entire triangle by the specified amount /// Amount the triangle will be offset on the X axis /// Amount the triangle will be offset on the Y axis /// Amount the triangle will be offset on the Z axis public: void ShiftBy(TScalar amountX, TScalar amountY, TScalar amountZ) { this->A.X += amountX; this->B.X += amountX; this->C.X += amountX; this->A.Y += amountY; this->B.Y += amountY; this->C.Y += amountY; this->A.Z += amountZ; this->B.Z += amountZ; this->C.Z += amountZ; } /// Offsets the entire triangle by the specified amount /// Amount the triangle will be offset public: void ShiftBy(const Vector3 &amount) { this->A += amount; this->B += amount; this->C += amount; } /// Coordinates of the triangle's first corner public: Point3 A; /// Coordinates of the triangle's second corner public: Point3 B; /// Coordinates of the triangle's third corner public: Point3 C; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Geometry::Areas #endif // NUCLEX_GEOMETRY_AREAS_TRIANGLE3_H