Line | Branch | Exec | Source |
---|---|---|---|
1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- | ||
2 | // vi: set et ts=4 sw=4 sts=4: | ||
3 | // | ||
4 | // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder | ||
5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
6 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup Geometry | ||
10 | * \brief A class for collision detection of two geometries | ||
11 | * and computation of intersection corners | ||
12 | */ | ||
13 | #ifndef DUMUX_GEOMETRY_INTERSECTION_HH | ||
14 | #define DUMUX_GEOMETRY_INTERSECTION_HH | ||
15 | |||
16 | #include <tuple> | ||
17 | |||
18 | #include <dune/common/exceptions.hh> | ||
19 | #include <dune/common/promotiontraits.hh> | ||
20 | #include <dune/geometry/multilineargeometry.hh> | ||
21 | #include <dune/geometry/referenceelements.hh> | ||
22 | |||
23 | #include <dumux/common/math.hh> | ||
24 | #include <dumux/geometry/intersectspointgeometry.hh> | ||
25 | #include <dumux/geometry/grahamconvexhull.hh> | ||
26 | #include <dumux/geometry/boundingboxtree.hh> | ||
27 | |||
28 | namespace Dumux { | ||
29 | namespace IntersectionPolicy { | ||
30 | |||
31 | //! Policy structure for point-like intersections | ||
32 | template<class ct, int dw> | ||
33 | struct PointPolicy | ||
34 | { | ||
35 | using ctype = ct; | ||
36 | using Point = Dune::FieldVector<ctype, dw>; | ||
37 | |||
38 | static constexpr int dimWorld = dw; | ||
39 | static constexpr int dimIntersection = 0; | ||
40 | using Intersection = Point; | ||
41 | }; | ||
42 | |||
43 | //! Policy structure for segment-like intersections | ||
44 | template<class ct, int dw> | ||
45 | struct SegmentPolicy | ||
46 | { | ||
47 | using ctype = ct; | ||
48 | using Point = Dune::FieldVector<ctype, dw>; | ||
49 | using Segment = std::array<Point, 2>; | ||
50 | |||
51 | static constexpr int dimWorld = dw; | ||
52 | static constexpr int dimIntersection = 1; | ||
53 | using Intersection = Segment; | ||
54 | }; | ||
55 | |||
56 | //! Policy structure for polygon-like intersections | ||
57 | template<class ct, int dw> | ||
58 | struct PolygonPolicy | ||
59 | { | ||
60 | using ctype = ct; | ||
61 | using Point = Dune::FieldVector<ctype, dw>; | ||
62 | using Polygon = std::vector<Point>; | ||
63 | |||
64 | static constexpr int dimWorld = dw; | ||
65 | static constexpr int dimIntersection = 2; | ||
66 | using Intersection = Polygon; | ||
67 | }; | ||
68 | |||
69 | //! Policy structure for polyhedron-like intersections | ||
70 | template<class ct, int dw> | ||
71 | struct PolyhedronPolicy | ||
72 | { | ||
73 | using ctype = ct; | ||
74 | using Point = Dune::FieldVector<ctype, dw>; | ||
75 | using Polyhedron = std::vector<Point>; | ||
76 | |||
77 | static constexpr int dimWorld = dw; | ||
78 | static constexpr int dimIntersection = 3; | ||
79 | using Intersection = Polyhedron; | ||
80 | }; | ||
81 | |||
82 | //! default policy chooser class | ||
83 | template<class Geometry1, class Geometry2> | ||
84 | class DefaultPolicyChooser | ||
85 | { | ||
86 | static constexpr int dimworld = Geometry1::coorddimension; | ||
87 | static constexpr int isDim = std::min( int(Geometry1::mydimension), int(Geometry2::mydimension) ); | ||
88 | static_assert(dimworld == int(Geometry2::coorddimension), | ||
89 | "Geometries must have the same coordinate dimension!"); | ||
90 | static_assert(int(Geometry1::mydimension) <= 3 && int(Geometry2::mydimension) <= 3, | ||
91 | "Geometries must have dimension 3 or less."); | ||
92 | using ctype = typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType; | ||
93 | |||
94 | using DefaultPolicies = std::tuple<PointPolicy<ctype, dimworld>, | ||
95 | SegmentPolicy<ctype, dimworld>, | ||
96 | PolygonPolicy<ctype, dimworld>, | ||
97 | PolyhedronPolicy<ctype, dimworld>>; | ||
98 | public: | ||
99 | using type = std::tuple_element_t<isDim, DefaultPolicies>; | ||
100 | }; | ||
101 | |||
102 | //! Helper alias to define the default intersection policy | ||
103 | template<class Geometry1, class Geometry2> | ||
104 | using DefaultPolicy = typename DefaultPolicyChooser<Geometry1, Geometry2>::type; | ||
105 | |||
106 | } // end namespace IntersectionPolicy | ||
107 | |||
108 | namespace Detail { | ||
109 | |||
110 | /*! | ||
111 | * \ingroup Geometry | ||
112 | * \brief Algorithm to find segment-like intersections of a polygon/polyhedron with a | ||
113 | * segment. The result is stored in the form of the local coordinates tfirst | ||
114 | * and tlast on the segment geo1. | ||
115 | * \param geo1 the first geometry | ||
116 | * \param geo2 the second geometry (dimGeo2 < dimGeo1) | ||
117 | * \param baseEps the base epsilon used for floating point comparisons | ||
118 | * \param tfirst stores the local coordinate of beginning of intersection segment | ||
119 | * \param tlast stores the local coordinate of the end of intersection segment | ||
120 | * \param getFacetCornerIndices Function to obtain the facet corner indices on geo1 | ||
121 | * \param computeNormal Function to obtain the normal vector on a facet on geo1 | ||
122 | */ | ||
123 | template< class Geo1, class Geo2, class ctype, | ||
124 | class GetFacetCornerIndices, class ComputeNormalFunction > | ||
125 | 753027 | bool computeSegmentIntersection(const Geo1& geo1, const Geo2& geo2, ctype baseEps, | |
126 | ctype& tfirst, ctype& tlast, | ||
127 | const GetFacetCornerIndices& getFacetCornerIndices, | ||
128 | const ComputeNormalFunction& computeNormal) | ||
129 | { | ||
130 | static_assert(int(Geo2::mydimension) == 1, "Geometry2 must be a segment"); | ||
131 | static_assert(int(Geo1::mydimension) > int(Geo2::mydimension), | ||
132 | "Dimension of Geometry1 must be higher than that of Geometry2"); | ||
133 | |||
134 | 753027 | const auto a = geo2.corner(0); | |
135 | 753027 | const auto b = geo2.corner(1); | |
136 | 753027 | const auto d = b - a; | |
137 | |||
138 | // The initial interval is the whole segment. | ||
139 | // Afterwards we start clipping the interval | ||
140 | // at the intersections with the facets of geo1 | ||
141 | 753027 | tfirst = 0.0; | |
142 | 753027 | tlast = 1.0; | |
143 | |||
144 |
1/2✓ Branch 1 taken 359140 times.
✗ Branch 2 not taken.
|
1506054 | const auto facets = getFacetCornerIndices(geo1); |
145 |
4/4✓ Branch 0 taken 1569625 times.
✓ Branch 1 taken 122811 times.
✓ Branch 2 taken 1569625 times.
✓ Branch 3 taken 122811 times.
|
3848263 | for (const auto& f : facets) |
146 | { | ||
147 |
1/2✓ Branch 1 taken 25123 times.
✗ Branch 2 not taken.
|
2207603 | const auto n = computeNormal(f); |
148 | |||
149 |
1/2✓ Branch 1 taken 25123 times.
✗ Branch 2 not taken.
|
3084547 | const auto c0 = geo1.corner(f[0]); |
150 | 2207603 | const ctype denom = n*d; | |
151 | 2224608 | const ctype dist = n*(a-c0); | |
152 | |||
153 | // use first edge of the facet to scale eps | ||
154 |
2/4✓ Branch 1 taken 25123 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 25123 times.
✗ Branch 5 not taken.
|
7950587 | const auto edge1 = geo1.corner(f[1]) - geo1.corner(f[0]); |
155 | 2207603 | const ctype eps = baseEps*edge1.two_norm(); | |
156 | |||
157 | // if denominator is zero the segment in parallel to the edge. | ||
158 | // If the distance is positive there is no intersection | ||
159 | using std::abs; | ||
160 |
4/4✓ Branch 0 taken 382776 times.
✓ Branch 1 taken 1186849 times.
✓ Branch 2 taken 382776 times.
✓ Branch 3 taken 1186849 times.
|
4415206 | if (abs(denom) < eps) |
161 | { | ||
162 |
2/2✓ Branch 0 taken 320704 times.
✓ Branch 1 taken 62072 times.
|
422989 | if (dist > eps) |
163 | 618421 | return false; | |
164 | } | ||
165 | else // not parallel: compute line-line intersection | ||
166 | { | ||
167 | 1784614 | const ctype t = -dist / denom; | |
168 | // if entering half space cut tfirst if t is larger | ||
169 | using std::signbit; | ||
170 |
4/4✓ Branch 0 taken 667775 times.
✓ Branch 1 taken 519074 times.
✓ Branch 2 taken 667775 times.
✓ Branch 3 taken 519074 times.
|
3569228 | if (signbit(denom)) |
171 | { | ||
172 |
2/2✓ Branch 0 taken 395741 times.
✓ Branch 1 taken 272034 times.
|
1008961 | if (t > tfirst) |
173 | 637552 | tfirst = t; | |
174 | } | ||
175 | // if exiting half space cut tlast if t is smaller | ||
176 | else | ||
177 | { | ||
178 |
2/2✓ Branch 0 taken 371360 times.
✓ Branch 1 taken 147714 times.
|
775653 | if (t < tlast) |
179 | 605165 | tlast = t; | |
180 | } | ||
181 | // there is no intersection of the interval is empty | ||
182 | // use unscaled epsilon since t is in local coordinates | ||
183 |
2/2✓ Branch 0 taken 813526 times.
✓ Branch 1 taken 373323 times.
|
1784614 | if (tfirst > tlast - baseEps) |
184 | return false; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | // If we made it until here an intersection exists. | ||
189 | return true; | ||
190 | } | ||
191 | |||
192 | } // end namespace Detail | ||
193 | |||
194 | /*! | ||
195 | * \ingroup Geometry | ||
196 | * \brief A class for geometry collision detection and intersection calculation | ||
197 | * The class can be specialized for combinations of dimworld, dim1, dim2, where | ||
198 | * dimworld is the world dimension embedding a grid of dim1 and a grid of dim2. | ||
199 | */ | ||
200 | template | ||
201 | <class Geometry1, class Geometry2, | ||
202 | class Policy = IntersectionPolicy::DefaultPolicy<Geometry1, Geometry2>, | ||
203 | int dimworld = Geometry1::coorddimension, | ||
204 | int dim1 = Geometry1::mydimension, | ||
205 | int dim2 = Geometry2::mydimension> | ||
206 | class GeometryIntersection | ||
207 | { | ||
208 | static constexpr int dimWorld = Policy::dimWorld; | ||
209 | |||
210 | public: | ||
211 | using ctype = typename Policy::ctype; | ||
212 | using Point = typename Policy::Point; | ||
213 | using Intersection = typename Policy::Intersection; | ||
214 | |||
215 | //! Determine if the two geometries intersect and compute the intersection geometry | ||
216 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
217 | { | ||
218 | static_assert(dimworld == Geometry2::coorddimension, "Can only intersect geometries of same coordinate dimension"); | ||
219 | DUNE_THROW(Dune::NotImplemented, "Geometry intersection detection with intersection computation not implemented for dimworld = " | ||
220 | << dimworld << ", dim1 = " << dim1 << ", dim2 = " << dim2); | ||
221 | } | ||
222 | }; | ||
223 | |||
224 | /*! | ||
225 | * \ingroup Geometry | ||
226 | * \brief A class for segment--segment intersection in 2d space | ||
227 | */ | ||
228 | template <class Geometry1, class Geometry2, class Policy> | ||
229 | class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 1, 1> | ||
230 | { | ||
231 | enum { dimworld = 2 }; | ||
232 | enum { dim1 = 1 }; | ||
233 | enum { dim2 = 1 }; | ||
234 | |||
235 | // base epsilon for floating point comparisons | ||
236 | static constexpr typename Policy::ctype eps_ = 1.5e-7; | ||
237 | |||
238 | public: | ||
239 | using ctype = typename Policy::ctype; | ||
240 | using Point = typename Policy::Point; | ||
241 | using Intersection = typename Policy::Intersection; | ||
242 | |||
243 | /*! | ||
244 | * \brief Colliding two segments | ||
245 | * \param geo1/geo2 The geometries to intersect | ||
246 | * \param intersection The intersection point | ||
247 | * \note This overload is used when point-like intersections are seeked | ||
248 | */ | ||
249 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
250 | 1896112 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
251 | { | ||
252 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
253 | |||
254 | 1896112 | const auto v1 = geo1.corner(1) - geo1.corner(0); | |
255 | 1896112 | const auto v2 = geo2.corner(1) - geo2.corner(0); | |
256 | 1896112 | const auto ac = geo2.corner(0) - geo1.corner(0); | |
257 | |||
258 | 5688336 | auto n2 = Point({-1.0*v2[1], v2[0]}); | |
259 | 3792224 | n2 /= n2.two_norm(); | |
260 | |||
261 | // compute distance of first corner on geo2 to line1 | ||
262 | const auto dist12 = n2*ac; | ||
263 | |||
264 | // first check parallel segments | ||
265 | using std::abs; | ||
266 | using std::sqrt; | ||
267 | |||
268 | 1896112 | const auto v1Norm2 = v1.two_norm2(); | |
269 | 1896112 | const auto eps = eps_*sqrt(v1Norm2); | |
270 | 1896112 | const auto eps2 = eps_*v1Norm2; | |
271 | |||
272 | 1896112 | const auto sp = n2*v1; | |
273 |
4/4✓ Branch 0 taken 947872 times.
✓ Branch 1 taken 948240 times.
✓ Branch 2 taken 947872 times.
✓ Branch 3 taken 948240 times.
|
3792224 | if (abs(sp) < eps) |
274 | { | ||
275 |
4/4✓ Branch 0 taken 213648 times.
✓ Branch 1 taken 734224 times.
✓ Branch 2 taken 213648 times.
✓ Branch 3 taken 734224 times.
|
1895744 | if (abs(dist12) > eps) |
276 | return false; | ||
277 | |||
278 | // point intersection can only be one of the corners | ||
279 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 213640 times.
|
213648 | if ( (v1*v2) < 0.0 ) |
280 | { | ||
281 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | if ( ac.two_norm2() < eps2 ) |
282 | 4 | { intersection = geo2.corner(0); return true; } | |
283 | |||
284 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
12 | if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 ) |
285 | ✗ | { intersection = geo2.corner(1); return true; } | |
286 | } | ||
287 | else | ||
288 | { | ||
289 |
2/2✓ Branch 2 taken 63892 times.
✓ Branch 3 taken 149748 times.
|
640920 | if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 ) |
290 | 63892 | { intersection = geo2.corner(1); return true; } | |
291 | |||
292 |
2/2✓ Branch 2 taken 63896 times.
✓ Branch 3 taken 85852 times.
|
449244 | if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 ) |
293 | 63896 | { intersection = geo2.corner(0); return true; } | |
294 | } | ||
295 | |||
296 | // no intersection | ||
297 | 85856 | return false; | |
298 | } | ||
299 | |||
300 | // intersection point on v1 in local coords | ||
301 | 948240 | const auto t1 = dist12 / sp; | |
302 | |||
303 | // check if the local coords are valid | ||
304 |
4/4✓ Branch 0 taken 796348 times.
✓ Branch 1 taken 151892 times.
✓ Branch 2 taken 644404 times.
✓ Branch 3 taken 151944 times.
|
948240 | if (t1 < -1.0*eps_ || t1 > 1.0 + eps_) |
305 | return false; | ||
306 | |||
307 | // compute global coordinates | ||
308 | 1288808 | auto isPoint = geo1.global(t1); | |
309 | |||
310 | // check if point is in bounding box of v2 | ||
311 | 644404 | const auto c = geo2.corner(0); | |
312 | 644404 | const auto d = geo2.corner(1); | |
313 | |||
314 | using std::min; using std::max; | ||
315 |
24/24✓ Branch 0 taken 60 times.
✓ Branch 1 taken 644344 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 644344 times.
✓ Branch 4 taken 60 times.
✓ Branch 5 taken 644344 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 644396 times.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 644396 times.
✓ Branch 10 taken 8 times.
✓ Branch 11 taken 644396 times.
✓ Branch 12 taken 322208 times.
✓ Branch 13 taken 322196 times.
✓ Branch 14 taken 322208 times.
✓ Branch 15 taken 322196 times.
✓ Branch 16 taken 322208 times.
✓ Branch 17 taken 322196 times.
✓ Branch 18 taken 322236 times.
✓ Branch 19 taken 322168 times.
✓ Branch 20 taken 322236 times.
✓ Branch 21 taken 322168 times.
✓ Branch 22 taken 322236 times.
✓ Branch 23 taken 322168 times.
|
2900040 | std::array<ctype, 4> bBox({ min(c[0], d[0]), min(c[1], d[1]), max(c[0], d[0]), max(c[1], d[1]) }); |
316 | |||
317 |
4/4✓ Branch 0 taken 302220 times.
✓ Branch 1 taken 342184 times.
✓ Branch 2 taken 302220 times.
✓ Branch 3 taken 342184 times.
|
1288808 | if ( intersectsPointBoundingBox(isPoint, bBox.data()) ) |
318 | { | ||
319 | 302220 | intersection = std::move(isPoint); | |
320 | 302220 | return true; | |
321 | } | ||
322 | |||
323 | return false; | ||
324 | } | ||
325 | |||
326 | /*! | ||
327 | * \brief Colliding two segments | ||
328 | * \param geo1/geo2 The geometries to intersect | ||
329 | * \param intersection Container to store corners of intersection segment | ||
330 | * \note this overload is used when segment-like intersections are seeked | ||
331 | */ | ||
332 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
333 | 68 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
334 | { | ||
335 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
336 | |||
337 | 68 | const auto& a = geo1.corner(0); | |
338 | 68 | const auto& b = geo1.corner(1); | |
339 | 68 | const auto ab = b - a; | |
340 | |||
341 | 68 | const auto& p = geo2.corner(0); | |
342 | 68 | const auto& q = geo2.corner(1); | |
343 | 68 | const auto pq = q - p; | |
344 | 204 | Dune::FieldVector<ctype, dimworld> n2{-pq[1], pq[0]}; | |
345 | |||
346 | using std::max; | ||
347 | 68 | const auto abNorm2 = ab.two_norm2(); | |
348 | 68 | const auto pqNorm2 = pq.two_norm2(); | |
349 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 48 times.
|
68 | const auto eps2 = eps_*max(abNorm2, pqNorm2); |
350 | |||
351 | // non-parallel segments do not intersect in a segment. | ||
352 | using std::abs; | ||
353 |
4/4✓ Branch 0 taken 64 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 4 times.
|
204 | if (abs(n2*ab) > eps2) |
354 | return false; | ||
355 | |||
356 | // check if the segments lie on the same line | ||
357 | 64 | const auto ap = p - a; | |
358 |
4/4✓ Branch 0 taken 60 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 4 times.
|
192 | if (abs(ap*n2) > eps2) |
359 | return false; | ||
360 | |||
361 | // compute scaled local coordinates of corner 1/2 of segment2 on segment1 | ||
362 | 60 | auto t1 = ab*ap; | |
363 | 120 | auto t2 = ab*(q - a); | |
364 | |||
365 | using std::swap; | ||
366 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 27 times.
|
60 | if (t1 > t2) |
367 | 33 | swap(t1, t2); | |
368 | |||
369 | using std::clamp; | ||
370 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 16 times.
|
60 | t1 = clamp(t1, 0.0, abNorm2); |
371 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 4 times.
|
60 | t2 = clamp(t2, 0.0, abNorm2); |
372 | |||
373 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 32 times.
|
120 | if (abs(t2-t1) < eps2) |
374 | return false; | ||
375 | |||
376 | 56 | intersection = Intersection({geo1.global(t1/abNorm2), geo1.global(t2/abNorm2)}); | |
377 | 28 | return true; | |
378 | } | ||
379 | }; | ||
380 | |||
381 | /*! | ||
382 | * \ingroup Geometry | ||
383 | * \brief A class for polygon--segment intersection in 2d space | ||
384 | */ | ||
385 | template <class Geometry1, class Geometry2, class Policy> | ||
386 | class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 2, 1> | ||
387 | { | ||
388 | enum { dimworld = 2 }; | ||
389 | enum { dim1 = 2 }; | ||
390 | enum { dim2 = 1 }; | ||
391 | |||
392 | public: | ||
393 | using ctype = typename Policy::ctype; | ||
394 | using Point = typename Policy::Point; | ||
395 | using Intersection = typename Policy::Intersection; | ||
396 | |||
397 | private: | ||
398 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
399 | |||
400 | public: | ||
401 | /*! | ||
402 | * \brief Colliding segment and convex polygon | ||
403 | * \param geo1/geo2 The geometries to intersect | ||
404 | * \param intersection If the geometries collide intersection holds the | ||
405 | * corner points of the intersection object in global coordinates. | ||
406 | * \note This overload is used when segment-like intersections are seeked. | ||
407 | */ | ||
408 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
409 | 320 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
410 | { | ||
411 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
412 | |||
413 | ctype tfirst, tlast; | ||
414 |
2/4✓ Branch 1 taken 306 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
320 | if (intersect_(geo1, geo2, tfirst, tlast)) |
415 | { | ||
416 | // the intersection exists. Export the intersections geometry now: | ||
417 | // s(t) = a + t(b-a) in [tfirst, tlast] | ||
418 | 1224 | intersection = Intersection({geo2.global(tfirst), geo2.global(tlast)}); | |
419 | 306 | return true; | |
420 | } | ||
421 | |||
422 | return false; | ||
423 | } | ||
424 | |||
425 | /*! | ||
426 | * \brief Colliding segment and convex polygon | ||
427 | * \param geo1/geo2 The geometries to intersect | ||
428 | * \param intersection If the geometries collide intersection holds the | ||
429 | * corner points of the intersection object in global coordinates. | ||
430 | * \note This overload is used when point-like intersections are seeked. | ||
431 | */ | ||
432 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
433 | 24 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename P::Intersection& intersection) | |
434 | { | ||
435 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
436 | |||
437 | ctype tfirst, tlast; | ||
438 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 20 times.
|
24 | if (!intersect_(geo1, geo2, tfirst, tlast)) |
439 | { | ||
440 | // if start & end point are same, the intersection is a point | ||
441 | using std::abs; | ||
442 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if ( tfirst > tlast - eps_ ) |
443 | { | ||
444 | 8 | intersection = Intersection(geo2.global(tfirst)); | |
445 | 4 | return true; | |
446 | } | ||
447 | } | ||
448 | |||
449 | return false; | ||
450 | } | ||
451 | |||
452 | private: | ||
453 | /*! | ||
454 | * \brief Obtain local coordinates of start/end point of the intersecting segment. | ||
455 | */ | ||
456 | 4800 | static bool intersect_(const Geometry1& geo1, const Geometry2& geo2, ctype& tfirst, ctype& tlast) | |
457 | { | ||
458 | // lambda to obtain the facet corners on geo1 | ||
459 | 4752 | auto getFacetCorners = [] (const Geometry1& geo1) | |
460 | { | ||
461 |
4/10✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4715 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
4752 | std::vector< std::array<int, 2> > facetCorners; |
462 |
8/12✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4715 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
|
4800 | switch (geo1.corners()) |
463 | { | ||
464 | 26 | case 4: // quadrilateral | |
465 |
2/4✓ Branch 1 taken 4717 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
|
4730 | facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}}; |
466 | break; | ||
467 | 22 | case 3: // triangle | |
468 |
2/4✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
22 | facetCorners = {{1, 0}, {0, 2}, {2, 1}}; |
469 | break; | ||
470 | ✗ | default: | |
471 | ✗ | DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type " | |
472 | << geo1.type() << " with "<< geo1.corners() << " corners."); | ||
473 | } | ||
474 | |||
475 | 14256 | return facetCorners; | |
476 | }; | ||
477 | |||
478 | // lambda to obtain the normal on a facet | ||
479 | 4800 | const auto center1 = geo1.center(); | |
480 | 55311 | auto computeNormal = [&geo1, ¢er1] (const std::array<int, 2>& facetCorners) | |
481 | { | ||
482 | 33674 | const auto c0 = geo1.corner(facetCorners[0]); | |
483 | 33674 | const auto c1 = geo1.corner(facetCorners[1]); | |
484 | 16837 | const auto edge = c1 - c0; | |
485 | |||
486 | 50511 | Dune::FieldVector<ctype, dimworld> n({-1.0*edge[1], edge[0]}); | |
487 | 33674 | n /= n.two_norm(); | |
488 | |||
489 | // orientation of the element is not known | ||
490 | // make sure normal points outwards of element | ||
491 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 16753 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 84 times.
|
50511 | if ( n*(center1-c0) > 0.0 ) |
492 | n *= -1.0; | ||
493 | |||
494 | 16837 | return n; | |
495 | }; | ||
496 | |||
497 | 4800 | return Detail::computeSegmentIntersection(geo1, geo2, eps_, tfirst, tlast, getFacetCorners, computeNormal); | |
498 | } | ||
499 | }; | ||
500 | |||
501 | /*! | ||
502 | * \ingroup Geometry | ||
503 | * \brief A class for segment--polygon intersection in 2d space | ||
504 | */ | ||
505 | template <class Geometry1, class Geometry2, class Policy> | ||
506 | class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 1, 2> | ||
507 | : public GeometryIntersection<Geometry2, Geometry1, Policy, 2, 2, 1> | ||
508 | { | ||
509 | using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 2, 2, 1>; | ||
510 | |||
511 | public: | ||
512 | /*! | ||
513 | * \brief Colliding segment and convex polygon | ||
514 | * \param geo1/geo2 The geometries to intersect | ||
515 | * \param intersection If the geometries collide intersection holds the | ||
516 | * corner points of the intersection object in global coordinates. | ||
517 | * \note This forwards to the polygon-segment specialization with swapped arguments. | ||
518 | */ | ||
519 | template<class P = Policy> | ||
520 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection) | ||
521 | { | ||
522 |
1/2✓ Branch 1 taken 4384 times.
✗ Branch 2 not taken.
|
4406 | return Base::intersection(geo2, geo1, intersection); |
523 | } | ||
524 | }; | ||
525 | |||
526 | /*! | ||
527 | * \ingroup Geometry | ||
528 | * \brief A class for polygon--polygon intersection in 2d space | ||
529 | */ | ||
530 | template <class Geometry1, class Geometry2, class Policy> | ||
531 | class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 2, 2> | ||
532 | { | ||
533 | enum { dimworld = 2 }; | ||
534 | enum { dim1 = 2 }; | ||
535 | enum { dim2 = 2 }; | ||
536 | |||
537 | public: | ||
538 | using ctype = typename Policy::ctype; | ||
539 | using Point = typename Policy::Point; | ||
540 | using Intersection = typename Policy::Intersection; | ||
541 | |||
542 | private: | ||
543 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
544 | |||
545 | public: | ||
546 | /*! | ||
547 | * \brief Colliding two polygons | ||
548 | * \note First we find the vertex candidates for the intersection region as follows: | ||
549 | * Add polygon vertices that are inside the other polygon | ||
550 | * Add intersections of polygon edges | ||
551 | * Remove duplicate points from the list | ||
552 | * Compute the convex hull polygon | ||
553 | * Return a triangulation of that polygon as intersection | ||
554 | * \param geo1/geo2 The geometries to intersect | ||
555 | * \param intersection Container to store the corner points of the polygon (as convex hull) | ||
556 | * \note This overload is used when polygon like intersections are seeked | ||
557 | */ | ||
558 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 2, int> = 0> | ||
559 | 196032 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
560 | { | ||
561 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
562 | |||
563 | // the candidate intersection points | ||
564 |
3/6✓ Branch 1 taken 195772 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 195772 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 195772 times.
✗ Branch 7 not taken.
|
784128 | std::vector<Point> points; points.reserve(6); |
565 | |||
566 | // add polygon1 corners that are inside polygon2 | ||
567 |
4/4✓ Branch 0 taken 783048 times.
✓ Branch 1 taken 195772 times.
✓ Branch 2 taken 783048 times.
✓ Branch 3 taken 195772 times.
|
1175892 | for (int i = 0; i < geo1.corners(); ++i) |
568 |
4/5✓ Branch 1 taken 134324 times.
✓ Branch 2 taken 648724 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 76 times.
|
1567736 | if (intersectsPointGeometry(geo1.corner(i), geo2)) |
569 |
2/3✓ Branch 1 taken 134324 times.
✓ Branch 2 taken 44 times.
✗ Branch 3 not taken.
|
268736 | points.emplace_back(geo1.corner(i)); |
570 | |||
571 |
2/2✓ Branch 0 taken 195192 times.
✓ Branch 1 taken 580 times.
|
196032 | const auto numPoints1 = points.size(); |
572 |
4/4✓ Branch 0 taken 195192 times.
✓ Branch 1 taken 580 times.
✓ Branch 2 taken 195192 times.
✓ Branch 3 taken 580 times.
|
391868 | if (numPoints1 != geo1.corners()) |
573 | { | ||
574 | // add polygon2 corners that are inside polygon1 | ||
575 |
4/4✓ Branch 0 taken 780744 times.
✓ Branch 1 taken 195192 times.
✓ Branch 2 taken 780744 times.
✓ Branch 3 taken 195192 times.
|
1172688 | for (int i = 0; i < geo2.corners(); ++i) |
576 |
4/5✓ Branch 1 taken 510524 times.
✓ Branch 2 taken 270220 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48 times.
✓ Branch 5 taken 72 times.
|
1563448 | if (intersectsPointGeometry(geo2.corner(i), geo1)) |
577 |
2/3✓ Branch 1 taken 510524 times.
✓ Branch 2 taken 48 times.
✗ Branch 3 not taken.
|
1022496 | points.emplace_back(geo2.corner(i)); |
578 | |||
579 |
2/4✓ Branch 0 taken 195192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195192 times.
✗ Branch 3 not taken.
|
390904 | if (points.empty()) |
580 | return false; | ||
581 | |||
582 |
6/6✓ Branch 0 taken 118392 times.
✓ Branch 1 taken 76800 times.
✓ Branch 2 taken 118392 times.
✓ Branch 3 taken 76800 times.
✓ Branch 4 taken 118392 times.
✓ Branch 5 taken 76800 times.
|
586320 | if (points.size() - numPoints1 != geo2.corners()) |
583 | { | ||
584 |
1/2✓ Branch 1 taken 118356 times.
✗ Branch 2 not taken.
|
118528 | const auto refElement1 = referenceElement(geo1); |
585 |
1/2✓ Branch 1 taken 118356 times.
✗ Branch 2 not taken.
|
118528 | const auto refElement2 = referenceElement(geo2); |
586 | |||
587 | // add intersections of edges | ||
588 | using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>; | ||
589 | using PointPolicy = IntersectionPolicy::PointPolicy<ctype, dimworld>; | ||
590 |
4/4✓ Branch 0 taken 473532 times.
✓ Branch 1 taken 118392 times.
✓ Branch 2 taken 473532 times.
✓ Branch 3 taken 118392 times.
|
1066600 | for (int i = 0; i < refElement1.size(dim1-1); ++i) |
591 | { | ||
592 | 474036 | const auto localEdgeGeom1 = refElement1.template geometry<dim1-1>(i); | |
593 |
6/9✓ Branch 2 taken 473532 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 473424 times.
✓ Branch 5 taken 108 times.
✓ Branch 6 taken 473424 times.
✓ Branch 7 taken 108 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 108 times.
✗ Branch 10 not taken.
|
2370180 | const auto edge1 = SegGeometry( Dune::GeometryTypes::line, |
594 |
1/4✓ Branch 3 taken 473424 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
1895688 | std::vector<Point>( {geo1.global(localEdgeGeom1.corner(0)), |
595 | geo1.global(localEdgeGeom1.corner(1))} )); | ||
596 | |||
597 |
4/4✓ Branch 0 taken 1894056 times.
✓ Branch 1 taken 473532 times.
✓ Branch 2 taken 1894056 times.
✓ Branch 3 taken 473532 times.
|
4266180 | for (int j = 0; j < refElement2.size(dim2-1); ++j) |
598 | { | ||
599 | 1896072 | const auto localEdgeGeom2 = refElement2.template geometry<dim2-1>(j); | |
600 |
6/11✓ Branch 2 taken 1894056 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1893696 times.
✓ Branch 5 taken 360 times.
✓ Branch 6 taken 1893696 times.
✓ Branch 7 taken 360 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 360 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
9480360 | const auto edge2 = SegGeometry( Dune::GeometryTypes::line, |
601 |
1/5✓ Branch 3 taken 1893696 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
7583568 | std::vector<Point>( {geo2.global(localEdgeGeom2.corner(0)), |
602 | geo2.global(localEdgeGeom2.corner(1))} )); | ||
603 | |||
604 | using EdgeTest = GeometryIntersection<SegGeometry, SegGeometry, PointPolicy>; | ||
605 | 1896072 | typename EdgeTest::Intersection edgeIntersection; | |
606 |
2/2✓ Branch 1 taken 429668 times.
✓ Branch 2 taken 1464388 times.
|
1896072 | if (EdgeTest::intersection(edge1, edge2, edgeIntersection)) |
607 |
1/2✓ Branch 1 taken 429668 times.
✗ Branch 2 not taken.
|
429988 | points.emplace_back(edgeIntersection); |
608 | } | ||
609 | } | ||
610 | } | ||
611 | } | ||
612 | |||
613 |
2/4✓ Branch 0 taken 195772 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 195772 times.
✗ Branch 3 not taken.
|
392040 | if (points.empty()) |
614 | return false; | ||
615 | |||
616 | // remove duplicates | ||
617 | 783896 | const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_; | |
618 | 588060 | std::sort(points.begin(), points.end(), [&eps](const auto& a, const auto& b) -> bool | |
619 | { | ||
620 | using std::abs; | ||
621 |
48/208✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 315638 times.
✓ Branch 25 taken 855127 times.
✓ Branch 26 taken 315638 times.
✓ Branch 27 taken 855127 times.
✓ Branch 28 taken 315638 times.
✓ Branch 29 taken 855127 times.
✓ Branch 30 taken 315638 times.
✓ Branch 31 taken 855127 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 368 times.
✓ Branch 49 taken 364 times.
✓ Branch 50 taken 368 times.
✓ Branch 51 taken 364 times.
✓ Branch 52 taken 368 times.
✓ Branch 53 taken 364 times.
✓ Branch 54 taken 368 times.
✓ Branch 55 taken 364 times.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✓ Branch 96 taken 308332 times.
✓ Branch 97 taken 570504 times.
✓ Branch 98 taken 308332 times.
✓ Branch 99 taken 570504 times.
✓ Branch 100 taken 308332 times.
✓ Branch 101 taken 570504 times.
✓ Branch 102 taken 308332 times.
✓ Branch 103 taken 570504 times.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✓ Branch 120 taken 136 times.
✓ Branch 121 taken 192 times.
✓ Branch 122 taken 136 times.
✓ Branch 123 taken 192 times.
✓ Branch 124 taken 136 times.
✓ Branch 125 taken 192 times.
✓ Branch 126 taken 136 times.
✓ Branch 127 taken 192 times.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✗ Branch 136 not taken.
✗ Branch 137 not taken.
✗ Branch 138 not taken.
✗ Branch 139 not taken.
✗ Branch 140 not taken.
✗ Branch 141 not taken.
✗ Branch 142 not taken.
✗ Branch 143 not taken.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✗ Branch 156 not taken.
✗ Branch 157 not taken.
✗ Branch 158 not taken.
✗ Branch 159 not taken.
✗ Branch 160 not taken.
✗ Branch 161 not taken.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✓ Branch 192 taken 372 times.
✓ Branch 193 taken 216 times.
✓ Branch 194 taken 372 times.
✓ Branch 195 taken 216 times.
✓ Branch 196 taken 372 times.
✓ Branch 197 taken 216 times.
✓ Branch 198 taken 372 times.
✓ Branch 199 taken 216 times.
✓ Branch 200 taken 112 times.
✓ Branch 201 taken 100 times.
✓ Branch 202 taken 112 times.
✓ Branch 203 taken 100 times.
✓ Branch 204 taken 112 times.
✓ Branch 205 taken 100 times.
✓ Branch 206 taken 112 times.
✓ Branch 207 taken 100 times.
|
8205844 | return (abs(a[0]-b[0]) > eps ? a[0] < b[0] : a[1] < b[1]); |
622 | }); | ||
623 | |||
624 | 2346532 | auto removeIt = std::unique(points.begin(), points.end(), [&eps](const auto& a, const auto&b) | |
625 | { | ||
626 | 1759272 | return (b-a).two_norm() < eps; | |
627 | }); | ||
628 | |||
629 |
8/8✓ Branch 0 taken 150872 times.
✓ Branch 1 taken 44900 times.
✓ Branch 2 taken 150872 times.
✓ Branch 3 taken 44900 times.
✓ Branch 4 taken 150872 times.
✓ Branch 5 taken 44900 times.
✓ Branch 6 taken 150872 times.
✓ Branch 7 taken 44900 times.
|
784080 | points.erase(removeIt, points.end()); |
630 | |||
631 | // return false if we don't have at least three unique points | ||
632 |
4/4✓ Branch 0 taken 78584 times.
✓ Branch 1 taken 117188 times.
✓ Branch 2 taken 78584 times.
✓ Branch 3 taken 117188 times.
|
392040 | if (points.size() < 3) |
633 | return false; | ||
634 | |||
635 | // intersection polygon is convex hull of above points | ||
636 |
2/4✓ Branch 1 taken 78584 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 78584 times.
|
78820 | intersection = grahamConvexHull<2>(points); |
637 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 78584 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78584 times.
|
157640 | assert(!intersection.empty()); |
638 | return true; | ||
639 | } | ||
640 | |||
641 | /*! | ||
642 | * \brief Colliding two polygons | ||
643 | * \param geo1/geo2 The geometries to intersect | ||
644 | * \param intersection Container to store the corners of intersection segment | ||
645 | * \note this overload is used when segment-like intersections are seeked | ||
646 | * \todo implement this query | ||
647 | */ | ||
648 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
649 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
650 | { | ||
651 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
652 | DUNE_THROW(Dune::NotImplemented, "Polygon-polygon intersection detection for segment-like intersections"); | ||
653 | } | ||
654 | |||
655 | /*! | ||
656 | * \brief Colliding two polygons | ||
657 | * \param geo1/geo2 The geometries to intersect | ||
658 | * \param intersection The intersection point | ||
659 | * \note this overload is used when point-like intersections are seeked | ||
660 | * \todo implement this query | ||
661 | */ | ||
662 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
663 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
664 | { | ||
665 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
666 | DUNE_THROW(Dune::NotImplemented, "Polygon-polygon intersection detection for touching points"); | ||
667 | } | ||
668 | }; | ||
669 | |||
670 | /*! | ||
671 | * \ingroup Geometry | ||
672 | * \brief A class for polyhedron--segment intersection in 3d space | ||
673 | */ | ||
674 | template <class Geometry1, class Geometry2, class Policy> | ||
675 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 3, 1> | ||
676 | { | ||
677 | enum { dimworld = 3 }; | ||
678 | enum { dim1 = 3 }; | ||
679 | enum { dim2 = 1 }; | ||
680 | |||
681 | public: | ||
682 | using ctype = typename Policy::ctype; | ||
683 | using Point = typename Policy::Point; | ||
684 | using Intersection = typename Policy::Intersection; | ||
685 | |||
686 | private: | ||
687 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
688 | |||
689 | public: | ||
690 | /*! | ||
691 | * \brief Colliding segment and convex polyhedron | ||
692 | * \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson, | ||
693 | * published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. | ||
694 | * Basis is the theorem that for any two non-intersecting convex polyhedrons | ||
695 | * a separating plane exists. | ||
696 | * \param geo1/geo2 The geometries to intersect | ||
697 | * \param intersection If the geometries collide intersection holds the corner points of | ||
698 | * the intersection object in global coordinates. | ||
699 | * \note This overload is used when segment-like intersections are seeked. | ||
700 | */ | ||
701 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
702 | 345274 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
703 | { | ||
704 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
705 | |||
706 | ctype tfirst, tlast; | ||
707 |
2/2✓ Branch 0 taken 48535 times.
✓ Branch 1 taken 150531 times.
|
345274 | if (intersect_(geo1, geo2, tfirst, tlast)) |
708 | { | ||
709 | // Intersection exists. Export the intersections geometry now: | ||
710 | // s(t) = a + t(b-a) in [tfirst, tlast] | ||
711 | 127516 | intersection = Intersection({geo2.global(tfirst), geo2.global(tlast)}); | |
712 | 49079 | return true; | |
713 | } | ||
714 | |||
715 | return false; | ||
716 | } | ||
717 | |||
718 | /*! | ||
719 | * \brief Colliding segment and convex polyhedron | ||
720 | * \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson, | ||
721 | * published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. | ||
722 | * Basis is the theorem that for any two non-intersecting convex polyhedrons | ||
723 | * a separating plane exists. | ||
724 | * \param geo1/geo2 The geometries to intersect | ||
725 | * \param intersection If the geometries collide intersection holds the corner points of | ||
726 | * the intersection object in global coordinates. | ||
727 | * \note This overload is used when point-like intersections are seeked. | ||
728 | */ | ||
729 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
730 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
731 | { | ||
732 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
733 | |||
734 | ctype tfirst, tlast; | ||
735 | if (intersect_(geo1, geo2, tfirst, tlast)) | ||
736 | { | ||
737 | // if start & end point are same, the intersection is a point | ||
738 | using std::abs; | ||
739 | if ( abs(tfirst - tlast) < eps_ ) | ||
740 | { | ||
741 | intersection = Intersection(geo2.global(tfirst)); | ||
742 | return true; | ||
743 | } | ||
744 | } | ||
745 | |||
746 | return false; | ||
747 | } | ||
748 | |||
749 | private: | ||
750 | /*! | ||
751 | * \brief Obtain local coordinates of start/end point of the intersecting segment. | ||
752 | */ | ||
753 | static bool intersect_(const Geometry1& geo1, const Geometry2& geo2, ctype& tfirst, ctype& tlast) | ||
754 | { | ||
755 | // lambda to obtain facet corners on geo1 | ||
756 | 345274 | auto getFacetCorners = [] (const Geometry1& geo1) | |
757 | { | ||
758 |
5/7✓ Branch 0 taken 19955 times.
✓ Branch 1 taken 165559 times.
✓ Branch 2 taken 6400 times.
✓ Branch 3 taken 4720 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2432 times.
✗ Branch 6 not taken.
|
199066 | std::vector< std::vector<int> > facetCorners; |
759 | // sort facet corner so that normal n = (p1-p0)x(p2-p0) always points outwards | ||
760 |
9/10✓ Branch 0 taken 19955 times.
✓ Branch 1 taken 165559 times.
✓ Branch 2 taken 6400 times.
✓ Branch 3 taken 4720 times.
✓ Branch 4 taken 2432 times.
✓ Branch 5 taken 19955 times.
✓ Branch 6 taken 9040 times.
✓ Branch 7 taken 6400 times.
✓ Branch 8 taken 4720 times.
✗ Branch 9 not taken.
|
239181 | switch (geo1.corners()) |
761 | { | ||
762 | // todo compute intersection geometries | ||
763 | 19955 | case 8: // hexahedron | |
764 |
32/72✓ Branch 1 taken 176474 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 176474 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 176474 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 176474 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 176474 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 176474 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 176474 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 176474 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 176474 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 176474 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 176474 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 176474 times.
✗ Branch 35 not taken.
✗ Branch 37 not taken.
✓ Branch 38 taken 176474 times.
✓ Branch 39 taken 1058844 times.
✓ Branch 40 taken 176474 times.
✓ Branch 41 taken 1058844 times.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✓ Branch 54 taken 2432 times.
✗ Branch 55 not taken.
✓ Branch 57 taken 2432 times.
✗ Branch 58 not taken.
✓ Branch 60 taken 2432 times.
✗ Branch 61 not taken.
✓ Branch 63 taken 2432 times.
✗ Branch 64 not taken.
✓ Branch 66 taken 2432 times.
✗ Branch 67 not taken.
✓ Branch 69 taken 2432 times.
✗ Branch 70 not taken.
✓ Branch 72 taken 2432 times.
✗ Branch 73 not taken.
✓ Branch 75 taken 2432 times.
✗ Branch 76 not taken.
✓ Branch 78 taken 2432 times.
✗ Branch 79 not taken.
✓ Branch 81 taken 2432 times.
✗ Branch 82 not taken.
✓ Branch 84 taken 2432 times.
✗ Branch 85 not taken.
✓ Branch 87 taken 2432 times.
✗ Branch 88 not taken.
✗ Branch 90 not taken.
✓ Branch 91 taken 2432 times.
✓ Branch 92 taken 14592 times.
✓ Branch 93 taken 2432 times.
✓ Branch 94 taken 14592 times.
✗ Branch 95 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
|
1590199 | facetCorners = {{2, 0, 6, 4}, {1, 3, 5, 7}, {0, 1, 4, 5}, |
765 | {3, 2, 7, 6}, {1, 0, 3, 2}, {4, 5, 6, 7}}; | ||
766 | 19955 | break; | |
767 | 9040 | case 6: // prism | |
768 |
14/30✓ Branch 1 taken 9040 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9040 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9040 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 9040 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 9040 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 9040 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 9040 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 9040 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 9040 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 9040 times.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 9040 times.
✓ Branch 33 taken 45200 times.
✓ Branch 34 taken 9040 times.
✓ Branch 35 taken 45200 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
|
63280 | facetCorners = {{0, 2, 1}, {3, 4, 5}, {0, 1, 3, 4}, {0, 3, 2, 5}, {1, 2, 4, 5}}; |
769 | 9040 | break; | |
770 | 6400 | case 5: // pyramid | |
771 |
14/30✓ Branch 1 taken 6400 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6400 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6400 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 6400 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 6400 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 6400 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 6400 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 6400 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 6400 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 6400 times.
✗ Branch 29 not taken.
✗ Branch 31 not taken.
✓ Branch 32 taken 6400 times.
✓ Branch 33 taken 32000 times.
✓ Branch 34 taken 6400 times.
✓ Branch 35 taken 32000 times.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
|
44800 | facetCorners = {{0, 2, 1, 3}, {0, 1, 4}, {1, 3, 4}, {2, 4, 3}, {0, 4, 2}}; |
772 | 6400 | break; | |
773 | 4720 | case 4: // tetrahedron | |
774 |
12/26✓ Branch 1 taken 4720 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4720 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4720 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4720 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4720 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4720 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4720 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 4720 times.
✗ Branch 23 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 4720 times.
✓ Branch 27 taken 18880 times.
✓ Branch 28 taken 4720 times.
✓ Branch 29 taken 18880 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
|
28320 | facetCorners = {{1, 0, 2}, {0, 1, 3}, {0, 3, 2}, {1, 2, 3}}; |
775 | 4720 | break; | |
776 | ✗ | default: | |
777 | ✗ | DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type " | |
778 | << geo1.type() << ", "<< geo1.corners() << " corners."); | ||
779 | } | ||
780 | |||
781 | 398132 | return facetCorners; | |
782 | }; | ||
783 | |||
784 | // lambda to obtain the normal on a facet | ||
785 | 1604590 | auto computeNormal = [&geo1] (const std::vector<int>& facetCorners) | |
786 | { | ||
787 | 2000635 | const auto v0 = geo1.corner(facetCorners[1]) - geo1.corner(facetCorners[0]); | |
788 | 2000635 | const auto v1 = geo1.corner(facetCorners[2]) - geo1.corner(facetCorners[0]); | |
789 | |||
790 | 808747 | auto n = crossProduct(v0, v1); | |
791 | 1617494 | n /= n.two_norm(); | |
792 | |||
793 | 808747 | return n; | |
794 | }; | ||
795 | |||
796 | 199066 | return Detail::computeSegmentIntersection(geo1, geo2, eps_, tfirst, tlast, getFacetCorners, computeNormal); | |
797 | } | ||
798 | }; | ||
799 | |||
800 | /*! | ||
801 | * \ingroup Geometry | ||
802 | * \brief A class for segment--polyhedron intersection in 3d space | ||
803 | */ | ||
804 | template <class Geometry1, class Geometry2, class Policy> | ||
805 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 1, 3> | ||
806 | : public GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 1> | ||
807 | { | ||
808 | using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 1>; | ||
809 | public: | ||
810 | /*! | ||
811 | * \brief Colliding segment and convex polyhedron | ||
812 | * \param geo1/geo2 The geometries to intersect | ||
813 | * \param intersection If the geometries collide intersection holds the | ||
814 | * corner points of the intersection object in global coordinates. | ||
815 | * \note This forwards to the polyhedron-segment specialization with swapped arguments. | ||
816 | */ | ||
817 | template<class P = Policy> | ||
818 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection) | ||
819 | { | ||
820 |
1/2✓ Branch 1 taken 143776 times.
✗ Branch 2 not taken.
|
145753 | return Base::intersection(geo2, geo1, intersection); |
821 | } | ||
822 | }; | ||
823 | |||
824 | /*! | ||
825 | * \ingroup Geometry | ||
826 | * \brief A class for polygon--polygon intersections in 3d space | ||
827 | */ | ||
828 | template <class Geometry1, class Geometry2, class Policy> | ||
829 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 2, 2> | ||
830 | { | ||
831 | enum { dimworld = 3 }; | ||
832 | enum { dim1 = 2 }; | ||
833 | enum { dim2 = 2 }; | ||
834 | |||
835 | public: | ||
836 | using ctype = typename Policy::ctype; | ||
837 | using Point = typename Policy::Point; | ||
838 | using Intersection = typename Policy::Intersection; | ||
839 | |||
840 | private: | ||
841 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
842 | |||
843 | public: | ||
844 | /*! | ||
845 | * \brief Colliding two polygons | ||
846 | * \note First we find the vertex candidates for the intersection region as follows: | ||
847 | * Add vertices of first polygon that are inside the second polygon | ||
848 | * Add intersections of polygon edges | ||
849 | * Remove duplicate points from the list | ||
850 | * Compute the convex hull polygon | ||
851 | * \param geo1/geo2 The geometries to intersect | ||
852 | * \param intersection Container to store the corner points of the polygon (as convex hull) | ||
853 | * \note This overload is used when polygon like intersections are seeked | ||
854 | */ | ||
855 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 2, int> = 0> | ||
856 | 49 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
857 | { | ||
858 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
859 | |||
860 | // if the geometries are not parallel, there cannot be a polygon intersection | ||
861 | 49 | const auto a1 = geo1.corner(1) - geo1.corner(0); | |
862 | 49 | const auto b1 = geo1.corner(2) - geo1.corner(0); | |
863 | 49 | const auto n1 = crossProduct(a1, b1); | |
864 | |||
865 | 49 | const auto a2 = geo2.corner(1) - geo2.corner(0); | |
866 | 49 | const auto b2 = geo2.corner(2) - geo2.corner(0); | |
867 | 49 | const auto n2 = crossProduct(a2, b2); | |
868 | |||
869 | // compute an epsilon scaled with larger edge length | ||
870 | 49 | const auto a1Norm2 = a1.two_norm2(); | |
871 | 49 | const auto b1Norm2 = b1.two_norm2(); | |
872 | |||
873 | using std::max; | ||
874 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1 times.
|
49 | const auto maxNorm2 = max(a1Norm2, b1Norm2); |
875 | 49 | const auto eps2 = maxNorm2*eps_; | |
876 | |||
877 | // early exit if polygons are not parallel | ||
878 | using std::abs; | ||
879 |
2/2✓ Branch 1 taken 47 times.
✓ Branch 2 taken 2 times.
|
98 | if (crossProduct(n1, n2).two_norm2() > eps2*maxNorm2) |
880 | return false; | ||
881 | |||
882 | // they are parallel, verify that they are on the same plane | ||
883 | 47 | auto d1 = geo2.corner(0) - geo1.corner(0); | |
884 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 37 times.
|
94 | if (d1.two_norm2() < eps2) |
885 | 20 | d1 = geo2.corner(1) - geo1.corner(0); | |
886 | |||
887 | using std::sqrt; | ||
888 | 47 | const auto maxNorm = sqrt(maxNorm2); | |
889 | 47 | const auto eps3 = maxNorm*eps2; | |
890 | |||
891 |
4/4✓ Branch 0 taken 43 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 43 times.
✓ Branch 3 taken 4 times.
|
141 | if (abs(d1*n2) > eps3) |
892 | return false; | ||
893 | |||
894 | // the candidate intersection points | ||
895 |
3/6✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 43 times.
✗ Branch 7 not taken.
|
129 | std::vector<Point> points; points.reserve(8); |
896 | |||
897 | // add polygon1 corners that are inside polygon2 | ||
898 |
4/4✓ Branch 0 taken 130 times.
✓ Branch 1 taken 43 times.
✓ Branch 2 taken 130 times.
✓ Branch 3 taken 43 times.
|
216 | for (int i = 0; i < geo1.corners(); ++i) |
899 |
3/4✓ Branch 2 taken 130 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 80 times.
|
130 | if (intersectsPointGeometry(geo1.corner(i), geo2)) |
900 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 | points.emplace_back(geo1.corner(i)); |
901 | |||
902 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
|
43 | const auto numPoints1 = points.size(); |
903 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
|
43 | const bool resultIsGeo1 = numPoints1 == geo1.corners(); |
904 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 5 times.
|
43 | if (!resultIsGeo1) |
905 | { | ||
906 | // add polygon2 corners that are inside polygon1 | ||
907 |
4/4✓ Branch 0 taken 126 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 38 times.
|
202 | for (int i = 0; i < geo2.corners(); ++i) |
908 |
3/4✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 76 times.
|
126 | if (intersectsPointGeometry(geo2.corner(i), geo1)) |
909 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
50 | points.emplace_back(geo2.corner(i)); |
910 | |||
911 |
2/4✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
|
76 | const bool resultIsGeo2 = (points.size() - numPoints1) == geo2.corners(); |
912 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | if (!resultIsGeo2) |
913 | { | ||
914 | 38 | const auto referenceElement1 = referenceElement(geo1); | |
915 | 38 | const auto referenceElement2 = referenceElement(geo2); | |
916 | |||
917 | // add intersections of edges | ||
918 | using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>; | ||
919 | using PointPolicy = IntersectionPolicy::PointPolicy<ctype, dimworld>; | ||
920 |
4/4✓ Branch 0 taken 114 times.
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 114 times.
✓ Branch 3 taken 38 times.
|
266 | for (int i = 0; i < referenceElement1.size(dim1-1); ++i) |
921 | { | ||
922 | 114 | const auto localEdgeGeom1 = referenceElement1.template geometry<dim1-1>(i); | |
923 |
4/8✓ Branch 2 taken 114 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 114 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 114 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 114 times.
✗ Branch 10 not taken.
|
570 | const auto edge1 = SegGeometry( |
924 | Dune::GeometryTypes::line, | ||
925 |
0/2✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
228 | std::vector<Point>({ |
926 | geo1.global(localEdgeGeom1.corner(0)), | ||
927 | geo1.global(localEdgeGeom1.corner(1)) | ||
928 | }) | ||
929 | ); | ||
930 | |||
931 |
4/4✓ Branch 0 taken 378 times.
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 378 times.
✓ Branch 3 taken 114 times.
|
870 | for (int j = 0; j < referenceElement2.size(dim2-1); ++j) |
932 | { | ||
933 | 378 | const auto localEdgeGeom2 = referenceElement2.template geometry<dim2-1>(j); | |
934 |
4/10✓ Branch 2 taken 378 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 378 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 378 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 378 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
1890 | const auto edge2 = SegGeometry( |
935 | Dune::GeometryTypes::line, | ||
936 |
0/2✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
756 | std::vector<Point>({ |
937 | geo2.global(localEdgeGeom2.corner(0)), | ||
938 | geo2.global(localEdgeGeom2.corner(1)) | ||
939 | }) | ||
940 | ); | ||
941 | |||
942 | using EdgeTest = GeometryIntersection<SegGeometry, SegGeometry, PointPolicy>; | ||
943 | 378 | typename EdgeTest::Intersection edgeIntersection; | |
944 |
2/2✓ Branch 1 taken 154 times.
✓ Branch 2 taken 224 times.
|
378 | if (EdgeTest::intersection(edge1, edge2, edgeIntersection)) |
945 |
1/2✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
|
154 | points.emplace_back(edgeIntersection); |
946 | } | ||
947 | } | ||
948 | } | ||
949 | } | ||
950 | |||
951 |
2/4✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 43 times.
✗ Branch 3 not taken.
|
86 | if (points.empty()) |
952 | return false; | ||
953 | |||
954 | // remove duplicates | ||
955 | 43 | const auto eps = maxNorm*eps_; | |
956 | 129 | std::sort(points.begin(), points.end(), [eps] (const auto& a, const auto& b) -> bool | |
957 | { | ||
958 | using std::abs; | ||
959 |
16/104✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 60 times.
✓ Branch 25 taken 248 times.
✓ Branch 26 taken 60 times.
✓ Branch 27 taken 248 times.
✓ Branch 28 taken 60 times.
✓ Branch 29 taken 248 times.
✓ Branch 30 taken 60 times.
✓ Branch 31 taken 248 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✓ Branch 96 taken 71 times.
✓ Branch 97 taken 140 times.
✓ Branch 98 taken 71 times.
✓ Branch 99 taken 140 times.
✓ Branch 100 taken 71 times.
✓ Branch 101 taken 140 times.
✓ Branch 102 taken 71 times.
✓ Branch 103 taken 140 times.
|
2076 | return (abs(a[0]-b[0]) > eps ? a[0] < b[0] |
960 |
12/78✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 84 times.
✓ Branch 19 taken 164 times.
✓ Branch 20 taken 84 times.
✓ Branch 21 taken 164 times.
✓ Branch 22 taken 84 times.
✓ Branch 23 taken 164 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✗ Branch 70 not taken.
✗ Branch 71 not taken.
✓ Branch 72 taken 48 times.
✓ Branch 73 taken 92 times.
✓ Branch 74 taken 48 times.
✓ Branch 75 taken 92 times.
✓ Branch 76 taken 48 times.
✓ Branch 77 taken 92 times.
|
1164 | : (abs(a[1]-b[1]) > eps ? a[1] < b[1] |
961 |
4/26✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 84 times.
✓ Branch 7 taken 164 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 48 times.
✓ Branch 25 taken 92 times.
|
388 | : (a[2] < b[2]))); |
962 | }); | ||
963 | |||
964 | 43 | const auto squaredEps = eps*eps; | |
965 | 215 | points.erase(std::unique( | |
966 | points.begin(), points.end(), | ||
967 | 422 | [squaredEps] (const auto& a, const auto&b) { return (b-a).two_norm2() < squaredEps; }), | |
968 | points.end() | ||
969 | ); | ||
970 | |||
971 | // return false if we don't have at least three unique points | ||
972 |
4/4✓ Branch 0 taken 21 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 22 times.
|
86 | if (points.size() < 3) |
973 | return false; | ||
974 | |||
975 | // intersection polygon is convex hull of above points | ||
976 |
2/4✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21 times.
|
21 | intersection = grahamConvexHull<2>(points); |
977 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 21 times.
|
42 | assert(!intersection.empty()); |
978 | return true; | ||
979 | } | ||
980 | |||
981 | /*! | ||
982 | * \brief Colliding two polygons | ||
983 | * \param geo1/geo2 The geometries to intersect | ||
984 | * \param intersection Container to store the corners of intersection segment | ||
985 | * \note this overload is used when segment-like intersections are seeked | ||
986 | * \todo implement this query | ||
987 | */ | ||
988 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
989 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
990 | { | ||
991 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
992 | DUNE_THROW(Dune::NotImplemented, "Polygon-polygon intersection detection for segment-like intersections"); | ||
993 | } | ||
994 | |||
995 | /*! | ||
996 | * \brief Colliding two polygons | ||
997 | * \param geo1/geo2 The geometries to intersect | ||
998 | * \param intersection The intersection point | ||
999 | * \note this overload is used when point-like intersections are seeked | ||
1000 | * \todo implement this query | ||
1001 | */ | ||
1002 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
1003 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
1004 | { | ||
1005 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1006 | DUNE_THROW(Dune::NotImplemented, "Polygon-polygon intersection detection for touching points"); | ||
1007 | } | ||
1008 | }; | ||
1009 | |||
1010 | /*! | ||
1011 | * \ingroup Geometry | ||
1012 | * \brief A class for polyhedron--polygon intersection in 3d space | ||
1013 | */ | ||
1014 | template <class Geometry1, class Geometry2, class Policy> | ||
1015 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 3, 2> | ||
1016 | { | ||
1017 | enum { dimworld = 3 }; | ||
1018 | enum { dim1 = 3 }; | ||
1019 | enum { dim2 = 2 }; | ||
1020 | |||
1021 | public: | ||
1022 | using ctype = typename Policy::ctype; | ||
1023 | using Point = typename Policy::Point; | ||
1024 | using Intersection = typename Policy::Intersection; | ||
1025 | |||
1026 | private: | ||
1027 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
1028 | |||
1029 | public: | ||
1030 | /*! | ||
1031 | * \brief Colliding polygon and convex polyhedron | ||
1032 | * \note First we find the vertex candidates for the intersection region as follows: | ||
1033 | * Add triangle vertices that are inside the tetrahedron | ||
1034 | * Add tetrahedron vertices that are inside the triangle | ||
1035 | * Add all intersection points of tetrahedron edges (codim 2) with the triangle (codim 0) (6*1 tests) | ||
1036 | * Add all intersection points of triangle edges (codim 1) with tetrahedron faces (codim 1) (3*4 tests) | ||
1037 | * Remove duplicate points from the list | ||
1038 | * Compute the convex hull polygon | ||
1039 | * Return a triangulation of that polygon as intersection | ||
1040 | * \param geo1/geo2 The geometries to intersect | ||
1041 | * \param intersection Container to store the corner points of the polygon (as convex hull) | ||
1042 | * \note This overload is used when polygon like intersections are seeked | ||
1043 | */ | ||
1044 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 2, int> = 0> | ||
1045 | 42239 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
1046 | { | ||
1047 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1048 | |||
1049 | // the candidate intersection points | ||
1050 |
3/6✓ Branch 1 taken 34631 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34631 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34631 times.
✗ Branch 7 not taken.
|
168956 | std::vector<Point> points; points.reserve(10); |
1051 | |||
1052 | // add 3d geometry corners that are inside the 2d geometry | ||
1053 |
4/4✓ Branch 0 taken 249456 times.
✓ Branch 1 taken 34631 times.
✓ Branch 2 taken 249456 times.
✓ Branch 3 taken 34631 times.
|
394798 | for (int i = 0; i < geo1.corners(); ++i) |
1054 |
5/5✓ Branch 1 taken 215168 times.
✓ Branch 2 taken 34288 times.
✓ Branch 3 taken 10816 times.
✓ Branch 4 taken 209982 times.
✓ Branch 5 taken 19634 times.
|
592888 | if (intersectsPointGeometry(geo1.corner(i), geo2)) |
1055 |
2/3✓ Branch 1 taken 13304 times.
✓ Branch 2 taken 8118 times.
✗ Branch 3 not taken.
|
56358 | points.emplace_back(geo1.corner(i)); |
1056 | |||
1057 | // add 2d geometry corners that are inside the 3d geometry | ||
1058 |
4/4✓ Branch 0 taken 105037 times.
✓ Branch 1 taken 34631 times.
✓ Branch 2 taken 100525 times.
✓ Branch 3 taken 33503 times.
|
211211 | for (int i = 0; i < geo2.corners(); ++i) |
1059 |
5/5✓ Branch 1 taken 3014 times.
✓ Branch 2 taken 88675 times.
✓ Branch 3 taken 13348 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 60 times.
|
233808 | if (intersectsPointGeometry(geo2.corner(i), geo1)) |
1060 |
2/3✓ Branch 1 taken 3014 times.
✓ Branch 2 taken 8130 times.
✗ Branch 3 not taken.
|
14786 | points.emplace_back(geo2.corner(i)); |
1061 | |||
1062 | // get some geometry types | ||
1063 | using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>; | ||
1064 | using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>; | ||
1065 | |||
1066 |
1/2✓ Branch 1 taken 34611 times.
✗ Branch 2 not taken.
|
42239 | const auto refElement1 = referenceElement(geo1); |
1067 |
1/2✓ Branch 1 taken 23101 times.
✗ Branch 2 not taken.
|
42239 | const auto refElement2 = referenceElement(geo2); |
1068 | |||
1069 | // intersection policy for point-like intersections (used later) | ||
1070 | using PointPolicy = IntersectionPolicy::PointPolicy<ctype, dimworld>; | ||
1071 | |||
1072 | // add intersection points of all polyhedron edges (codim dim-1) with the polygon | ||
1073 |
4/4✓ Branch 0 taken 374184 times.
✓ Branch 1 taken 34631 times.
✓ Branch 2 taken 374184 times.
✓ Branch 3 taken 34631 times.
|
973199 | for (int i = 0; i < refElement1.size(dim1-1); ++i) |
1074 | { | ||
1075 | 465480 | const auto localEdgeGeom = refElement1.template geometry<dim1-1>(i); | |
1076 | 930960 | const auto p = geo1.global(localEdgeGeom.corner(0)); | |
1077 | 930960 | const auto q = geo1.global(localEdgeGeom.corner(1)); | |
1078 |
6/16✓ Branch 1 taken 374184 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 374184 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 374184 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 374184 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 374184 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 374184 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
2792880 | const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q}); |
1079 | |||
1080 | using PolySegTest = GeometryIntersection<Geometry2, SegGeometry, PointPolicy>; | ||
1081 | 465480 | typename PolySegTest::Intersection polySegIntersection; | |
1082 |
3/4✓ Branch 1 taken 374184 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 51273 times.
✓ Branch 4 taken 322911 times.
|
465480 | if (PolySegTest::intersection(geo2, segGeo, polySegIntersection)) |
1083 |
1/2✓ Branch 1 taken 51273 times.
✗ Branch 2 not taken.
|
65225 | points.emplace_back(std::move(polySegIntersection)); |
1084 | } | ||
1085 | |||
1086 | // add intersection points of all polygon faces (codim 1) with the polyhedron faces | ||
1087 |
4/4✓ Branch 0 taken 193990 times.
✓ Branch 1 taken 34631 times.
✓ Branch 2 taken 193990 times.
✓ Branch 3 taken 34631 times.
|
521515 | for (int i = 0; i < refElement1.size(1); ++i) |
1088 | { | ||
1089 |
2/6✓ Branch 1 taken 193990 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 193990 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
764562 | const auto faceGeo = [&]() |
1090 | { | ||
1091 | 581970 | const auto localFaceGeo = refElement1.template geometry<1>(i); | |
1092 |
4/4✓ Branch 0 taken 120750 times.
✓ Branch 1 taken 27592 times.
✓ Branch 2 taken 120750 times.
✓ Branch 3 taken 27592 times.
|
387980 | if (localFaceGeo.corners() == 4) |
1093 | { | ||
1094 | 332796 | const auto a = geo1.global(localFaceGeo.corner(0)); | |
1095 | 332796 | const auto b = geo1.global(localFaceGeo.corner(1)); | |
1096 | 332796 | const auto c = geo1.global(localFaceGeo.corner(2)); | |
1097 | 332796 | const auto d = geo1.global(localFaceGeo.corner(3)); | |
1098 | |||
1099 |
4/10✓ Branch 1 taken 120750 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 120750 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 120750 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 120750 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
831990 | return PolyhedronFaceGeometry(Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d}); |
1100 | } | ||
1101 | else | ||
1102 | { | ||
1103 | 55184 | const auto a = geo1.global(localFaceGeo.corner(0)); | |
1104 | 55184 | const auto b = geo1.global(localFaceGeo.corner(1)); | |
1105 | 55184 | const auto c = geo1.global(localFaceGeo.corner(2)); | |
1106 | |||
1107 |
4/10✓ Branch 1 taken 27592 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 27592 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 27592 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27592 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
137960 | return PolyhedronFaceGeometry(Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c}); |
1108 | } | ||
1109 |
2/2✓ Branch 0 taken 120750 times.
✓ Branch 1 taken 27592 times.
|
193990 | }(); |
1110 | |||
1111 |
4/4✓ Branch 0 taken 588834 times.
✓ Branch 1 taken 193990 times.
✓ Branch 2 taken 588834 times.
✓ Branch 3 taken 193990 times.
|
1693546 | for (int j = 0; j < refElement2.size(1); ++j) |
1112 | { | ||
1113 | 726954 | const auto localEdgeGeom = refElement2.template geometry<1>(j); | |
1114 | 726954 | const auto p = geo2.global(localEdgeGeom.corner(0)); | |
1115 | 726954 | const auto q = geo2.global(localEdgeGeom.corner(1)); | |
1116 | |||
1117 |
6/16✓ Branch 1 taken 588834 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 588834 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 588834 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 588834 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 588834 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 588834 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
4361724 | const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q}); |
1118 | |||
1119 | using PolySegTest = GeometryIntersection<PolyhedronFaceGeometry, SegGeometry, PointPolicy>; | ||
1120 | 726954 | typename PolySegTest::Intersection polySegIntersection; | |
1121 |
3/4✓ Branch 1 taken 588834 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 65786 times.
✓ Branch 4 taken 523048 times.
|
726954 | if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection)) |
1122 |
1/2✓ Branch 1 taken 65786 times.
✗ Branch 2 not taken.
|
71258 | points.emplace_back(std::move(polySegIntersection)); |
1123 | } | ||
1124 | } | ||
1125 | |||
1126 | // return if no intersection points were found | ||
1127 |
4/4✓ Branch 0 taken 19844 times.
✓ Branch 1 taken 14787 times.
✓ Branch 2 taken 19844 times.
✓ Branch 3 taken 14787 times.
|
84478 | if (points.empty()) return false; |
1128 | |||
1129 | // remove duplicates | ||
1130 | 58816 | const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_; | |
1131 | 1264318 | const auto notEqual = [eps] (auto a, auto b) { using std::abs; return abs(b-a) > eps; }; | |
1132 | 71196 | std::sort(points.begin(), points.end(), [notEqual](const auto& a, const auto& b) -> bool | |
1133 | { | ||
1134 |
160/384✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 74023 times.
✓ Branch 17 taken 122487 times.
✓ Branch 18 taken 74023 times.
✓ Branch 19 taken 122487 times.
✓ Branch 20 taken 74023 times.
✓ Branch 21 taken 122487 times.
✓ Branch 22 taken 74023 times.
✓ Branch 23 taken 122487 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✓ Branch 64 taken 368 times.
✓ Branch 65 taken 364 times.
✓ Branch 66 taken 368 times.
✓ Branch 67 taken 364 times.
✓ Branch 68 taken 368 times.
✓ Branch 69 taken 364 times.
✓ Branch 70 taken 368 times.
✓ Branch 71 taken 364 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✓ Branch 88 taken 33178 times.
✓ Branch 89 taken 69931 times.
✓ Branch 90 taken 33178 times.
✓ Branch 91 taken 69931 times.
✓ Branch 92 taken 33178 times.
✓ Branch 93 taken 69931 times.
✓ Branch 94 taken 33178 times.
✓ Branch 95 taken 69931 times.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✗ Branch 104 not taken.
✗ Branch 105 not taken.
✗ Branch 106 not taken.
✗ Branch 107 not taken.
✗ Branch 108 not taken.
✗ Branch 109 not taken.
✗ Branch 110 not taken.
✗ Branch 111 not taken.
✗ Branch 112 not taken.
✗ Branch 113 not taken.
✗ Branch 114 not taken.
✗ Branch 115 not taken.
✗ Branch 116 not taken.
✗ Branch 117 not taken.
✗ Branch 118 not taken.
✗ Branch 119 not taken.
✗ Branch 120 not taken.
✗ Branch 121 not taken.
✗ Branch 122 not taken.
✗ Branch 123 not taken.
✗ Branch 124 not taken.
✗ Branch 125 not taken.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✗ Branch 132 not taken.
✗ Branch 133 not taken.
✗ Branch 134 not taken.
✗ Branch 135 not taken.
✓ Branch 136 taken 720 times.
✓ Branch 137 taken 1774 times.
✓ Branch 138 taken 720 times.
✓ Branch 139 taken 1774 times.
✓ Branch 140 taken 720 times.
✓ Branch 141 taken 1774 times.
✓ Branch 142 taken 720 times.
✓ Branch 143 taken 1774 times.
✓ Branch 144 taken 78 times.
✓ Branch 145 taken 69 times.
✓ Branch 146 taken 78 times.
✓ Branch 147 taken 69 times.
✓ Branch 148 taken 78 times.
✓ Branch 149 taken 69 times.
✓ Branch 150 taken 78 times.
✓ Branch 151 taken 69 times.
✓ Branch 152 taken 35 times.
✓ Branch 153 taken 23 times.
✓ Branch 154 taken 35 times.
✓ Branch 155 taken 23 times.
✓ Branch 156 taken 35 times.
✓ Branch 157 taken 23 times.
✓ Branch 158 taken 35 times.
✓ Branch 159 taken 23 times.
✓ Branch 160 taken 1 times.
✓ Branch 161 taken 9 times.
✓ Branch 162 taken 1 times.
✓ Branch 163 taken 9 times.
✓ Branch 164 taken 1 times.
✓ Branch 165 taken 9 times.
✓ Branch 166 taken 1 times.
✓ Branch 167 taken 9 times.
✓ Branch 168 taken 4 times.
✓ Branch 169 taken 4 times.
✓ Branch 170 taken 4 times.
✓ Branch 171 taken 4 times.
✓ Branch 172 taken 4 times.
✓ Branch 173 taken 4 times.
✓ Branch 174 taken 4 times.
✓ Branch 175 taken 4 times.
✓ Branch 176 taken 4 times.
✓ Branch 177 taken 2 times.
✓ Branch 178 taken 4 times.
✓ Branch 179 taken 2 times.
✓ Branch 180 taken 4 times.
✓ Branch 181 taken 2 times.
✓ Branch 182 taken 4 times.
✓ Branch 183 taken 2 times.
✓ Branch 184 taken 1 times.
✓ Branch 185 taken 1 times.
✓ Branch 186 taken 1 times.
✓ Branch 187 taken 1 times.
✓ Branch 188 taken 1 times.
✓ Branch 189 taken 1 times.
✓ Branch 190 taken 1 times.
✓ Branch 191 taken 1 times.
✓ Branch 192 taken 1 times.
✗ Branch 193 not taken.
✓ Branch 194 taken 1 times.
✗ Branch 195 not taken.
✓ Branch 196 taken 1 times.
✗ Branch 197 not taken.
✓ Branch 198 taken 1 times.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 204 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 207 not taken.
✓ Branch 208 taken 18140 times.
✓ Branch 209 taken 21376 times.
✓ Branch 210 taken 18140 times.
✓ Branch 211 taken 21376 times.
✓ Branch 212 taken 18140 times.
✓ Branch 213 taken 21376 times.
✓ Branch 214 taken 18140 times.
✓ Branch 215 taken 21376 times.
✗ Branch 216 not taken.
✗ Branch 217 not taken.
✗ Branch 218 not taken.
✗ Branch 219 not taken.
✗ Branch 220 not taken.
✗ Branch 221 not taken.
✗ Branch 222 not taken.
✗ Branch 223 not taken.
✗ Branch 224 not taken.
✗ Branch 225 not taken.
✗ Branch 226 not taken.
✗ Branch 227 not taken.
✗ Branch 228 not taken.
✗ Branch 229 not taken.
✗ Branch 230 not taken.
✗ Branch 231 not taken.
✗ Branch 232 not taken.
✗ Branch 233 not taken.
✗ Branch 234 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 240 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 243 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✗ Branch 246 not taken.
✗ Branch 247 not taken.
✗ Branch 248 not taken.
✗ Branch 249 not taken.
✗ Branch 250 not taken.
✗ Branch 251 not taken.
✗ Branch 252 not taken.
✗ Branch 253 not taken.
✗ Branch 254 not taken.
✗ Branch 255 not taken.
✗ Branch 256 not taken.
✗ Branch 257 not taken.
✗ Branch 258 not taken.
✗ Branch 259 not taken.
✗ Branch 260 not taken.
✗ Branch 261 not taken.
✗ Branch 262 not taken.
✗ Branch 263 not taken.
✗ Branch 264 not taken.
✗ Branch 265 not taken.
✗ Branch 266 not taken.
✗ Branch 267 not taken.
✗ Branch 268 not taken.
✗ Branch 269 not taken.
✗ Branch 270 not taken.
✗ Branch 271 not taken.
✗ Branch 272 not taken.
✗ Branch 273 not taken.
✗ Branch 274 not taken.
✗ Branch 275 not taken.
✗ Branch 276 not taken.
✗ Branch 277 not taken.
✗ Branch 278 not taken.
✗ Branch 279 not taken.
✓ Branch 280 taken 6399 times.
✓ Branch 281 taken 7477 times.
✓ Branch 282 taken 6399 times.
✓ Branch 283 taken 7477 times.
✓ Branch 284 taken 6399 times.
✓ Branch 285 taken 7477 times.
✓ Branch 286 taken 6399 times.
✓ Branch 287 taken 7477 times.
✓ Branch 288 taken 19 times.
✓ Branch 289 taken 32 times.
✓ Branch 290 taken 19 times.
✓ Branch 291 taken 32 times.
✓ Branch 292 taken 19 times.
✓ Branch 293 taken 32 times.
✓ Branch 294 taken 19 times.
✓ Branch 295 taken 32 times.
✓ Branch 296 taken 1 times.
✓ Branch 297 taken 28 times.
✓ Branch 298 taken 1 times.
✓ Branch 299 taken 28 times.
✓ Branch 300 taken 1 times.
✓ Branch 301 taken 28 times.
✓ Branch 302 taken 1 times.
✓ Branch 303 taken 28 times.
✗ Branch 304 not taken.
✓ Branch 305 taken 4 times.
✗ Branch 306 not taken.
✓ Branch 307 taken 4 times.
✗ Branch 308 not taken.
✓ Branch 309 taken 4 times.
✗ Branch 310 not taken.
✓ Branch 311 taken 4 times.
✗ Branch 312 not taken.
✗ Branch 313 not taken.
✗ Branch 314 not taken.
✗ Branch 315 not taken.
✗ Branch 316 not taken.
✗ Branch 317 not taken.
✗ Branch 318 not taken.
✗ Branch 319 not taken.
✗ Branch 320 not taken.
✗ Branch 321 not taken.
✗ Branch 322 not taken.
✗ Branch 323 not taken.
✗ Branch 324 not taken.
✗ Branch 325 not taken.
✗ Branch 326 not taken.
✗ Branch 327 not taken.
✗ Branch 328 not taken.
✓ Branch 329 taken 4 times.
✗ Branch 330 not taken.
✓ Branch 331 taken 4 times.
✗ Branch 332 not taken.
✓ Branch 333 taken 4 times.
✗ Branch 334 not taken.
✓ Branch 335 taken 4 times.
✗ Branch 336 not taken.
✓ Branch 337 taken 4 times.
✗ Branch 338 not taken.
✓ Branch 339 taken 4 times.
✗ Branch 340 not taken.
✓ Branch 341 taken 4 times.
✗ Branch 342 not taken.
✓ Branch 343 taken 4 times.
✗ Branch 344 not taken.
✗ Branch 345 not taken.
✗ Branch 346 not taken.
✗ Branch 347 not taken.
✗ Branch 348 not taken.
✗ Branch 349 not taken.
✗ Branch 350 not taken.
✗ Branch 351 not taken.
✓ Branch 352 taken 372 times.
✓ Branch 353 taken 216 times.
✓ Branch 354 taken 372 times.
✓ Branch 355 taken 216 times.
✓ Branch 356 taken 372 times.
✓ Branch 357 taken 216 times.
✓ Branch 358 taken 372 times.
✓ Branch 359 taken 216 times.
✓ Branch 360 taken 206 times.
✓ Branch 361 taken 866 times.
✓ Branch 362 taken 206 times.
✓ Branch 363 taken 866 times.
✓ Branch 364 taken 206 times.
✓ Branch 365 taken 866 times.
✓ Branch 366 taken 206 times.
✓ Branch 367 taken 866 times.
✓ Branch 368 taken 9500 times.
✓ Branch 369 taken 8172 times.
✓ Branch 370 taken 9500 times.
✓ Branch 371 taken 8172 times.
✓ Branch 372 taken 9500 times.
✓ Branch 373 taken 8172 times.
✓ Branch 374 taken 9500 times.
✓ Branch 375 taken 8172 times.
✓ Branch 376 taken 3035 times.
✓ Branch 377 taken 4261 times.
✓ Branch 378 taken 3035 times.
✓ Branch 379 taken 4261 times.
✓ Branch 380 taken 3035 times.
✓ Branch 381 taken 4261 times.
✓ Branch 382 taken 3035 times.
✓ Branch 383 taken 4261 times.
|
1532756 | return (notEqual(a[0], b[0]) ? a[0] < b[0] |
1135 |
87/288✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 13759 times.
✓ Branch 13 taken 108728 times.
✓ Branch 14 taken 13759 times.
✓ Branch 15 taken 108728 times.
✓ Branch 16 taken 13759 times.
✓ Branch 17 taken 108728 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 364 times.
✗ Branch 49 not taken.
✓ Branch 50 taken 364 times.
✗ Branch 51 not taken.
✓ Branch 52 taken 364 times.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✓ Branch 66 taken 10648 times.
✓ Branch 67 taken 59283 times.
✓ Branch 68 taken 10648 times.
✓ Branch 69 taken 59283 times.
✓ Branch 70 taken 10648 times.
✓ Branch 71 taken 59283 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✗ Branch 83 not taken.
✗ Branch 84 not taken.
✗ Branch 85 not taken.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✗ Branch 88 not taken.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✗ Branch 91 not taken.
✗ Branch 92 not taken.
✗ Branch 93 not taken.
✗ Branch 94 not taken.
✗ Branch 95 not taken.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✓ Branch 103 taken 1774 times.
✗ Branch 104 not taken.
✓ Branch 105 taken 1774 times.
✗ Branch 106 not taken.
✓ Branch 107 taken 1774 times.
✗ Branch 108 not taken.
✓ Branch 109 taken 69 times.
✗ Branch 110 not taken.
✓ Branch 111 taken 69 times.
✗ Branch 112 not taken.
✓ Branch 113 taken 69 times.
✗ Branch 114 not taken.
✓ Branch 115 taken 23 times.
✗ Branch 116 not taken.
✓ Branch 117 taken 23 times.
✗ Branch 118 not taken.
✓ Branch 119 taken 23 times.
✗ Branch 120 not taken.
✓ Branch 121 taken 9 times.
✗ Branch 122 not taken.
✓ Branch 123 taken 9 times.
✗ Branch 124 not taken.
✓ Branch 125 taken 9 times.
✗ Branch 126 not taken.
✓ Branch 127 taken 4 times.
✗ Branch 128 not taken.
✓ Branch 129 taken 4 times.
✗ Branch 130 not taken.
✓ Branch 131 taken 4 times.
✗ Branch 132 not taken.
✓ Branch 133 taken 2 times.
✗ Branch 134 not taken.
✓ Branch 135 taken 2 times.
✗ Branch 136 not taken.
✓ Branch 137 taken 2 times.
✗ Branch 138 not taken.
✓ Branch 139 taken 1 times.
✗ Branch 140 not taken.
✓ Branch 141 taken 1 times.
✗ Branch 142 not taken.
✓ Branch 143 taken 1 times.
✗ Branch 144 not taken.
✗ Branch 145 not taken.
✗ Branch 146 not taken.
✗ Branch 147 not taken.
✗ Branch 148 not taken.
✗ Branch 149 not taken.
✗ Branch 150 not taken.
✗ Branch 151 not taken.
✗ Branch 152 not taken.
✗ Branch 153 not taken.
✗ Branch 154 not taken.
✗ Branch 155 not taken.
✓ Branch 156 taken 10304 times.
✓ Branch 157 taken 11072 times.
✓ Branch 158 taken 10304 times.
✓ Branch 159 taken 11072 times.
✓ Branch 160 taken 10304 times.
✓ Branch 161 taken 11072 times.
✗ Branch 162 not taken.
✗ Branch 163 not taken.
✗ Branch 164 not taken.
✗ Branch 165 not taken.
✗ Branch 166 not taken.
✗ Branch 167 not taken.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✗ Branch 176 not taken.
✗ Branch 177 not taken.
✗ Branch 178 not taken.
✗ Branch 179 not taken.
✗ Branch 180 not taken.
✗ Branch 181 not taken.
✗ Branch 182 not taken.
✗ Branch 183 not taken.
✗ Branch 184 not taken.
✗ Branch 185 not taken.
✗ Branch 186 not taken.
✗ Branch 187 not taken.
✗ Branch 188 not taken.
✗ Branch 189 not taken.
✗ Branch 190 not taken.
✗ Branch 191 not taken.
✗ Branch 192 not taken.
✗ Branch 193 not taken.
✗ Branch 194 not taken.
✗ Branch 195 not taken.
✗ Branch 196 not taken.
✗ Branch 197 not taken.
✗ Branch 198 not taken.
✗ Branch 199 not taken.
✗ Branch 200 not taken.
✗ Branch 201 not taken.
✗ Branch 202 not taken.
✗ Branch 203 not taken.
✗ Branch 204 not taken.
✗ Branch 205 not taken.
✗ Branch 206 not taken.
✗ Branch 207 not taken.
✗ Branch 208 not taken.
✗ Branch 209 not taken.
✓ Branch 210 taken 1861 times.
✓ Branch 211 taken 5616 times.
✓ Branch 212 taken 1861 times.
✓ Branch 213 taken 5616 times.
✓ Branch 214 taken 1861 times.
✓ Branch 215 taken 5616 times.
✓ Branch 216 taken 23 times.
✓ Branch 217 taken 9 times.
✓ Branch 218 taken 23 times.
✓ Branch 219 taken 9 times.
✓ Branch 220 taken 23 times.
✓ Branch 221 taken 9 times.
✓ Branch 222 taken 21 times.
✓ Branch 223 taken 7 times.
✓ Branch 224 taken 21 times.
✓ Branch 225 taken 7 times.
✓ Branch 226 taken 21 times.
✓ Branch 227 taken 7 times.
✗ Branch 228 not taken.
✓ Branch 229 taken 4 times.
✗ Branch 230 not taken.
✓ Branch 231 taken 4 times.
✗ Branch 232 not taken.
✓ Branch 233 taken 4 times.
✗ Branch 234 not taken.
✗ Branch 235 not taken.
✗ Branch 236 not taken.
✗ Branch 237 not taken.
✗ Branch 238 not taken.
✗ Branch 239 not taken.
✗ Branch 240 not taken.
✗ Branch 241 not taken.
✗ Branch 242 not taken.
✗ Branch 243 not taken.
✗ Branch 244 not taken.
✗ Branch 245 not taken.
✗ Branch 246 not taken.
✓ Branch 247 taken 4 times.
✗ Branch 248 not taken.
✓ Branch 249 taken 4 times.
✗ Branch 250 not taken.
✓ Branch 251 taken 4 times.
✗ Branch 252 not taken.
✓ Branch 253 taken 4 times.
✗ Branch 254 not taken.
✓ Branch 255 taken 4 times.
✗ Branch 256 not taken.
✓ Branch 257 taken 4 times.
✗ Branch 258 not taken.
✗ Branch 259 not taken.
✗ Branch 260 not taken.
✗ Branch 261 not taken.
✗ Branch 262 not taken.
✗ Branch 263 not taken.
✓ Branch 264 taken 216 times.
✗ Branch 265 not taken.
✓ Branch 266 taken 216 times.
✗ Branch 267 not taken.
✓ Branch 268 taken 216 times.
✗ Branch 269 not taken.
✗ Branch 270 not taken.
✓ Branch 271 taken 866 times.
✗ Branch 272 not taken.
✓ Branch 273 taken 866 times.
✗ Branch 274 not taken.
✓ Branch 275 taken 866 times.
✓ Branch 276 taken 4756 times.
✓ Branch 277 taken 3416 times.
✓ Branch 278 taken 4756 times.
✓ Branch 279 taken 3416 times.
✓ Branch 280 taken 4756 times.
✓ Branch 281 taken 3416 times.
✓ Branch 282 taken 818 times.
✓ Branch 283 taken 3443 times.
✓ Branch 284 taken 818 times.
✓ Branch 285 taken 3443 times.
✓ Branch 286 taken 818 times.
✓ Branch 287 taken 3443 times.
|
711312 | : (notEqual(a[1], b[1]) ? a[1] < b[1] |
1136 |
29/96✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 13759 times.
✓ Branch 5 taken 108728 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 364 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✓ Branch 22 taken 10648 times.
✓ Branch 23 taken 59283 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✓ Branch 35 taken 1774 times.
✗ Branch 36 not taken.
✓ Branch 37 taken 69 times.
✗ Branch 38 not taken.
✓ Branch 39 taken 23 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 9 times.
✗ Branch 42 not taken.
✓ Branch 43 taken 4 times.
✗ Branch 44 not taken.
✓ Branch 45 taken 2 times.
✗ Branch 46 not taken.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✓ Branch 52 taken 10304 times.
✓ Branch 53 taken 11072 times.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 1861 times.
✓ Branch 71 taken 5616 times.
✓ Branch 72 taken 23 times.
✓ Branch 73 taken 9 times.
✓ Branch 74 taken 21 times.
✓ Branch 75 taken 7 times.
✗ Branch 76 not taken.
✓ Branch 77 taken 4 times.
✗ Branch 78 not taken.
✗ Branch 79 not taken.
✗ Branch 80 not taken.
✗ Branch 81 not taken.
✗ Branch 82 not taken.
✓ Branch 83 taken 4 times.
✗ Branch 84 not taken.
✓ Branch 85 taken 4 times.
✗ Branch 86 not taken.
✗ Branch 87 not taken.
✓ Branch 88 taken 216 times.
✗ Branch 89 not taken.
✗ Branch 90 not taken.
✓ Branch 91 taken 866 times.
✓ Branch 92 taken 4756 times.
✓ Branch 93 taken 3416 times.
✓ Branch 94 taken 818 times.
✓ Branch 95 taken 3443 times.
|
237104 | : (a[2] < b[2]))); |
1137 | }); | ||
1138 | |||
1139 | 23732 | const auto squaredEps = eps*eps; | |
1140 | 145332 | points.erase(std::unique( | |
1141 | points.begin(), points.end(), | ||
1142 | 232890 | [squaredEps] (const auto& a, const auto&b) { return (b-a).two_norm2() < squaredEps; }), | |
1143 | points.end() | ||
1144 | ); | ||
1145 | |||
1146 | // return false if we don't have more than three unique points | ||
1147 |
4/4✓ Branch 0 taken 13016 times.
✓ Branch 1 taken 6828 times.
✓ Branch 2 taken 13016 times.
✓ Branch 3 taken 6828 times.
|
47464 | if (points.size() < 3) return false; |
1148 | |||
1149 | // intersection polygon is convex hull of above points | ||
1150 |
2/4✓ Branch 1 taken 13016 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13016 times.
|
15932 | intersection = grahamConvexHull<2>(points); |
1151 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 13016 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13016 times.
|
31864 | assert(!intersection.empty()); |
1152 | |||
1153 | return true; | ||
1154 | } | ||
1155 | |||
1156 | /*! | ||
1157 | * \brief Colliding segment and convex polyhedron | ||
1158 | * \note First we find the vertex candidates for the intersection region as follows: | ||
1159 | * Add triangle vertices that are inside the tetrahedron | ||
1160 | * Add tetrahedron vertices that are inside the triangle | ||
1161 | * Add all intersection points of tetrahedron edges (codim 2) with the triangle (codim 0) (6*1 tests) | ||
1162 | * Add all intersection points of triangle edges (codim 1) with tetrahedron faces (codim 1) (3*4 tests) | ||
1163 | * Remove duplicate points from the list | ||
1164 | * Compute the convex hull polygon | ||
1165 | * Return a triangulation of that polygon as intersection | ||
1166 | * \param geo1/geo2 The geometries to intersect | ||
1167 | * \param intersection Container to store the intersection result | ||
1168 | * \todo implement overloads for segment or point-like intersections | ||
1169 | */ | ||
1170 | template<class P = Policy, std::enable_if_t<P::dimIntersection != 2, int> = 0> | ||
1171 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
1172 | { | ||
1173 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1174 | DUNE_THROW(Dune::NotImplemented, "Polyhedron-polygon intersection detection only implemented for polygon-like intersections"); | ||
1175 | } | ||
1176 | }; | ||
1177 | |||
1178 | /*! | ||
1179 | * \ingroup Geometry | ||
1180 | * \brief A class for polygon--polyhedron intersection in 3d space | ||
1181 | */ | ||
1182 | template <class Geometry1, class Geometry2, class Policy> | ||
1183 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 2, 3> | ||
1184 | : public GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 2> | ||
1185 | { | ||
1186 | using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 2>; | ||
1187 | public: | ||
1188 | /*! | ||
1189 | * \brief Colliding polygon and convex polyhedron | ||
1190 | * \param geo1/geo2 The geometries to intersect | ||
1191 | * \param intersection If the geometries collide intersection holds the | ||
1192 | * corner points of the intersection object in global coordinates. | ||
1193 | * \note This forwards to the polyhedron-polygon specialization with swapped arguments. | ||
1194 | */ | ||
1195 | template<class P = Policy> | ||
1196 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection) | ||
1197 | { | ||
1198 |
3/6✓ Branch 1 taken 196 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 256 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4356 times.
✗ Branch 8 not taken.
|
4808 | return Base::intersection(geo2, geo1, intersection); |
1199 | } | ||
1200 | }; | ||
1201 | |||
1202 | /*! | ||
1203 | * \ingroup Geometry | ||
1204 | * \brief A class for polyhedron--polyhedron intersection in 3d space | ||
1205 | */ | ||
1206 | template <class Geometry1, class Geometry2, class Policy> | ||
1207 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 3, 3> | ||
1208 | { | ||
1209 | enum { dimworld = 3 }; | ||
1210 | enum { dim1 = 3 }; | ||
1211 | enum { dim2 = 3 }; | ||
1212 | |||
1213 | public: | ||
1214 | using ctype = typename Policy::ctype; | ||
1215 | using Point = typename Policy::Point; | ||
1216 | using Intersection = typename Policy::Intersection; | ||
1217 | |||
1218 | private: | ||
1219 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
1220 | |||
1221 | public: | ||
1222 | /*! | ||
1223 | * \brief Colliding two convex polyhedra | ||
1224 | * \note First we find the vertex candidates for the intersection region as follows: | ||
1225 | * Add vertices that are inside the other geometry for both geometries | ||
1226 | * Add all intersection points of edges (codim 2) with the other tetrahedron's faces triangle | ||
1227 | * Remove duplicate points from the list | ||
1228 | * Return a triangulation of the polyhedron formed by the convex hull of the point cloud | ||
1229 | * \param geo1/geo2 The geometries to intersect | ||
1230 | * \param intersection Container to store the corner points of the polygon (as convex hull) | ||
1231 | * \note This overload is used when polyhedron-like intersections are seeked | ||
1232 | */ | ||
1233 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 3, int> = 0> | ||
1234 | 12782 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
1235 | { | ||
1236 | static_assert( | ||
1237 | int(dimworld) == int(Geometry2::coorddimension), | ||
1238 | "Can only collide geometries of same coordinate dimension" | ||
1239 | ); | ||
1240 | |||
1241 |
1/2✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
|
12782 | const auto refElement1 = referenceElement(geo1); |
1242 |
1/2✓ Branch 1 taken 124 times.
✗ Branch 2 not taken.
|
12782 | const auto refElement2 = referenceElement(geo2); |
1243 | |||
1244 | // the candidate intersection points | ||
1245 |
2/6✓ Branch 1 taken 6453 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6453 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
38346 | std::vector<Point> points; |
1246 |
3/6✓ Branch 1 taken 6453 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6453 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6453 times.
✗ Branch 8 not taken.
|
38346 | points.reserve(refElement1.size(2) + refElement2.size(2)); |
1247 | |||
1248 | // add corners inside the other geometry | ||
1249 | 25936 | const auto addPointIntersections = [&](const auto& g1, const auto& g2) | |
1250 | { | ||
1251 |
12/24✓ Branch 0 taken 5448 times.
✓ Branch 1 taken 681 times.
✓ Branch 2 taken 5448 times.
✓ Branch 3 taken 681 times.
✓ Branch 4 taken 1732 times.
✓ Branch 5 taken 433 times.
✓ Branch 6 taken 1732 times.
✓ Branch 7 taken 433 times.
✓ Branch 8 taken 94336 times.
✓ Branch 9 taken 11792 times.
✓ Branch 10 taken 94336 times.
✓ Branch 11 taken 11792 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
|
127328 | for (int i = 0; i < g1.corners(); ++i) |
1252 |
7/14✓ Branch 1 taken 106 times.
✓ Branch 2 taken 4010 times.
✓ Branch 3 taken 1332 times.
✓ Branch 5 taken 762 times.
✓ Branch 6 taken 970 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 28008 times.
✓ Branch 9 taken 66328 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
199316 | if (const auto& c = g1.corner(i); intersectsPointGeometry(c, g2)) |
1253 |
0/8✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
29528 | points.emplace_back(c); |
1254 | }; | ||
1255 | |||
1256 |
1/2✓ Branch 1 taken 6453 times.
✗ Branch 2 not taken.
|
12782 | addPointIntersections(geo1, geo2); |
1257 |
1/2✓ Branch 1 taken 6453 times.
✗ Branch 2 not taken.
|
12782 | addPointIntersections(geo2, geo1); |
1258 | |||
1259 | // get geometry types for the facets | ||
1260 | using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>; | ||
1261 | using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>; | ||
1262 | |||
1263 | // intersection policy for point-like intersections (used later) | ||
1264 | using PointPolicy = IntersectionPolicy::PointPolicy<ctype, dimworld>; | ||
1265 | |||
1266 | // add intersection points of all edges with the faces of the other polyhedron | ||
1267 | 25564 | const auto addEdgeIntersections = [&](const auto& g1, const auto& g2, const auto& ref1, const auto& ref2) | |
1268 | { | ||
1269 |
12/12✓ Branch 0 taken 4086 times.
✓ Branch 1 taken 681 times.
✓ Branch 2 taken 4086 times.
✓ Branch 3 taken 681 times.
✓ Branch 4 taken 1732 times.
✓ Branch 5 taken 433 times.
✓ Branch 6 taken 1732 times.
✓ Branch 7 taken 433 times.
✓ Branch 8 taken 70752 times.
✓ Branch 9 taken 11792 times.
✓ Branch 10 taken 70752 times.
✓ Branch 11 taken 11792 times.
|
166046 | for (int i = 0; i < ref1.size(1); ++i) |
1270 | { | ||
1271 |
6/12✓ Branch 1 taken 4086 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2598 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1732 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1732 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 70752 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 70752 times.
✗ Branch 14 not taken.
|
304792 | const auto faceGeo = [&]() |
1272 | { | ||
1273 | 229710 | const auto localFaceGeo = ref1.template geometry<1>(i); | |
1274 |
2/4✓ Branch 0 taken 1488 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1488 times.
✗ Branch 3 not taken.
|
153140 | if (localFaceGeo.corners() == 4) |
1275 | { | ||
1276 | 149676 | const auto a = g1.global(localFaceGeo.corner(0)); | |
1277 | 149676 | const auto b = g1.global(localFaceGeo.corner(1)); | |
1278 | 149676 | const auto c = g1.global(localFaceGeo.corner(2)); | |
1279 | 149676 | const auto d = g1.global(localFaceGeo.corner(3)); | |
1280 | |||
1281 | return PolyhedronFaceGeometry( | ||
1282 | Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d} | ||
1283 |
4/10✓ Branch 1 taken 1488 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1488 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1488 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1488 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
374190 | ); |
1284 | } | ||
1285 | else | ||
1286 | { | ||
1287 | 3464 | const auto a = g1.global(localFaceGeo.corner(0)); | |
1288 | 3464 | const auto b = g1.global(localFaceGeo.corner(1)); | |
1289 | 3464 | const auto c = g1.global(localFaceGeo.corner(2)); | |
1290 | |||
1291 | return PolyhedronFaceGeometry( | ||
1292 | Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c} | ||
1293 |
0/10✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
8660 | ); |
1294 | } | ||
1295 |
1/2✓ Branch 0 taken 1488 times.
✗ Branch 1 not taken.
|
76570 | }(); |
1296 | |||
1297 |
12/12✓ Branch 0 taken 33444 times.
✓ Branch 1 taken 4086 times.
✓ Branch 2 taken 33444 times.
✓ Branch 3 taken 4086 times.
✓ Branch 4 taken 20784 times.
✓ Branch 5 taken 1732 times.
✓ Branch 6 taken 20784 times.
✓ Branch 7 taken 1732 times.
✓ Branch 8 taken 849024 times.
✓ Branch 9 taken 70752 times.
✓ Branch 10 taken 849024 times.
✓ Branch 11 taken 70752 times.
|
1883074 | for (int j = 0; j < ref2.size(2); ++j) |
1298 | { | ||
1299 | 903252 | const auto localEdgeGeom = ref2.template geometry<2>(j); | |
1300 | 1806504 | const auto p = g2.global(localEdgeGeom.corner(0)); | |
1301 | 1806504 | const auto q = g2.global(localEdgeGeom.corner(1)); | |
1302 | |||
1303 |
18/48✓ Branch 1 taken 33444 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 33444 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 33444 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 33444 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 33444 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 33444 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✓ Branch 21 taken 20784 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 20784 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 20784 times.
✗ Branch 28 not taken.
✓ Branch 29 taken 20784 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 20784 times.
✗ Branch 33 not taken.
✓ Branch 34 taken 20784 times.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 41 taken 849024 times.
✗ Branch 42 not taken.
✓ Branch 44 taken 849024 times.
✗ Branch 45 not taken.
✓ Branch 47 taken 849024 times.
✗ Branch 48 not taken.
✓ Branch 49 taken 849024 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 849024 times.
✗ Branch 53 not taken.
✓ Branch 54 taken 849024 times.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
|
5419512 | const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q}); |
1304 | |||
1305 | using PolySegTest = GeometryIntersection<PolyhedronFaceGeometry, SegGeometry, PointPolicy>; | ||
1306 | 903252 | typename PolySegTest::Intersection polySegIntersection; | |
1307 |
9/12✓ Branch 1 taken 33444 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5797 times.
✓ Branch 4 taken 27647 times.
✓ Branch 6 taken 20784 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1234 times.
✓ Branch 9 taken 19550 times.
✓ Branch 11 taken 849024 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 109584 times.
✓ Branch 14 taken 739440 times.
|
903252 | if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection)) |
1308 |
3/6✓ Branch 1 taken 5797 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1234 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 109584 times.
✗ Branch 8 not taken.
|
116615 | points.emplace_back(std::move(polySegIntersection)); |
1309 | } | ||
1310 | } | ||
1311 | }; | ||
1312 | |||
1313 |
1/2✓ Branch 1 taken 6453 times.
✗ Branch 2 not taken.
|
12782 | addEdgeIntersections(geo1, geo2, refElement1, refElement2); |
1314 |
1/2✓ Branch 1 taken 6453 times.
✗ Branch 2 not taken.
|
12782 | addEdgeIntersections(geo2, geo1, refElement2, refElement1); |
1315 | |||
1316 | // return if no intersection points were found | ||
1317 |
4/4✓ Branch 0 taken 6407 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 6407 times.
✓ Branch 3 taken 46 times.
|
25564 | if (points.empty()) |
1318 | return false; | ||
1319 | |||
1320 | // remove duplicates | ||
1321 | 36274 | const auto norm = (geo1.corner(0) - geo1.corner(1)).two_norm(); | |
1322 | 12690 | const auto eps = norm*eps_; | |
1323 | 2239566 | const auto notEqual = [eps] (auto a, auto b) { using std::abs; return abs(b-a) > eps; }; | |
1324 | 38070 | std::sort(points.begin(), points.end(), [notEqual](const auto& a, const auto& b) -> bool | |
1325 | { | ||
1326 |
160/192✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 2280 times.
✓ Branch 17 taken 8243 times.
✓ Branch 18 taken 2280 times.
✓ Branch 19 taken 8243 times.
✓ Branch 20 taken 2280 times.
✓ Branch 21 taken 8243 times.
✓ Branch 22 taken 2280 times.
✓ Branch 23 taken 8243 times.
✓ Branch 24 taken 1945 times.
✓ Branch 25 taken 3041 times.
✓ Branch 26 taken 1945 times.
✓ Branch 27 taken 3041 times.
✓ Branch 28 taken 1945 times.
✓ Branch 29 taken 3041 times.
✓ Branch 30 taken 1945 times.
✓ Branch 31 taken 3041 times.
✓ Branch 32 taken 3927 times.
✓ Branch 33 taken 8929 times.
✓ Branch 34 taken 3927 times.
✓ Branch 35 taken 8929 times.
✓ Branch 36 taken 3927 times.
✓ Branch 37 taken 8929 times.
✓ Branch 38 taken 3927 times.
✓ Branch 39 taken 8929 times.
✓ Branch 40 taken 224 times.
✓ Branch 41 taken 1161 times.
✓ Branch 42 taken 224 times.
✓ Branch 43 taken 1161 times.
✓ Branch 44 taken 224 times.
✓ Branch 45 taken 1161 times.
✓ Branch 46 taken 224 times.
✓ Branch 47 taken 1161 times.
✓ Branch 48 taken 122 times.
✓ Branch 49 taken 1107 times.
✓ Branch 50 taken 122 times.
✓ Branch 51 taken 1107 times.
✓ Branch 52 taken 122 times.
✓ Branch 53 taken 1107 times.
✓ Branch 54 taken 122 times.
✓ Branch 55 taken 1107 times.
✓ Branch 56 taken 25 times.
✓ Branch 57 taken 126 times.
✓ Branch 58 taken 25 times.
✓ Branch 59 taken 126 times.
✓ Branch 60 taken 25 times.
✓ Branch 61 taken 126 times.
✓ Branch 62 taken 25 times.
✓ Branch 63 taken 126 times.
✓ Branch 64 taken 55 times.
✓ Branch 65 taken 155 times.
✓ Branch 66 taken 55 times.
✓ Branch 67 taken 155 times.
✓ Branch 68 taken 55 times.
✓ Branch 69 taken 155 times.
✓ Branch 70 taken 55 times.
✓ Branch 71 taken 155 times.
✓ Branch 72 taken 22 times.
✓ Branch 73 taken 108 times.
✓ Branch 74 taken 22 times.
✓ Branch 75 taken 108 times.
✓ Branch 76 taken 22 times.
✓ Branch 77 taken 108 times.
✓ Branch 78 taken 22 times.
✓ Branch 79 taken 108 times.
✓ Branch 80 taken 16 times.
✓ Branch 81 taken 80 times.
✓ Branch 82 taken 16 times.
✓ Branch 83 taken 80 times.
✓ Branch 84 taken 16 times.
✓ Branch 85 taken 80 times.
✓ Branch 86 taken 16 times.
✓ Branch 87 taken 80 times.
✓ Branch 88 taken 475 times.
✓ Branch 89 taken 1183 times.
✓ Branch 90 taken 475 times.
✓ Branch 91 taken 1183 times.
✓ Branch 92 taken 475 times.
✓ Branch 93 taken 1183 times.
✓ Branch 94 taken 475 times.
✓ Branch 95 taken 1183 times.
✗ Branch 96 not taken.
✗ Branch 97 not taken.
✗ Branch 98 not taken.
✗ Branch 99 not taken.
✗ Branch 100 not taken.
✗ Branch 101 not taken.
✗ Branch 102 not taken.
✗ Branch 103 not taken.
✓ Branch 104 taken 73198 times.
✓ Branch 105 taken 224692 times.
✓ Branch 106 taken 73198 times.
✓ Branch 107 taken 224692 times.
✓ Branch 108 taken 73198 times.
✓ Branch 109 taken 224692 times.
✓ Branch 110 taken 73198 times.
✓ Branch 111 taken 224692 times.
✓ Branch 112 taken 20280 times.
✓ Branch 113 taken 69291 times.
✓ Branch 114 taken 20280 times.
✓ Branch 115 taken 69291 times.
✓ Branch 116 taken 20280 times.
✓ Branch 117 taken 69291 times.
✓ Branch 118 taken 20280 times.
✓ Branch 119 taken 69291 times.
✓ Branch 120 taken 30500 times.
✓ Branch 121 taken 71604 times.
✓ Branch 122 taken 30500 times.
✓ Branch 123 taken 71604 times.
✓ Branch 124 taken 30500 times.
✓ Branch 125 taken 71604 times.
✓ Branch 126 taken 30500 times.
✓ Branch 127 taken 71604 times.
✓ Branch 128 taken 3065 times.
✓ Branch 129 taken 5142 times.
✓ Branch 130 taken 3065 times.
✓ Branch 131 taken 5142 times.
✓ Branch 132 taken 3065 times.
✓ Branch 133 taken 5142 times.
✓ Branch 134 taken 3065 times.
✓ Branch 135 taken 5142 times.
✓ Branch 136 taken 1745 times.
✓ Branch 137 taken 4305 times.
✓ Branch 138 taken 1745 times.
✓ Branch 139 taken 4305 times.
✓ Branch 140 taken 1745 times.
✓ Branch 141 taken 4305 times.
✓ Branch 142 taken 1745 times.
✓ Branch 143 taken 4305 times.
✓ Branch 144 taken 1570 times.
✓ Branch 145 taken 3730 times.
✓ Branch 146 taken 1570 times.
✓ Branch 147 taken 3730 times.
✓ Branch 148 taken 1570 times.
✓ Branch 149 taken 3730 times.
✓ Branch 150 taken 1570 times.
✓ Branch 151 taken 3730 times.
✓ Branch 152 taken 625 times.
✓ Branch 153 taken 1532 times.
✓ Branch 154 taken 625 times.
✓ Branch 155 taken 1532 times.
✓ Branch 156 taken 625 times.
✓ Branch 157 taken 1532 times.
✓ Branch 158 taken 625 times.
✓ Branch 159 taken 1532 times.
✓ Branch 160 taken 125 times.
✓ Branch 161 taken 637 times.
✓ Branch 162 taken 125 times.
✓ Branch 163 taken 637 times.
✓ Branch 164 taken 125 times.
✓ Branch 165 taken 637 times.
✓ Branch 166 taken 125 times.
✓ Branch 167 taken 637 times.
✗ Branch 168 not taken.
✗ Branch 169 not taken.
✗ Branch 170 not taken.
✗ Branch 171 not taken.
✗ Branch 172 not taken.
✗ Branch 173 not taken.
✗ Branch 174 not taken.
✗ Branch 175 not taken.
✓ Branch 176 taken 1398 times.
✓ Branch 177 taken 2111 times.
✓ Branch 178 taken 1398 times.
✓ Branch 179 taken 2111 times.
✓ Branch 180 taken 1398 times.
✓ Branch 181 taken 2111 times.
✓ Branch 182 taken 1398 times.
✓ Branch 183 taken 2111 times.
✓ Branch 184 taken 18369 times.
✓ Branch 185 taken 69559 times.
✓ Branch 186 taken 18369 times.
✓ Branch 187 taken 69559 times.
✓ Branch 188 taken 18369 times.
✓ Branch 189 taken 69559 times.
✓ Branch 190 taken 18369 times.
✓ Branch 191 taken 69559 times.
|
2546808 | return (notEqual(a[0], b[0]) ? a[0] < b[0] |
1327 |
117/144✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2464 times.
✓ Branch 13 taken 5779 times.
✓ Branch 14 taken 2464 times.
✓ Branch 15 taken 5779 times.
✓ Branch 16 taken 2464 times.
✓ Branch 17 taken 5779 times.
✓ Branch 18 taken 1098 times.
✓ Branch 19 taken 1943 times.
✓ Branch 20 taken 1098 times.
✓ Branch 21 taken 1943 times.
✓ Branch 22 taken 1098 times.
✓ Branch 23 taken 1943 times.
✓ Branch 24 taken 2238 times.
✓ Branch 25 taken 6691 times.
✓ Branch 26 taken 2238 times.
✓ Branch 27 taken 6691 times.
✓ Branch 28 taken 2238 times.
✓ Branch 29 taken 6691 times.
✓ Branch 30 taken 98 times.
✓ Branch 31 taken 1063 times.
✓ Branch 32 taken 98 times.
✓ Branch 33 taken 1063 times.
✓ Branch 34 taken 98 times.
✓ Branch 35 taken 1063 times.
✓ Branch 36 taken 67 times.
✓ Branch 37 taken 1040 times.
✓ Branch 38 taken 67 times.
✓ Branch 39 taken 1040 times.
✓ Branch 40 taken 67 times.
✓ Branch 41 taken 1040 times.
✓ Branch 42 taken 19 times.
✓ Branch 43 taken 107 times.
✓ Branch 44 taken 19 times.
✓ Branch 45 taken 107 times.
✓ Branch 46 taken 19 times.
✓ Branch 47 taken 107 times.
✓ Branch 48 taken 62 times.
✓ Branch 49 taken 93 times.
✓ Branch 50 taken 62 times.
✓ Branch 51 taken 93 times.
✓ Branch 52 taken 62 times.
✓ Branch 53 taken 93 times.
✓ Branch 54 taken 18 times.
✓ Branch 55 taken 90 times.
✓ Branch 56 taken 18 times.
✓ Branch 57 taken 90 times.
✓ Branch 58 taken 18 times.
✓ Branch 59 taken 90 times.
✓ Branch 60 taken 4 times.
✓ Branch 61 taken 76 times.
✓ Branch 62 taken 4 times.
✓ Branch 63 taken 76 times.
✓ Branch 64 taken 4 times.
✓ Branch 65 taken 76 times.
✓ Branch 66 taken 200 times.
✓ Branch 67 taken 983 times.
✓ Branch 68 taken 200 times.
✓ Branch 69 taken 983 times.
✓ Branch 70 taken 200 times.
✓ Branch 71 taken 983 times.
✗ Branch 72 not taken.
✗ Branch 73 not taken.
✗ Branch 74 not taken.
✗ Branch 75 not taken.
✗ Branch 76 not taken.
✗ Branch 77 not taken.
✓ Branch 78 taken 60960 times.
✓ Branch 79 taken 163732 times.
✓ Branch 80 taken 60960 times.
✓ Branch 81 taken 163732 times.
✓ Branch 82 taken 60960 times.
✓ Branch 83 taken 163732 times.
✓ Branch 84 taken 16279 times.
✓ Branch 85 taken 53012 times.
✓ Branch 86 taken 16279 times.
✓ Branch 87 taken 53012 times.
✓ Branch 88 taken 16279 times.
✓ Branch 89 taken 53012 times.
✓ Branch 90 taken 13436 times.
✓ Branch 91 taken 58168 times.
✓ Branch 92 taken 13436 times.
✓ Branch 93 taken 58168 times.
✓ Branch 94 taken 13436 times.
✓ Branch 95 taken 58168 times.
✓ Branch 96 taken 2140 times.
✓ Branch 97 taken 3002 times.
✓ Branch 98 taken 2140 times.
✓ Branch 99 taken 3002 times.
✓ Branch 100 taken 2140 times.
✓ Branch 101 taken 3002 times.
✓ Branch 102 taken 520 times.
✓ Branch 103 taken 3785 times.
✓ Branch 104 taken 520 times.
✓ Branch 105 taken 3785 times.
✓ Branch 106 taken 520 times.
✓ Branch 107 taken 3785 times.
✓ Branch 108 taken 1442 times.
✓ Branch 109 taken 2288 times.
✓ Branch 110 taken 1442 times.
✓ Branch 111 taken 2288 times.
✓ Branch 112 taken 1442 times.
✓ Branch 113 taken 2288 times.
✓ Branch 114 taken 125 times.
✓ Branch 115 taken 1407 times.
✓ Branch 116 taken 125 times.
✓ Branch 117 taken 1407 times.
✓ Branch 118 taken 125 times.
✓ Branch 119 taken 1407 times.
✗ Branch 120 not taken.
✓ Branch 121 taken 637 times.
✗ Branch 122 not taken.
✓ Branch 123 taken 637 times.
✗ Branch 124 not taken.
✓ Branch 125 taken 637 times.
✗ Branch 126 not taken.
✗ Branch 127 not taken.
✗ Branch 128 not taken.
✗ Branch 129 not taken.
✗ Branch 130 not taken.
✗ Branch 131 not taken.
✓ Branch 132 taken 406 times.
✓ Branch 133 taken 1705 times.
✓ Branch 134 taken 406 times.
✓ Branch 135 taken 1705 times.
✓ Branch 136 taken 406 times.
✓ Branch 137 taken 1705 times.
✓ Branch 138 taken 17014 times.
✓ Branch 139 taken 52545 times.
✓ Branch 140 taken 17014 times.
✓ Branch 141 taken 52545 times.
✓ Branch 142 taken 17014 times.
✓ Branch 143 taken 52545 times.
|
1430208 | : (notEqual(a[1], b[1]) ? a[1] < b[1] |
1328 |
39/48✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2464 times.
✓ Branch 5 taken 5779 times.
✓ Branch 6 taken 1098 times.
✓ Branch 7 taken 1943 times.
✓ Branch 8 taken 2238 times.
✓ Branch 9 taken 6691 times.
✓ Branch 10 taken 98 times.
✓ Branch 11 taken 1063 times.
✓ Branch 12 taken 67 times.
✓ Branch 13 taken 1040 times.
✓ Branch 14 taken 19 times.
✓ Branch 15 taken 107 times.
✓ Branch 16 taken 62 times.
✓ Branch 17 taken 93 times.
✓ Branch 18 taken 18 times.
✓ Branch 19 taken 90 times.
✓ Branch 20 taken 4 times.
✓ Branch 21 taken 76 times.
✓ Branch 22 taken 200 times.
✓ Branch 23 taken 983 times.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 60960 times.
✓ Branch 27 taken 163732 times.
✓ Branch 28 taken 16279 times.
✓ Branch 29 taken 53012 times.
✓ Branch 30 taken 13436 times.
✓ Branch 31 taken 58168 times.
✓ Branch 32 taken 2140 times.
✓ Branch 33 taken 3002 times.
✓ Branch 34 taken 520 times.
✓ Branch 35 taken 3785 times.
✓ Branch 36 taken 1442 times.
✓ Branch 37 taken 2288 times.
✓ Branch 38 taken 125 times.
✓ Branch 39 taken 1407 times.
✗ Branch 40 not taken.
✓ Branch 41 taken 637 times.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 406 times.
✓ Branch 45 taken 1705 times.
✓ Branch 46 taken 17014 times.
✓ Branch 47 taken 52545 times.
|
476736 | : (a[2] < b[2]))); |
1329 | }); | ||
1330 | |||
1331 | 12690 | const auto squaredEps = eps*eps; | |
1332 | 199142 | points.erase(std::unique( | |
1333 | points.begin(), points.end(), | ||
1334 | 143780 | [squaredEps] (const auto& a, const auto&b) { return (b-a).two_norm2() < squaredEps; }), | |
1335 | points.end() | ||
1336 | ); | ||
1337 | |||
1338 | // return false if we don't have more than four unique points (dim+1) | ||
1339 |
4/4✓ Branch 0 taken 3747 times.
✓ Branch 1 taken 2660 times.
✓ Branch 2 taken 3747 times.
✓ Branch 3 taken 2660 times.
|
25380 | if (points.size() < 4) |
1340 | return false; | ||
1341 | |||
1342 | // check if the points are coplanar (then we don't have a 3-dimensional intersection) | ||
1343 | 3747 | const bool coplanar = [&] | |
1344 | { | ||
1345 | 11080 | const auto p0 = points[0]; | |
1346 | 18735 | const auto normal = crossProduct(points[1] - p0, points[2] - p0); | |
1347 | // include the normal in eps (instead of norm*norm) since the normal can become very small | ||
1348 | // if the first three points are very close together | ||
1349 | 3747 | const auto epsCoplanar = normal.two_norm()*norm*eps_; | |
1350 |
4/4✓ Branch 0 taken 196 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 196 times.
✓ Branch 3 taken 8 times.
|
7333 | for (int i = 3; i < points.size(); ++i) |
1351 | { | ||
1352 | 9820 | const auto ad = points[i] - p0; | |
1353 | using std::abs; | ||
1354 |
4/4✓ Branch 0 taken 108 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 88 times.
|
9820 | if (abs(normal*ad) > epsCoplanar) |
1355 | 1324 | return false; | |
1356 | } | ||
1357 | |||
1358 | return true; | ||
1359 | 7378 | }(); | |
1360 | |||
1361 |
2/2✓ Branch 0 taken 1324 times.
✓ Branch 1 taken 2423 times.
|
7378 | if (coplanar) |
1362 | return false; | ||
1363 | |||
1364 | // we return the intersection as point cloud (that can be triangulated later) | ||
1365 |
1/2✓ Branch 1 taken 1324 times.
✗ Branch 2 not taken.
|
2540 | intersection = points; |
1366 | |||
1367 | return true; | ||
1368 | } | ||
1369 | |||
1370 | /*! | ||
1371 | * \brief Colliding segment and convex polyhedron | ||
1372 | * \param geo1/geo2 The geometries to intersect | ||
1373 | * \param intersection Container to store the intersection result | ||
1374 | * \todo implement overloads for polygon-, segment- or point-like intersections | ||
1375 | */ | ||
1376 | template<class P = Policy, std::enable_if_t<P::dimIntersection != 3, int> = 0> | ||
1377 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | ||
1378 | { | ||
1379 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1380 | DUNE_THROW(Dune::NotImplemented, "Polyhedron-polygon intersection detection only implemented for polygon-like intersections"); | ||
1381 | } | ||
1382 | }; | ||
1383 | |||
1384 | /*! | ||
1385 | * \ingroup Geometry | ||
1386 | * \brief A class for polygon--segment intersection in 3d space | ||
1387 | */ | ||
1388 | template <class Geometry1, class Geometry2, class Policy> | ||
1389 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 2, 1> | ||
1390 | { | ||
1391 | enum { dimworld = 3 }; | ||
1392 | enum { dim1 = 2 }; | ||
1393 | enum { dim2 = 1 }; | ||
1394 | |||
1395 | public: | ||
1396 | using ctype = typename Policy::ctype; | ||
1397 | using Point = typename Policy::Point; | ||
1398 | using Intersection = typename Policy::Intersection; | ||
1399 | |||
1400 | private: | ||
1401 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
1402 | |||
1403 | public: | ||
1404 | /*! | ||
1405 | * \brief Colliding segment and convex polyhedron | ||
1406 | * \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson, | ||
1407 | * published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. (Chapter 5.3.6) | ||
1408 | * \param geo1/geo2 The geometries to intersect | ||
1409 | * \param intersection If the geometries collide, is holds the corner points of | ||
1410 | * the intersection object in global coordinates. | ||
1411 | * \note This overload is used when point-like intersections are seeked | ||
1412 | */ | ||
1413 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
1414 | 354449 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
1415 | { | ||
1416 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1417 | |||
1418 | ctype tfirst, tlast; | ||
1419 |
2/2✓ Branch 1 taken 73770 times.
✓ Branch 2 taken 280618 times.
|
354449 | if (intersect_(geo1, geo2, tfirst, tlast)) |
1420 | { | ||
1421 | // the intersection exists. Export the intersections geometry now: | ||
1422 | // s(t) = a + t(b-a) in [tfirst, tlast] | ||
1423 | 295172 | intersection = Intersection({geo2.global(tfirst), geo2.global(tlast)}); | |
1424 | 73813 | return true; | |
1425 | } | ||
1426 | |||
1427 | return false; | ||
1428 | } | ||
1429 | |||
1430 | /*! | ||
1431 | * \brief Colliding segment and convex polyhedron | ||
1432 | * \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson, | ||
1433 | * published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. (Chapter 5.3.6) | ||
1434 | * \param geo1/geo2 The geometries to intersect | ||
1435 | * \param is If the geometries collide, is holds the corner points of | ||
1436 | * the intersection object in global coordinates. | ||
1437 | * \note This overload is used when point-like intersections are seeked | ||
1438 | */ | ||
1439 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
1440 | 2705188 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& is) | |
1441 | { | ||
1442 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1443 | |||
1444 | 2705188 | const auto p = geo2.corner(0); | |
1445 | 2705188 | const auto q = geo2.corner(1); | |
1446 | |||
1447 | 2705188 | const auto a = geo1.corner(0); | |
1448 | 2705188 | const auto b = geo1.corner(1); | |
1449 | 2705188 | const auto c = geo1.corner(2); | |
1450 | |||
1451 |
4/4✓ Branch 0 taken 464047 times.
✓ Branch 1 taken 1388731 times.
✓ Branch 2 taken 464047 times.
✓ Branch 3 taken 1388731 times.
|
5383304 | if (geo1.corners() == 3) |
1452 | 783135 | return intersect_<Policy>(a, b, c, p, q, is); | |
1453 | |||
1454 |
2/4✓ Branch 0 taken 1388731 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1388731 times.
✗ Branch 3 not taken.
|
3817034 | else if (geo1.corners() == 4) |
1455 | { | ||
1456 | 1922053 | Intersection is1, is2; | |
1457 | bool hasSegment1, hasSegment2; | ||
1458 | |||
1459 | 1922053 | const auto d = geo1.corner(3); | |
1460 | 1922053 | const bool intersects1 = intersect_<Policy>(a, b, d, p, q, is1, hasSegment1); | |
1461 | 1922053 | const bool intersects2 = intersect_<Policy>(a, d, c, p, q, is2, hasSegment2); | |
1462 | |||
1463 |
4/4✓ Branch 0 taken 1374151 times.
✓ Branch 1 taken 28116 times.
✓ Branch 2 taken 1346312 times.
✓ Branch 3 taken 27839 times.
|
1922053 | if (hasSegment1 || hasSegment2) |
1464 | return false; | ||
1465 | |||
1466 |
2/2✓ Branch 0 taken 97613 times.
✓ Branch 1 taken 1248699 times.
|
1861312 | if (intersects1) { is = is1; return true; } |
1467 |
2/2✓ Branch 0 taken 48264 times.
✓ Branch 1 taken 1200435 times.
|
1746745 | if (intersects2) { is = is2; return true; } |
1468 | |||
1469 | return false; | ||
1470 | } | ||
1471 | |||
1472 | else | ||
1473 | ✗ | DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type " | |
1474 | << geo1.type() << ", "<< geo1.corners() << " corners."); | ||
1475 | } | ||
1476 | |||
1477 | private: | ||
1478 | /*! | ||
1479 | * \brief Obtain local coordinates of start/end point of the intersecting segment. | ||
1480 | */ | ||
1481 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
1482 | 354449 | static bool intersect_(const Geometry1& geo1, const Geometry2& geo2, ctype& tfirst, ctype& tlast) | |
1483 | { | ||
1484 | // lambda to obtain the facet corners on geo1 | ||
1485 | 354388 | auto getFacetCorners = [] (const Geometry1& geo1) | |
1486 | { | ||
1487 |
3/10✗ Branch 0 not taken.
✓ Branch 1 taken 354364 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
354388 | std::vector< std::array<int, 2> > facetCorners; |
1488 |
6/12✗ Branch 0 not taken.
✓ Branch 1 taken 354364 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 354364 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
✓ Branch 10 taken 11 times.
✗ Branch 11 not taken.
|
708776 | switch (geo1.corners()) |
1489 | { | ||
1490 | 13 | case 4: // quadrilateral | |
1491 |
1/4✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
|
13 | facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}}; |
1492 | break; | ||
1493 | 354375 | case 3: // triangle | |
1494 |
2/4✓ Branch 1 taken 354364 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
|
354375 | facetCorners = {{1, 0}, {0, 2}, {2, 1}}; |
1495 | break; | ||
1496 | ✗ | default: | |
1497 | ✗ | DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type " | |
1498 | << geo1.type() << " with "<< geo1.corners() << " corners."); | ||
1499 | } | ||
1500 | |||
1501 | 1063164 | return facetCorners; | |
1502 | }; | ||
1503 | |||
1504 | 354449 | const auto center1 = geo1.center(); | |
1505 | 1063299 | const auto normal1 = crossProduct(geo1.corner(1) - geo1.corner(0), | |
1506 | 1417700 | geo1.corner(2) - geo1.corner(0)); | |
1507 | |||
1508 | // lambda to obtain the normal on a facet | ||
1509 | 3330613 | auto computeNormal = [¢er1, &normal1, &geo1] (const std::array<int, 2>& facetCorners) | |
1510 | { | ||
1511 | 1488082 | const auto c0 = geo1.corner(facetCorners[0]); | |
1512 | 1488082 | const auto c1 = geo1.corner(facetCorners[1]); | |
1513 | 744041 | const auto edge = c1 - c0; | |
1514 | |||
1515 | 744041 | Dune::FieldVector<ctype, dimworld> n = crossProduct(edge, normal1); | |
1516 | 1488082 | n /= n.two_norm(); | |
1517 | |||
1518 | // orientation of the element is not known | ||
1519 | // make sure normal points outwards of element | ||
1520 |
2/4✓ Branch 0 taken 743957 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
1488082 | if ( n*(center1-c0) > 0.0 ) |
1521 | n *= -1.0; | ||
1522 | |||
1523 | 744041 | return n; | |
1524 | }; | ||
1525 | |||
1526 | 354449 | return Detail::computeSegmentIntersection(geo1, geo2, eps_, tfirst, tlast, getFacetCorners, computeNormal); | |
1527 | } | ||
1528 | |||
1529 | /*! | ||
1530 | * \brief triangle--segment point-like intersection with points as input. | ||
1531 | */ | ||
1532 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
1533 | static bool intersect_(const Point& a, const Point& b, const Point& c, | ||
1534 | const Point& p, const Point& q, | ||
1535 | Intersection& is) | ||
1536 | { | ||
1537 | bool hasSegment; | ||
1538 | 464047 | return intersect_(a, b, c, p, q, is, hasSegment); | |
1539 | } | ||
1540 | |||
1541 | /*! | ||
1542 | * \brief triangle--segment point-like intersection with points as input. Also | ||
1543 | * stores if a segment-like intersection was found in the provided boolean. | ||
1544 | */ | ||
1545 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
1546 | 3268581 | static bool intersect_(const Point& a, const Point& b, const Point& c, | |
1547 | const Point& p, const Point& q, | ||
1548 | Intersection& is, bool& hasSegmentIs) | ||
1549 | { | ||
1550 | 3268581 | hasSegmentIs = false; | |
1551 | |||
1552 | 3268581 | const auto ab = b - a; | |
1553 | 3268581 | const auto ac = c - a; | |
1554 | 3268581 | const auto qp = p - q; | |
1555 | |||
1556 | // compute the triangle normal that defines the triangle plane | ||
1557 | 3268581 | const auto normal = crossProduct(ab, ac); | |
1558 | |||
1559 | // compute the denominator | ||
1560 | // if denom is 0 the segment is parallel and we can return | ||
1561 | 3268581 | const auto denom = normal*qp; | |
1562 | 3268581 | const auto abnorm2 = ab.two_norm2(); | |
1563 | 3268581 | const auto eps = eps_*abnorm2*qp.two_norm(); | |
1564 | using std::abs; | ||
1565 |
4/4✓ Branch 0 taken 1157013 times.
✓ Branch 1 taken 752908 times.
✓ Branch 2 taken 1157013 times.
✓ Branch 3 taken 752908 times.
|
6537162 | if (abs(denom) < eps) |
1566 | { | ||
1567 | 1373701 | const auto pa = a - p; | |
1568 | 1373701 | const auto denom2 = normal*pa; | |
1569 |
2/2✓ Branch 0 taken 292120 times.
✓ Branch 1 taken 864893 times.
|
4121103 | if (abs(denom2) > eps_*pa.two_norm()*abnorm2) |
1570 | return false; | ||
1571 | |||
1572 | // if we get here, we are in-plane. Check if a | ||
1573 | // segment-like intersection with geometry 1 exists. | ||
1574 | using SegmentPolicy = typename IntersectionPolicy::SegmentPolicy<ctype, dimworld>; | ||
1575 | using Triangle = Dune::AffineGeometry<ctype, 2, dimworld>; | ||
1576 | using Segment = Dune::AffineGeometry<ctype, 1, dimworld>; | ||
1577 | using SegmentIntersectionAlgorithm = GeometryIntersection<Triangle, Segment, SegmentPolicy>; | ||
1578 | using SegmentIntersectionType = typename SegmentIntersectionAlgorithm::Intersection; | ||
1579 | 354364 | SegmentIntersectionType segmentIs; | |
1580 | |||
1581 | 354364 | Triangle triangle(Dune::GeometryTypes::simplex(2), std::array<Point, 3>({a, b, c})); | |
1582 | 354364 | Segment segment(Dune::GeometryTypes::simplex(1), std::array<Point, 2>({p, q})); | |
1583 |
2/2✓ Branch 1 taken 58012 times.
✓ Branch 2 taken 234108 times.
|
354364 | if (SegmentIntersectionAlgorithm::intersection(triangle, segment, segmentIs)) |
1584 | { | ||
1585 | 73750 | hasSegmentIs = true; | |
1586 | 73750 | return false; | |
1587 | } | ||
1588 | |||
1589 | // We are in-plane. A point-like | ||
1590 | // intersection can only be on the edges | ||
1591 |
2/2✓ Branch 0 taken 424188 times.
✓ Branch 1 taken 146602 times.
|
989344 | for (const auto& ip : {p, q}) |
1592 | { | ||
1593 | 516658 | if ( intersectsPointSimplex(ip, a, b) | |
1594 |
2/2✓ Branch 1 taken 344380 times.
✓ Branch 2 taken 25067 times.
|
461569 | || intersectsPointSimplex(ip, b, c) |
1595 |
4/4✓ Branch 0 taken 369447 times.
✓ Branch 1 taken 54741 times.
✓ Branch 3 taken 7698 times.
✓ Branch 4 taken 336682 times.
|
953112 | || intersectsPointSimplex(ip, c, a) ) |
1596 | { | ||
1597 | 88542 | is = ip; | |
1598 | 88542 | return true; | |
1599 | } | ||
1600 | } | ||
1601 | |||
1602 | 192072 | return false; | |
1603 | } | ||
1604 | |||
1605 | // compute intersection t value of pq with plane of triangle. | ||
1606 | // a segment intersects if and only if 0 <= t <= 1. | ||
1607 | 1894880 | const auto ap = p - a; | |
1608 | 1894880 | const auto t = (ap*normal)/denom; | |
1609 |
2/2✓ Branch 0 taken 597679 times.
✓ Branch 1 taken 155229 times.
|
1894880 | if (t < 0.0 - eps_) return false; |
1610 |
2/2✓ Branch 0 taken 449497 times.
✓ Branch 1 taken 148182 times.
|
1436115 | if (t > 1.0 + eps_) return false; |
1611 | |||
1612 | // compute the barycentric coordinates and check if the intersection point | ||
1613 | // is inside the bounds of the triangle | ||
1614 | 987776 | const auto e = crossProduct(qp, ap); | |
1615 | 987776 | const auto v = (ac*e)/denom; | |
1616 |
4/4✓ Branch 0 taken 333450 times.
✓ Branch 1 taken 116047 times.
✓ Branch 2 taken 262013 times.
✓ Branch 3 taken 71437 times.
|
987776 | if (v < -eps_ || v > 1.0 + eps_) return false; |
1617 | 423202 | const auto w = -(ab*e)/denom; | |
1618 |
4/4✓ Branch 0 taken 201694 times.
✓ Branch 1 taken 60319 times.
✓ Branch 2 taken 165820 times.
✓ Branch 3 taken 35874 times.
|
423202 | if (w < -eps_ || v + w > 1.0 + eps_) return false; |
1619 | |||
1620 | // Now we are sure there is an intersection points | ||
1621 | // Perform delayed division compute the last barycentric coordinate component | ||
1622 | 225203 | const auto u = 1.0 - v - w; | |
1623 | |||
1624 | 225203 | Point ip(0.0); | |
1625 | ip.axpy(u, a); | ||
1626 | ip.axpy(v, b); | ||
1627 | 225203 | ip.axpy(w, c); | |
1628 | 225203 | is = ip; | |
1629 | 225203 | return true; | |
1630 | } | ||
1631 | }; | ||
1632 | |||
1633 | /*! | ||
1634 | * \ingroup Geometry | ||
1635 | * \brief A class for segment--polygon intersection in 3d space | ||
1636 | */ | ||
1637 | template <class Geometry1, class Geometry2, class Policy> | ||
1638 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 1, 2> | ||
1639 | : public GeometryIntersection<Geometry2, Geometry1, Policy, 3, 2, 1> | ||
1640 | { | ||
1641 | using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 3, 2, 1>; | ||
1642 | public: | ||
1643 | /*! | ||
1644 | * \brief Colliding segment and convex polygon | ||
1645 | * \param geo1/geo2 The geometries to intersect | ||
1646 | * \param intersection If the geometries collide intersection holds the | ||
1647 | * corner points of the intersection object in global coordinates. | ||
1648 | * \note This forwards to the polyhedron-polygon specialization with swapped arguments. | ||
1649 | */ | ||
1650 | template<class P = Policy> | ||
1651 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection) | ||
1652 | { | ||
1653 | return Base::intersection(geo2, geo1, intersection); | ||
1654 | } | ||
1655 | }; | ||
1656 | |||
1657 | /*! | ||
1658 | * \ingroup Geometry | ||
1659 | * \brief A class for segment--segment intersection in 3d space | ||
1660 | */ | ||
1661 | template <class Geometry1, class Geometry2, class Policy> | ||
1662 | class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 1, 1> | ||
1663 | { | ||
1664 | enum { dimworld = 3 }; | ||
1665 | enum { dim1 = 1 }; | ||
1666 | enum { dim2 = 1 }; | ||
1667 | |||
1668 | public: | ||
1669 | using ctype = typename Policy::ctype; | ||
1670 | using Point = typename Policy::Point; | ||
1671 | using Intersection = typename Policy::Intersection; | ||
1672 | |||
1673 | private: | ||
1674 | static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons | ||
1675 | |||
1676 | public: | ||
1677 | /*! | ||
1678 | * \brief Colliding two segments | ||
1679 | * \param geo1/geo2 The geometries to intersect | ||
1680 | * \param intersection The intersection point | ||
1681 | * \note This overload is used when point-like intersections are seeked | ||
1682 | */ | ||
1683 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0> | ||
1684 | 418 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
1685 | { | ||
1686 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1687 | |||
1688 | 418 | const auto v1 = geo1.corner(1) - geo1.corner(0); | |
1689 | 418 | const auto v2 = geo2.corner(1) - geo2.corner(0); | |
1690 | 418 | const auto ac = geo2.corner(0) - geo1.corner(0); | |
1691 | |||
1692 | 418 | const auto v1Norm2 = v1.two_norm2(); | |
1693 | 418 | const auto eps2 = eps_*v1Norm2; | |
1694 | |||
1695 | 418 | const auto n = crossProduct(v1, v2); | |
1696 | |||
1697 | // first check if segments are parallel | ||
1698 | using std::abs; | ||
1699 |
2/2✓ Branch 1 taken 100 times.
✓ Branch 2 taken 318 times.
|
836 | if ( n.two_norm2() < eps2*v1Norm2 ) |
1700 | { | ||
1701 | // check if they lie on the same line | ||
1702 |
2/2✓ Branch 1 taken 51 times.
✓ Branch 2 taken 49 times.
|
200 | if (crossProduct(v1, ac).two_norm2() > eps2) |
1703 | return false; | ||
1704 | |||
1705 | // they lie on the same line, | ||
1706 | // if so, point intersection can only be one of the corners | ||
1707 | 51 | const auto sp = v1*v2; | |
1708 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 42 times.
|
51 | if ( sp < 0.0 ) |
1709 | { | ||
1710 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
|
9 | if ( ac.two_norm2() < eps2 ) |
1711 | 4 | { intersection = geo2.corner(0); return true; } | |
1712 | |||
1713 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
|
10 | if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 ) |
1714 | ✗ | { intersection = geo2.corner(1); return true; } | |
1715 | } | ||
1716 | else | ||
1717 | { | ||
1718 |
2/2✓ Branch 2 taken 4 times.
✓ Branch 3 taken 38 times.
|
84 | if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 ) |
1719 | 4 | { intersection = geo2.corner(1); return true; } | |
1720 | |||
1721 |
2/2✓ Branch 2 taken 8 times.
✓ Branch 3 taken 30 times.
|
76 | if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 ) |
1722 | 8 | { intersection = geo2.corner(0); return true; } | |
1723 | } | ||
1724 | |||
1725 | // no intersection | ||
1726 | 35 | return false; | |
1727 | } | ||
1728 | |||
1729 | // in-plane normal vector on v1 | ||
1730 | 318 | const auto v1Normal = crossProduct(v1, n); | |
1731 | |||
1732 | // intersection point on v2 in local coords | ||
1733 | 636 | const auto t2 = - 1.0*(ac*v1Normal) / (v2*v1Normal); | |
1734 | |||
1735 | // check if the local coords are valid | ||
1736 |
4/4✓ Branch 0 taken 254 times.
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 40 times.
|
318 | if (t2 < -1.0*eps_ || t2 > 1.0 + eps_) |
1737 | return false; | ||
1738 | |||
1739 |
2/2✓ Branch 3 taken 162 times.
✓ Branch 4 taken 52 times.
|
428 | if (auto ip = geo2.global(t2); intersectsPointGeometry(ip, geo1)) |
1740 | 162 | { intersection = std::move(ip); return true; } | |
1741 | |||
1742 | 52 | return false; | |
1743 | } | ||
1744 | |||
1745 | /*! | ||
1746 | * \brief Colliding two segments in 3D | ||
1747 | * \param geo1/geo2 The geometries to intersect | ||
1748 | * \param intersection If the geometries collide, is holds the corner points of | ||
1749 | * the intersection object in global coordinates. | ||
1750 | * \note This overload is used when segment-like intersections are seeked | ||
1751 | */ | ||
1752 | template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0> | ||
1753 | 478 | static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection) | |
1754 | { | ||
1755 | static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension"); | ||
1756 | |||
1757 | 478 | const auto& a = geo1.corner(0); | |
1758 | 478 | const auto& b = geo1.corner(1); | |
1759 | 478 | const auto ab = b-a; | |
1760 | |||
1761 | 478 | const auto& p = geo2.corner(0); | |
1762 | 478 | const auto& q = geo2.corner(1); | |
1763 | 478 | const auto pq = q-p; | |
1764 | |||
1765 | 478 | const auto abNorm2 = ab.two_norm2(); | |
1766 | 478 | const auto pqNorm2 = pq.two_norm2(); | |
1767 | |||
1768 | using std::max; | ||
1769 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 443 times.
|
478 | const auto eps2 = eps_*max(abNorm2, pqNorm2); |
1770 | |||
1771 | // if the segment are not parallel there is no segment intersection | ||
1772 | using std::abs; | ||
1773 |
2/2✓ Branch 1 taken 474 times.
✓ Branch 2 taken 4 times.
|
956 | if (crossProduct(ab, pq).two_norm2() > eps2*eps2) |
1774 | return false; | ||
1775 | |||
1776 | 474 | const auto ap = (p-a); | |
1777 | 474 | const auto aq = (q-a); | |
1778 | |||
1779 | // points have to be colinear | ||
1780 |
2/2✓ Branch 1 taken 470 times.
✓ Branch 2 taken 4 times.
|
948 | if (crossProduct(ap, aq).two_norm2() > eps2*eps2) |
1781 | return false; | ||
1782 | |||
1783 | // scaled local coordinates | ||
1784 | // we save the division for the normalization for now | ||
1785 | // and do it in the very end if we find an intersection | ||
1786 | 470 | auto tp = ap*ab; | |
1787 | 470 | auto tq = aq*ab; | |
1788 | |||
1789 | // make sure they are sorted | ||
1790 | using std::swap; | ||
1791 |
2/2✓ Branch 0 taken 33 times.
✓ Branch 1 taken 437 times.
|
470 | if (tp > tq) |
1792 | 33 | swap(tp, tq); | |
1793 | |||
1794 | using std::clamp; | ||
1795 |
2/2✓ Branch 0 taken 334 times.
✓ Branch 1 taken 136 times.
|
470 | tp = clamp(tp, 0.0, abNorm2); |
1796 |
2/2✓ Branch 0 taken 466 times.
✓ Branch 1 taken 4 times.
|
470 | tq = clamp(tq, 0.0, abNorm2); |
1797 | |||
1798 |
4/4✓ Branch 0 taken 338 times.
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 338 times.
✓ Branch 3 taken 132 times.
|
940 | if (abs(tp-tq) < eps2) |
1799 | return false; | ||
1800 | |||
1801 | 676 | intersection = Intersection({geo1.global(tp/abNorm2), geo1.global(tq/abNorm2)}); | |
1802 | 338 | return true; | |
1803 | } | ||
1804 | }; | ||
1805 | |||
1806 | } // end namespace Dumux | ||
1807 | |||
1808 | #endif | ||
1809 |