17#ifndef AGXCOLLIDE_BASICPRIMITIVETESTS_H
18#define AGXCOLLIDE_BASICPRIMITIVETESTS_H
24#include <agx/agx_vector_types.h>
55 const agx::Real cosEpsilon = parallelityThreshold);
67 const agx::Real sinEpsilon = parallelityThreshold);
85 bool intersectLineSegmentHyperPlane(
109 template <
typename T>
110 bool intersectLineHyperPlane(
145 const agx::Vec3 pointP0 = lineP0 - point;
146 const agx::Vec3 dist = pointP0 - dir * (dir * pointP0) / dirLen2;
147 return dist.
length2() < epsilon * epsilon;
326 class ClosestPointsSolution
346 void closestPointsSegmentSegment(
351 ClosestPointsSolution& solution,
353 ClosestPointsSolution& parallelSolution,
387 bool clipConvexPolygonAgainstSlab(
390 const uint8_t clipDim,
409 bool clipConvexPolygonAgainstBox(
449 bool clipSegmentLineSemi1D(
529 template<
size_t N1,
size_t N2>
530 void clipConvexPolygonAgainstConvexPolygon(
547 void clipLineSegmentAgainstConvexPolygon(
620 unsigned int& triangleIndex);
665 bool clipConvexPolygonAgainstSlab(
668 const uint8_t clipDim,
683 if (cPolygon.
size() == 0)
686 for (
unsigned int i = 0; i < cPolygon.
size(); ++i)
689 while(result.
size() < 3)
693 for (
int sign = -1;
sign <=1;
sign+=2) {
695 bool lastPointWasOutside = (result[0][clipDim] *
sign > slabDistance + relativeEpsilon);
697 for (
unsigned int j = 0; j < result.
size(); ++j) {
698 int j_next = (j + 1) % (
unsigned int)result.
size();
699 bool nextPointIsOutside =
700 (result[j_next][clipDim] *
sign > slabDistance + relativeEpsilon);
701 if (lastPointWasOutside != nextPointIsOutside) {
704 if (clipSegmentLineSemi1D( result[j], result[j_next], clipDim,
705 slabDistance * sign, newPoint, relativeEpsilon )) {
709 if (!nextPointIsOutside)
711 lastPointWasOutside = nextPointIsOutside;
720 for (
size_t j = 0; j < tmp.
size(); ++j) {
721 bool addPoint =
true;
722 if (result.
size() > 0) {
723 if ((result.
back() - tmp[j]).length2() < relativeEpsilon)
731 while(result.
size() > 0 && result.
size() < 3)
740 bool clipConvexPolygonAgainstBox(
755 if (cPolygon.
size() == 0)
758 for (
size_t i = 0; i < cPolygon.
size(); ++i)
761 while (result.
size() < 3)
767 for (
int i = 0; i < 2; ++i) {
770 bool lastPointWasOutside = (result[0][dim] *
sign > boxHe[dim] + relativeEpsilon);
772 for (
unsigned int j = 0; j < result.
size(); ++j) {
773 const int j_next = (int)((j + 1) % result.
size());
774 bool nextPointIsOutside = (result[j_next][dim] *
sign > boxHe[dim] + relativeEpsilon);
775 if (lastPointWasOutside != nextPointIsOutside) {
778 if (clipSegmentLineSemi1D( result[j], result[j_next], dim, boxHe[dim] * sign, newPoint, relativeEpsilon ))
781 if (!nextPointIsOutside)
783 lastPointWasOutside = nextPointIsOutside;
792 for (
size_t j = 0; j < tmp.
size(); ++j) {
793 if (result.
size() > 0 && (result.
back() - tmp[j]).length2() < relativeEpsilon)
799 while (result.
size() > 0 && result.
size() < 3)
808 void clipLineSegmentAgainstConvexPolygon(
815 if (segment.
size() < 2 || poly.
size() < 3)
818 for (
int i = 0; i < 2; ++i)
824 for (
int i = 0; i < int(poly.
size()) - 1; ++i) {
825 agx::Vec2 tmp = (poly[(i + 1)] - poly[i]);
827 planeDists.
push_back( poly[i] * planeNormals[i] );
837 for (
unsigned int i = 0; i < poly.
size(); ++i) {
839 isInside[0] = result[0] * planeNormals[i] - planeDists[i] < epsilon;
840 isInside[1] = result[1] * planeNormals[i] - planeDists[i] < epsilon;
842 if (isInside[0] == isInside[1]) {
850 int first = isInside[0] ? 0 : 1;
851 int second = 1 - first;
853 intersectLineSegmentHyperPlane( result[first], result[second], planeNormals[i],
854 planeDists[i], tmpT, secondPoint, epsilon );
856 result[second] = secondPoint;
860 if (
equivalent( result[0], result[1], epsilon ))
865 template<
size_t N1,
size_t N2>
866 void clipConvexPolygonAgainstConvexPolygon(
877 if (poly1.
size() < 2 || poly2.
size() < 2)
880 if (poly1.
size() == 2) {
884 clipLineSegmentAgainstConvexPolygon(segment, poly2, segmentResult, epsilon);
885 for (
size_t i = 0; i < segmentResult.
size(); ++i)
890 if (poly2.
size() == 2) {
894 clipLineSegmentAgainstConvexPolygon(segment, poly1, segmentResult, epsilon);
895 for (
size_t i = 0; i < segmentResult.
size(); ++i)
900 for (
size_t i = 0; i < poly1.
size(); ++i)
906 for (
size_t i = 0; i < poly2.
size(); ++i) {
907 size_t next = (i+1) % poly2.
size();
908 agx::Vec2 tmp = (poly2[next] - poly2[i]);
910 planeNormals.
back().normalize();
911 planeDists.
push_back( poly2[i] * planeNormals[i] );
915 for (
size_t i = 0; i < poly2.
size(); ++i) {
916 if (planeNormals[i].x() * planeNormals[i].x() + planeNormals[i].y() * planeNormals[i].y() < epsilon)
920 bool lastPointWasOutside = result[0] * planeNormals[i] - planeDists[i] > epsilon;
923 for (
size_t j = 0; j < result.
size(); ++j) {
924 int j_next = int((j + 1) % result.
size());
925 bool nextPointIsOutside = result[j_next] * planeNormals[i] - planeDists[i] > epsilon;
926 if (lastPointWasOutside != nextPointIsOutside) {
930 if (intersectLineSegmentHyperPlane( result[j], result[j_next], planeNormals[i], planeDists[i], tmpT, newPoint, epsilon )) {
934 if (!nextPointIsOutside) {
937 lastPointWasOutside = nextPointIsOutside;
940 if (tmpPoints.
size() == 0)
943 for (
size_t j = 0; j < tmpPoints.
size(); ++j) {
944 bool addPoint =
true;
945 if (result.
size() > 0) {
946 if ((result.
back() - tmpPoints[j]).length2() < epsilon)
948 if ((
int)j ==
int(tmpPoints.
size()) - 1) {
949 if ((result[0] - tmpPoints[j]).length2() < epsilon)
966 ClosestPointsSolution& solution,
968 ClosestPointsSolution& parallelSolution,
972 closestPointsSegmentSegment(start1, end1, start2, end2,
973 solution.pointOn1, solution.pointOn2, solution.t1, solution.t2,
975 parallelSolution.pointOn1, parallelSolution.pointOn2, parallelSolution.t1, parallelSolution.t2, epsilon);
998 agx::Real t = (clipBoundary - a[dim]) / divisor;
999 result = a * (1 - t) + b * t;
1000 return (t >= 0 && t <= 1);
1005 template <
typename T>
1020 result = linePoint + lineDir;
1025 t = (d - normal * linePoint) / divisor;
1027 result = linePoint + lineDir * t;
1033 template <
typename T>
1043 if (intersectLineHyperPlane(lineP1, lineP2 - lineP1, normal, d, t, result, epsilon)) {
1044 const bool isInInterval = (t > -epsilon && t <
agx::Real(1) + epsilon);
1045 return isInInterval;
1056 bool areParallel = (std::abs(cosAngle) >= cosEpsilon);
1065 const agx::Real cosAngleSquared = cosAngle * cosAngle;
1067 bool areOrthogonal = (sinAngleSquared >= sinEpsilon * sinEpsilon);
1068 return areOrthogonal;
1085 t = ((p - s0) * sDir) / divisor;
1087 const agx::Vec3 point = s0 * (1 - t) + s1 * t;
1105 const agx::Vec3 capsHalfExt = capsuleEnd1 - capsMid;
1109 for (
size_t i = 0; i < 3; ++i) {
1110 if (capsAbsMid[i] > boxHe[i] + capsRadius + capsAbsHalfExt[i])
1116 agx::Vec3 closest = closestPointPointSegment(
agx::Vec3(), capsuleEnd0, capsuleEnd1, t);
1122 if (closestDist > capsRadius + closestAbsDir * boxHe )
#define AGXPHYSICS_EXPORT
Mesh is a common base class for triangle meshes, such as Mesh or HeightField.
Class representing the mathematical concept of a plane, also called a half- space.
Templated stack array class.
size_t size() const
Get the size of the array (number of filled slots).
void push_back(const T &value)
Real normalize()
Normalize the vector so that it has length unity.
Real length2() const
Length squared of the vector = vec .
Vector containing 'raw' data.
#define DOXYGEN_END_INTERNAL_BLOCK()
#define DOXYGEN_START_INTERNAL_BLOCK()
This namespace consists of a set of classes for handling geometric intersection tests including boole...
T absolute(T v)
return the absolute value.
AGXCORE_EXPORT const Real REAL_SQRT_EPSILON
T1 clamp(T1 v, T2 minimum, T3 maximum)
AGXCORE_EXPORT const Real RealEpsilon
AGXPHYSICS_EXPORT agx::Bool equalsZero(const agx::AddedMassInteraction::Matrix6x6 &matrix, agx::Real eps=agx::RealEpsilon)
static constexpr Real AGX_EQUIVALENT_EPSILON
AGXPHYSICS_EXPORT agx::Bool equivalent(const agx::AddedMassInteraction::Matrix6x6 &lhs, const agx::AddedMassInteraction::Matrix6x6 &rhs, agx::Real eps=agx::RealEpsilon)