Merge branch 'jtg/area' of https://github.com/JesseTG/glm into gtx_area

This commit is contained in:
Christophe Riccio 2015-10-07 22:47:51 +02:00
commit 40e061396f
10 changed files with 446 additions and 5 deletions

68
glm/gtx/area.hpp Normal file
View File

@ -0,0 +1,68 @@
///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2015 G-Truc Creation (www.g-truc.net)
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// Restrictions:
/// By making use of the Software for military purposes, you choose to make
/// a Bunny unhappy.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///
/// @ref gtx_area
/// @file glm/gtx/area.hpp
/// @date 2015-09-27
/// @author Jesse Talavera-Greenberg
///
/// @see core (dependence)
///
/// @defgroup gtx_area GLM_GTX_area
/// @ingroup gtx
///
/// @brief Functions to compute the area of polygons and other common structures.
/// <glm/gtx/area.hpp> need to be included to use these functionalities.
///////////////////////////////////////////////////////////////////////////////////
#pragma once
// Dependency:
#include <cmath>
#include "../glm.hpp"
#include "../vec2.hpp"
#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED))
# pragma message("GLM: GLM_GTX_area extension included")
#endif
namespace glm
{
/// @addtogroup gtx_area
/// @{
//! Returns the area of the triangle made by the three given vertices.
/// If the triangles are given in counter-clockwise order, the area will be
/// positive. If they're given in clockwise order, the area will be negative.
/// If they're collinear, the area will be zero.
template<typename T, precision P = defaultp, typename areaType = float>
GLM_FUNC_DECL areaType area(const tvec2<T, P>& a, const tvec2<T, P>& b, const tvec2<T, P>& c);
/// @}
} //namespace glm
#include "area.inl"

45
glm/gtx/area.inl Normal file
View File

@ -0,0 +1,45 @@
///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2015 G-Truc Creation (www.g-truc.net)
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// Restrictions:
/// By making use of the Software for military purposes, you choose to make
/// a Bunny unhappy.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///
/// @ref gtx_area
/// @file glm/gtx/area.inl
/// @date 2015-09-27
/// @author Jesse Talavera-Greenberg
///////////////////////////////////////////////////////////////////////////////////
namespace glm {
namespace detail {
template<typename T, precision P, typename areaType = float>
GLM_FUNC_QUALIFIER areaType area2(const tvec2<T, P>& a, const tvec2<T, P>& b, const tvec2<T, P>& c) {
return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
}
template<typename T, precision P, typename areaType>
GLM_FUNC_QUALIFIER areaType area(const tvec2<T, P>& a, const tvec2<T, P>& b, const tvec2<T, P>& c) {
return detail::area2<T, P, areaType>(a, b, c) / static_cast<areaType>(2.0);
}
}//namespace glm

View File

@ -43,8 +43,13 @@
#pragma once #pragma once
// Dependency: // Dependency:
#include <cfloat>
#include <limits>
#include "../glm.hpp" #include "../glm.hpp"
#include "../geometric.hpp"
#include "../gtc/epsilon.hpp"
#include "../gtx/closest_point.hpp" #include "../gtx/closest_point.hpp"
#include "../gtx/vector_query.hpp"
#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) #if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED))
# pragma message("GLM: GLM_GTX_closest_point extension included") # pragma message("GLM: GLM_GTX_closest_point extension included")
@ -106,6 +111,42 @@ namespace glm
genType & intersectionPosition1, genType & intersectionNormal1, genType & intersectionPosition1, genType & intersectionNormal1,
genType & intersectionPosition2 = genType(), genType & intersectionNormal2 = genType()); genType & intersectionPosition2 = genType(), genType & intersectionNormal2 = genType());
//! Returns true if the two given line segments intersect.
//! From GLM_GTX_intersect extension
/// @param a, b The two endpoints of the first line segment (ab)
/// @param c, d The two endpoints of the second line segment (cd)
template <typename T, precision P = defaultp>
GLM_FUNC_DECL bool intersectLineLine(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c,
tvec2<T, P> const& d
);
//! Returns true if the two given line segments intersect properly (i.e. they
/// both cross one another without merely touching).
//! From GLM_GTX_intersect extension
/// @param a, b The two endpoints of the first line segment (ab)
/// @param c, d The two endpoints of the second line segment (cd)
template <typename T, precision P = defaultp>
GLM_FUNC_DECL bool intersectLineLineProper(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c,
tvec2<T, P> const& d
);
///! Returns true if the two given line segments properly overlap one another
/// (i.e. they're collinear and their intersection is a line segment of non-zero
/// length).
/// From GLM_GTX_intersect extension
template <typename T, precision P = defaultp>
GLM_FUNC_DECL bool overlapSegment(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c,
tvec2<T, P> const& d
);
/// @} /// @}
}//namespace glm }//namespace glm

View File

@ -7,10 +7,6 @@
// File : glm/gtx/intersect.inl // File : glm/gtx/intersect.inl
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
#include "../geometric.hpp"
#include <cfloat>
#include <limits>
namespace glm namespace glm
{ {
template <typename genType> template <typename genType>
@ -214,4 +210,51 @@ namespace glm
intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius; intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius;
return true; return true;
} }
template <typename T, precision P>
GLM_FUNC_QUALIFIER bool intersectLineLine
(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c,
tvec2<T, P> const& d
)
{
return (isLeft(a, b, c) ^ isLeft(a, b, d))
&& (isLeft(c, d, a) ^ isLeft(c, d, b));
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER bool intersectLineLineProper
(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c,
tvec2<T, P> const& d
)
{
T Epsilon = std::numeric_limits<T>::epsilon();
if (epsilonEqual(detail::area2<T, P, float>(a, b, c), 0.0f, Epsilon) ||
epsilonEqual(detail::area2<T, P, float>(a, b, d), 0.0f, Epsilon) ||
epsilonEqual(detail::area2<T, P, float>(c, d, a), 0.0f, Epsilon) ||
epsilonEqual(detail::area2<T, P, float>(c, d, b), 0.0f, Epsilon))
// If any triple of points here is collinear...
return false;
return intersectLineLine(a, b, c, d);
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER bool overlapSegment
(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c,
tvec2<T, P> const& d
)
{
return areCollinear(a, b, c) && areCollinear(a, b, d)
&& a != c && a != d
&& b != c && b != d;
}
}//namespace glm }//namespace glm

View File

@ -43,6 +43,9 @@
// Dependency: // Dependency:
#include "../glm.hpp" #include "../glm.hpp"
#include "../gtx/area.hpp"
#include "../gtc/epsilon.hpp"
#include "../gtc/constants.hpp"
#include <cfloat> #include <cfloat>
#include <limits> #include <limits>
@ -60,6 +63,11 @@ namespace glm
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL bool areCollinear(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon); GLM_FUNC_DECL bool areCollinear(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon);
//! Returns true if the three given points are collinear.
/// @see gtx_vector_query extensions
template<typename T, precision P = defaultp>
GLM_FUNC_DECL bool areCollinear(tvec2<T, P> const& a, tvec2<T, P> const& b, tvec2<T, P> const& c);
//! Check whether two vectors are orthogonals. //! Check whether two vectors are orthogonals.
/// @see gtx_vector_query extensions. /// @see gtx_vector_query extensions.
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
@ -85,6 +93,21 @@ namespace glm
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_DECL bool areOrthonormal(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon); GLM_FUNC_DECL bool areOrthonormal(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon);
//! Returns true if the given vector is to the left of the given oriented line
/// segment, with respect to its direction.
/// @param a, b The two vectors that make up the line segment to test against
/// @param v The point to test against the line segment
/// @see gtx_vector_query extensions
template<typename T, precision P>
GLM_FUNC_DECL bool isLeft(tvec2<T, P> const& a, tvec2<T, P> const& b, tvec2<T, P> const& v);
//! Returns true if the given vector is to the left of or on the given oriented
/// line segment, with respect to its direction.
/// @param a, b The two vectors that make up the line segment to test against
/// @param v The point to test against the line segment
/// @see gtx_vector_query extensions
template<typename T, precision P>
GLM_FUNC_DECL bool isLeftOrOn(tvec2<T, P> const& a, tvec2<T, P> const& b, tvec2<T, P> const& v);
/// @} /// @}
}// namespace glm }// namespace glm

View File

@ -119,6 +119,17 @@ namespace detail
return detail::compute_areCollinear<T, P, vecType>::call(v0, v1, epsilon); return detail::compute_areCollinear<T, P, vecType>::call(v0, v1, epsilon);
} }
template<typename T, precision P>
GLM_FUNC_QUALIFIER bool areCollinear
(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& c
)
{
return epsilonEqual(detail::area2(a, b, c), 0.0f, epsilon<float>());
}
template <typename T, precision P, template <typename, precision> class vecType> template <typename T, precision P, template <typename, precision> class vecType>
GLM_FUNC_QUALIFIER bool areOrthogonal GLM_FUNC_QUALIFIER bool areOrthogonal
( (
@ -219,4 +230,25 @@ namespace detail
return isNormalized(v0, epsilon) && isNormalized(v1, epsilon) && (abs(dot(v0, v1)) <= epsilon); return isNormalized(v0, epsilon) && isNormalized(v1, epsilon) && (abs(dot(v0, v1)) <= epsilon);
} }
template <typename T, precision P>
GLM_FUNC_QUALIFIER bool isLeft
(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& v
)
{
return detail::area2(a, b, v) > 0;
}
template <typename T, precision P>
GLM_FUNC_QUALIFIER bool isLeftOrOn
(
tvec2<T, P> const& a,
tvec2<T, P> const& b,
tvec2<T, P> const& v
)
{
return detail::area2(a, b, v) >= 0;
}
}//namespace glm }//namespace glm

View File

@ -1,3 +1,4 @@
glmCreateTestGTC(gtx_area)
glmCreateTestGTC(gtx_associated_min_max) glmCreateTestGTC(gtx_associated_min_max)
glmCreateTestGTC(gtx_closest_point) glmCreateTestGTC(gtx_closest_point)
glmCreateTestGTC(gtx_color_space_YCoCg) glmCreateTestGTC(gtx_color_space_YCoCg)

106
test/gtx/gtx_area.cpp Normal file
View File

@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////////
/// OpenGL Mathematics (glm.g-truc.net)
///
/// Copyright (c) 2015 G-Truc Creation (www.g-truc.net)
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// Restrictions:
/// By making use of the Software for military purposes, you choose to make
/// a Bunny unhappy.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
/// THE SOFTWARE.
///
/// @file test/gtx/gtx_area.cpp
/// @date 2015-09-27
/// @author Jesse Talavera-Greenberg
///////////////////////////////////////////////////////////////////////////////////
#include <glm/gtx/area.hpp>
#include <glm/vec2.hpp>
#include <glm/gtc/epsilon.hpp>
using namespace glm;
const float EPSILON = epsilon<float>();
int test_triangle_area_zero() {
int Error(0);
vec2 a(0, 0), b(0, 0), c(0, 0);
Error += epsilonEqual(area(a, b, c), 0.0f, EPSILON) ? 0 : 1;
return Error;
}
int test_triangle_area_clockwise_negative() {
int Error(0);
vec2 a(0, 1), b(-1, 0), c(1, 0);
// Upward-facing triangle at the origin
Error += epsilonEqual(area(a, c, b), -1.0f, EPSILON) ? 0 : 1;
Error += epsilonEqual(area(b, a, c), -1.0f, EPSILON) ? 0 : 1;
Error += epsilonEqual(area(c, b, a), -1.0f, EPSILON) ? 0 : 1;
return Error;
}
int test_triangle_area_anticlockwise_positive() {
int Error(0);
vec2 a(0, 1), b(-1, 0), c(1, 0);
Error += epsilonEqual(area(a, b, c), 1.0f, EPSILON) ? 0 : 1;
Error += epsilonEqual(area(b, c, a), 1.0f, EPSILON) ? 0 : 1;
Error += epsilonEqual(area(c, a, b), 1.0f, EPSILON) ? 0 : 1;
return Error;
}
int test_triangle_area_collinear() {
int Error(0);
vec2 a(-1, 0), b(0, 0), c(1, 0);
Error += epsilonEqual(area(a, b, c), 0.0f, EPSILON) ? 0 : 1;
vec2 d(0, -1), e(0, 0), f(0, 1);
Error += epsilonEqual(area(d, e, f), 0.0f, EPSILON) ? 0 : 1;
return Error;
}
int test_polygon_area() {
int Error(0);
return Error;
}
int main()
{
int Error(0);
Error += test_triangle_area_zero();
Error += test_triangle_area_clockwise_negative();
Error += test_triangle_area_anticlockwise_positive();
Error += test_triangle_area_collinear();
Error += test_polygon_area();
return Error;
}

View File

@ -31,9 +31,52 @@
#include <glm/gtx/intersect.hpp> #include <glm/gtx/intersect.hpp>
using namespace glm;
int test_LineLine() {
int Error(0);
Error += intersectLineLine(vec2(0, 2), vec2(2, 0), vec2(1, 1), vec2(1, 3)) ? 0 : 1;
Error += intersectLineLine(vec2(-1, -1), vec2(1, 1), vec2(1, -1), vec2(-1, 1)) ? 0 : 1;
Error += intersectLineLine(vec2(-1, -1), vec2(1, 1), vec2(-1, 1), vec2(1, -1)) ? 0 : 1;
Error += !intersectLineLine(vec2(-1, 1), vec2(1, 1), vec2(-1, -1), vec2(1, -1)) ? 0 : 1;
Error += !intersectLineLine(vec2(-1, 1), vec2(1, 1), vec2(0, 0), vec2(0, -1)) ? 0 : 1;
return Error;
}
int test_LineLineProper() {
int Error(0);
Error += !intersectLineLineProper(vec2(0, 2), vec2(2, 0), vec2(1, 1), vec2(1, 3)) ? 0 : 1;
Error += intersectLineLineProper(vec2(-1, -1), vec2(1, 1), vec2(1, -1), vec2(-1, 1)) ? 0 : 1;
Error += intersectLineLineProper(vec2(-1, -1), vec2(1, 1), vec2(-1, 1), vec2(1, -1)) ? 0 : 1;
Error += !intersectLineLineProper(vec2(-1, 1), vec2(1, 1), vec2(-1, -1), vec2(1, -1)) ? 0 : 1;
Error += !intersectLineLineProper(vec2(-1, 1), vec2(1, 1), vec2(0, 0), vec2(0, -1)) ? 0 : 1;
return Error;
}
int test_overlapSegment() {
int Error(0);
Error += !overlapSegment(vec2(0, 1), vec2(2, 1), vec2(1, 1), vec2(1, 2)) ? 0 : 1;
Error += !overlapSegment(vec2(0, 1), vec2(2, 1), vec2(1, 2), vec2(1, 1)) ? 0 : 1;
Error += !overlapSegment(vec2(0, 0), vec2(0, 1), vec2(0, 1), vec2(0, 2)) ? 0 : 1;
Error += overlapSegment(vec2(0, 0), vec2(0, 1), vec2(0, 0.5), vec2(0, 2)) ? 0 : 1;
Error += overlapSegment(vec2(0.5, 1), vec2(2, 2.5), vec2(1, 1.5), vec2(1.5, 2)) ? 0 : 1;
Error += !overlapSegment(vec2(0.5, 1), vec2(2, 2.5), vec2(1, 1.51), vec2(1.5, 2)) ? 0 : 1;
return Error;
}
int main() int main()
{ {
int Error(0); int Error(0);
Error += test_LineLine();
Error += test_LineLineProper();
Error += test_overlapSegment();
return Error; return Error;
} }

View File

@ -34,6 +34,8 @@
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <glm/gtx/vector_query.hpp> #include <glm/gtx/vector_query.hpp>
using namespace glm;
int test_areCollinear() int test_areCollinear()
{ {
int Error(0); int Error(0);
@ -53,6 +55,16 @@ int test_areCollinear()
Error += TestA ? 0 : 1; Error += TestA ? 0 : 1;
} }
{
bool TestA = glm::areCollinear(glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(2, 2));
Error += TestA ? 0 : 1;
}
{
bool TestA = glm::areCollinear(glm::vec2(0, 0), glm::vec2(1, 1), glm::vec2(4, 2));
Error += !TestA ? 0 : 1;
}
return Error; return Error;
} }
@ -96,6 +108,31 @@ int test_areOrthonormal()
return Error; return Error;
} }
int test_isLeft()
{
int Error(0);
Error += isLeft(vec2(1, 1), vec2(2.5, 2), vec2(1.305, 3.062)) ? 0 : 1;
Error += isLeft(vec2(1.278, 1.176), vec2(0.734, 2.257), vec2(0.5, 1.5)) ? 0 : 1;
Error += isLeft(vec2(1.183, 1.326), vec2(0.923, 0.695), vec2(2, 0)) ? 0 : 1;
Error += !isLeft(vec2(0.923, 0.695), vec2(1.183, 1.326), vec2(2, 0)) ? 0 : 1;
Error += isLeft(vec2(0, 0), vec2(1, 0), vec2(-1, 1)) ? 0 : 1;
return Error;
}
int test_isLeftOrOn()
{
int Error(0);
Error += isLeftOrOn(vec2(0, 2), vec2(2, 0), vec2(1, 1)) ? 0 : 1;
Error += isLeftOrOn(vec2(0, 2), vec2(2, 0), vec2(2, 2)) ? 0 : 1;
Error += isLeftOrOn(ivec2(0, 2), ivec2(2, 0), ivec2(0, 5)) ? 0 : 1;
Error += isLeftOrOn(dvec2(0, 2), dvec2(2, 0), dvec2(-1, 5)) ? 0 : 1;
Error += !isLeftOrOn(vec2(0, 2), vec2(2, 0), vec2(0, 0)) ? 0 : 1;
return Error;
}
int main() int main()
{ {
int Error(0); int Error(0);
@ -105,6 +142,8 @@ int main()
Error += test_isNormalized(); Error += test_isNormalized();
Error += test_isNull(); Error += test_isNull();
Error += test_areOrthonormal(); Error += test_areOrthonormal();
Error += test_isLeft();
Error += test_isLeftOrOn();
return Error; return Error;
} }