#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