Loading [MathJax]/extensions/tex2jax.js
Radium Engine  1.5.28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
distance.cpp
1#include <Core/Geometry/DistanceQueries.hpp>
2#include <Core/Math/LinearAlgebra.hpp> // Math::getOrthogonalVectors
3#include <Core/Math/Math.hpp> // Math::areApproxEqual
4#include <Core/Types.hpp>
5#include <Eigen/Core>
6#include <catch2/catch_test_macros.hpp>
7#include <cmath>
8
9TEST_CASE( "Core/Geometry/DistanceQueries", "[unittests][Core][Core/Geometry][DistanceQueries]" ) {
10
11 using namespace Ra::Core;
12 SECTION( "Simple tests" ) {
13 Vector3 a( -2.f, 0.f, 0.f );
14 Vector3 b( 2.f, 0.f, 0.f );
15 Vector3 c( 0.f, 3.f, 0.f );
16 Vector3 d( 0.f, -3.f, 0.f );
17 Vector3 e( -4.f, -3.f, 0.f );
18 Vector3 f( 4.f, 3.f, 0.f );
19
20 // Test point to triangle query
21 Scalar distPointToTri = std::sqrt( Geometry::pointToTriSq( c, a, b, d ).distanceSquared );
22 // Distance point to triangle
23 REQUIRE( Math::areApproxEqual( distPointToTri, ( c - ( .5_ra * ( a + b ) ) ).norm() ) );
24
25 // Test line to segment distance query
26 const Vector3& lineOrigin = a;
27 Vector3 lineDirection = d - a;
28 const Vector3& segCenter = .5_ra * ( c + b );
29 Vector3 segDirection = b - c;
30 Scalar segExtent = .5_ra * std::sqrt( ( b - c ).dot( b - c ) );
31 Scalar distLineToSeg =
32 Geometry::lineToSegSq( lineOrigin, lineDirection, segCenter, segDirection, segExtent )
33 .sqrDistance;
34 REQUIRE( Math::areApproxEqual( distLineToSeg, Geometry::pointToSegmentSq( a, c, b - c ) ) );
35
36 // Test line to triangle distance query
37 Vector3 v[3] = { a, d, e };
38 Scalar distLineToTri = Geometry::lineToTriSq( segCenter, segDirection, v ).sqrDistance;
39 REQUIRE( Math::areApproxEqual( distLineToTri, Geometry::pointToSegmentSq( a, c, b - c ) ) );
40
41 // Test segment to triangle distance query
42 Scalar distSegToTri =
43 Geometry::segmentToTriSq( segCenter, segDirection, segExtent, v ).sqrDistance;
44 REQUIRE( Math::areApproxEqual( distSegToTri, Geometry::pointToSegmentSq( a, c, b - c ) ) );
45
46 // Test triangle to triangle distance query
47 Vector3 v2[3] = { c, f, b };
48 Scalar distTriToTri = Geometry::triangleToTriSq( v, v2 ).sqrDistance;
49 REQUIRE( Math::areApproxEqual( distTriToTri, Geometry::pointToSegmentSq( a, c, b - c ) ) );
50 }
51
52 Vector3 a( 1_ra, 2.3_ra, 4.5_ra );
53 Vector3 b( -6_ra, 7_ra, 8.9_ra );
54 Vector3 c( -3_ra, 12.3_ra, -42.1_ra );
55
56 // Midpoint.
57 Vector3 m = 0.5_ra * ( a + b );
58
59 // Point on the line, before A
60 Vector3 na = a - 12_ra * ( b - a );
61
62 // Point on the line after B
63 Vector3 nb = a + 42_ra * ( b - a );
64
65 Vector3 y, z;
66 Math::getOrthogonalVectors( ( b - a ).normalized(), y, z );
67
68 SECTION( "Test line queries" ) {
69 // distance from A to AB
70 REQUIRE( Math::areApproxEqual( Geometry::pointToLineSq( a, a, b - a ), 0_ra ) );
71 // distance from B to AB
72 REQUIRE( Math::areApproxEqual( Geometry::pointToLineSq( b, a, b - a ), 0_ra ) );
73 // point on the line
74 REQUIRE( Math::areApproxEqual( Geometry::pointToLineSq( na, a, b - a ), 0_ra ) );
75 REQUIRE( Math::areApproxEqual( Geometry::pointToLineSq( nb, a, b - a ), 0_ra ) );
76 // point perpendicular to segment.
77 REQUIRE(
78 Math::areApproxEqual( Geometry::pointToLineSq( m + y, a, b - a ), y.squaredNorm() ) );
79 }
80
81 SECTION( "Test segment queries" ) {
82 // segment extremity
83 REQUIRE( Math::areApproxEqual( Geometry::pointToSegmentSq( a, a, b - a ), 0_ra ) );
84 REQUIRE( Math::areApproxEqual( Geometry::pointToSegmentSq( b, a, b - a ), 0_ra ) );
85 // point on the line
86 REQUIRE( Math::areApproxEqual( Geometry::pointToSegmentSq( na, a, b - a ),
87 ( na - a ).squaredNorm() ) );
88 REQUIRE( Math::areApproxEqual( Geometry::pointToSegmentSq( nb, a, b - a ),
89 ( nb - b ).squaredNorm() ) );
90 // point perpendicular to segment
91 REQUIRE( Math::areApproxEqual( Geometry::pointToSegmentSq( m + y, a, b - a ),
92 y.squaredNorm() ) );
93 }
94
95 SECTION( "Triangle queries: Test that each vertex returns itself" ) {
96 // distance from A to ABC
97 auto da = Geometry::pointToTriSq( a, a, b, c );
98 REQUIRE( Math::areApproxEqual( da.distanceSquared, 0_ra ) );
99 REQUIRE( da.meshPoint == a );
100 REQUIRE( da.flags == Geometry::FlagsInternal::HIT_A );
101
102 // distance from B to ABC
103 auto db = Geometry::pointToTriSq( b, a, b, c );
104 REQUIRE( Math::areApproxEqual( db.distanceSquared, 0_ra ) );
105 REQUIRE( db.meshPoint == b );
106 REQUIRE( db.flags == Geometry::FlagsInternal::HIT_B );
107
108 // distance from C to ABC
109 auto dc = Geometry::pointToTriSq( c, a, b, c );
110 REQUIRE( Math::areApproxEqual( dc.distanceSquared, 0_ra ) );
111 REQUIRE( dc.meshPoint == c );
112 REQUIRE( dc.flags == Geometry::FlagsInternal::HIT_C );
113 }
114
115 SECTION( "Triangle queries: Test midpoints of edges" ) {
116 Vector3 mab = .5_ra * ( a + b );
117 Vector3 mac = .5_ra * ( a + c );
118 Vector3 mbc = .5_ra * ( b + c );
119
120 // Distance from AB midpoint to ABC
121 auto dmab = Geometry::pointToTriSq( mab, a, b, c );
122 REQUIRE( Math::areApproxEqual( dmab.distanceSquared, 0_ra ) );
123 REQUIRE( dmab.meshPoint.isApprox( mab ) );
124 REQUIRE( dmab.flags == Geometry::FlagsInternal::HIT_AB );
125
126 // Distance from AC midpoint to ABC
127 auto dmac = Geometry::pointToTriSq( mac, a, b, c );
128 REQUIRE( Math::areApproxEqual( dmac.distanceSquared, 0_ra ) );
129 REQUIRE( dmac.meshPoint.isApprox( mac ) );
130 REQUIRE( dmac.flags == Geometry::FlagsInternal::HIT_CA );
131
132 // Distance from BC midpoint to ABC
133 auto dmbc = Geometry::pointToTriSq( mbc, a, b, c );
134 REQUIRE( Math::areApproxEqual( dmbc.distanceSquared, 0_ra ) );
135 REQUIRE( dmbc.meshPoint.isApprox( mbc ) );
136 REQUIRE( dmbc.flags == Geometry::FlagsInternal::HIT_BC );
137 }
138
139 SECTION( "Triangle queries: Test point inside the triangle" ) {
140 Vector3 g = ( 1_ra / 3_ra ) * ( a + b + c );
141
142 auto dg = Geometry::pointToTriSq( g, a, b, c );
143 // Distance from centroid to ABC
144 REQUIRE( Math::areApproxEqual( dg.distanceSquared, 0_ra ) );
145 REQUIRE( dg.meshPoint.isApprox( g ) );
146 REQUIRE( dg.flags == Geometry::FlagsInternal::HIT_FACE );
147 }
148}
This namespace contains everything "low level", related to data, datastuctures, and computation.
Definition Cage.cpp:5
T sqrt(T... args)