Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
SegmentSegmentDistance.cpp
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_SegmentSegmentDistance_CPP_
9#define model_SegmentSegmentDistance_CPP_
10
11#include <cfloat>
12#include <deque>
13#include <map>
14#include <tuple>
15#include <Eigen/Dense>
16
18
19namespace model
20{
21 /**********************************************************************/
22 template <int dim>
23 long double SegmentSegmentDistance<dim>::limitRange(const long double& v)
24 {
25 if (v < 0.0)
26 {
27 return 0.0;
28 }
29 else if (v > 1.0)
30 {
31 return 1.0;
32 }
33 else
34 {
35 return v;
36 }
37 }
38
39 /**********************************************************************/
40 template <int dim>
41 std::pair<long double,long double> SegmentSegmentDistance<dim>::step4U(const long double& T) const
42 {
44 return std::make_pair(T, limitRange((T * R - S2) / D2));
45 }
46
47 /**********************************************************************/
48 template <int dim>
49 std::pair<long double,long double> SegmentSegmentDistance<dim>::step4(const long double& U) const
50 {
52 return std::make_pair(limitRange((U * R + S1) / D1), U);
53 }
54
55 /**********************************************************************/
56 template <int dim>
57 std::pair<long double,long double> SegmentSegmentDistance<dim>::step3(const long double& T) const
58 {
59 const long double U = (T * R - S2) / D2; // compute U from eq. (10)
60 if (U < 0.0 || U > 1.0)
61 { // u is not in [0,1]
62 return step4(limitRange(U));
63 }
64 else
65 { // u is in [0,1]
66 return std::make_pair(T, U);
67 }
68 }
69
70 /**********************************************************************/
71 template <int dim>
72 std::pair<long double,long double> SegmentSegmentDistance<dim>::step2() const
73 {
74 const long double T = limitRange((S1 * D2 - S2 * R) / den); // compute t from eq. (11) and limit by eq. (12)
75 return step3(T);
76 }
77
78 /**********************************************************************/
79 template <int dim>
80 std::pair<long double,long double> SegmentSegmentDistance<dim>::getTU() const
81 {
82 if (D1 < tol && D2 < tol)
83 { // Step 1b: both segments are degenerate
84 return std::make_pair(degeneracyValue, degeneracyValue);
85 }
86 else if (D1 < tol && D2 >= tol)
87 { // Step 1a: first segment is degenerate
88 return step4U(degeneracyValue);
89 }
90 else if (D1 >= tol && D2 < tol)
91 { // Step 1a: second segment is degenerate
92 return step4(degeneracyValue);
93 }
94 else
95 { // both segments are not degenerate
96 if (std::fabs(den) > tol) // MAY NEED fabs(den)>tol*D1*D2
97 { // Step 1d: skew segments
98 return step2();
99 }
100 else
101 { // Step 1c: parallel or coincident segments
102 return step3(degeneracyValue);
103 }
104 }
105 }
106
107 /**********************************************************************/
108 template <int dim>
110 const VectorDim& B0,
111 const VectorDim& C0,
112 const VectorDim& D0,
113 const double& degeneracyValue_in) :
114 /* init */ A(A0.template cast<long double>()),
115 /* init */ B(B0.template cast<long double>()),
116 /* init */ C(C0.template cast<long double>()),
117 /* init */ D(D0.template cast<long double>()),
118 /* init */ degeneracyValue(degeneracyValue_in),
119 /* init */ d1(B-A),
120 /* init */ d2(D-C),
121 /* init */ d12(C-A),
122 /* init */ R(d1.dot(d2)),
123 /* init */ S1(d1.dot(d12)),
124 /* init */ S2(d2.dot(d12)),
125 /* init */ D1(d1.squaredNorm()), // length of AB squared
126 /* init */ D2(d2.squaredNorm()), // length of CD squared
127 /* init */ den(D1*D2-R*R),
128 /* init */ tu(getTU()),
129 /* init */ t(tu.first),
130 /* init */ u(tu.second),
131 /* init */ dMin((d1*t-d2*u-d12).norm()),
132 /* init */ x0((A+t*d1).template cast<double>()),
133 /* init */ x1((C+u*d2).template cast<double>())
134 {
139
140 }
141
142 /**********************************************************************/
143 template <int dim>
145 { /*\returns the point(s) of intersection between the segments, if any.
146 * The return type is deque<tuple<x,t,u>>, where x is the intersection
147 * point, t the parameter on the first segment, u the parameter on the
148 * second segment. The deque is empty if no intersection was found.
149 * If one intersection is found, the deque contains that intersection.
150 * In case of coincident segments, the deque contains two points. These
151 * points define the line element over which the original segments overlap.
152 */
153
155
156 if (dMin < FLT_EPSILON)
157 { // an intersection exists
158
159 if (D1 < tol || D2 < tol)
160 { // At least one segment is degenerate
161 temp.emplace_back(0.5 * (x0 + x1), t, u);
162 }
163 else
164 { // both segments are not degenerate
165
166 if (std::fabs(den) > tol * D1 * D2)
167 { // Step 1d: skew segments
168 temp.emplace_back(0.5 * (x0 + x1), t, u);
169 }
170 else
171 { // coincident segments. Since there must be an intersection, the two innermost points are the overlapping segment
172
173 const long double tC = (C - A).dot(d1) / D1; // value of t for point C
174 const long double tD = (D - A).dot(d1) / D1; // value of t for point D
175
176 std::multimap<long double, VectorDimLD> ms;
177 ms.emplace(0.0, A);
178 ms.emplace(1.0, B);
179 ms.emplace(tC, C);
180 ms.emplace(tD, D);
181
182 auto iter1 = ms.begin();
183 std::advance(iter1, 1);
184 auto iter2 = ms.begin();
185 std::advance(iter2, 2);
186
187 if ((iter1->second - iter2->second).norm() > FLT_EPSILON)
188 {
189 temp.emplace_back(iter1->second.template cast<double>(), iter1->first, (iter1->second - C).dot(d2) / D2);
190 temp.emplace_back(iter2->second.template cast<double>(), iter2->first, (iter2->second - C).dot(d2) / D2);
191 }
192 else
193 {
194 temp.emplace_back((0.5 * (iter1->second + iter2->second)).template cast<double>(),
195 0.5 * (iter1->first + iter2->first),
196 0.5 * ((iter1->second - C).dot(d2) / D2 + (iter2->second - C).dot(d2) / D2));
197 }
198 }
199 }
200 }
201
202 return temp;
203 }
204
205 template <int dim>
206 bool SegmentSegmentDistance<dim>::isIntersecting(const double tolerance) const
207 {
208 return (dMin < tolerance);
209 }
210
211 template struct SegmentSegmentDistance<1>;
212 template struct SegmentSegmentDistance<2>;
213 template struct SegmentSegmentDistance<3>;
214}
215#endif
const std::pair< long double, long double > tu
IntersectionContainerType intersectionSegment() const
std::pair< long double, long double > step4U(const long double &T) const
static long double limitRange(const long double &v)
std::pair< long double, long double > step2() const
bool isIntersecting(const double tolerance=FLT_EPSILON) const
Eigen::Matrix< double, dim, 1 > VectorDim
std::pair< long double, long double > step3(const long double &T) const
std::pair< long double, long double > getTU() const
SegmentSegmentDistance(const VectorDim &A0, const VectorDim &B0, const VectorDim &C0, const VectorDim &D0, const double &degeneracyValue_in=0.0)
std::pair< long double, long double > step4(const long double &U) const
std::deque< IntersectionPointType > IntersectionContainerType
vertex temp
vertex first
REAL v[4]