GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#include "hpp/rbprm/utils/algorithms.h" |
||
2 |
|||
3 |
#include <hpp/pinocchio/collision-object.hh> |
||
4 |
#include <hpp/util/debug.hh> |
||
5 |
#include <pinocchio/fwd.hpp> |
||
6 |
#include <pinocchio/multibody/geometry.hpp> |
||
7 |
|||
8 |
using namespace hpp; |
||
9 |
|||
10 |
namespace geom { |
||
11 |
|||
12 |
/// Computes the (unit) normal vector of a triangle based on the |
||
13 |
/// global position of its vertices. The normal is subject to convention! |
||
14 |
/// \param tri The global position of a triangles vertices |
||
15 |
43580 |
Point TriangleNormal(TrianglePoints& tri) { |
|
16 |
✓✗✓✗ |
43580 |
Point normal = (tri.p2 - tri.p1).cross(tri.p3 - tri.p1); |
17 |
43580 |
normal.normalize(); |
|
18 |
// hppDout(notice,"normal, in geom :: "<<normal.transpose()); |
||
19 |
43580 |
return normal; |
|
20 |
} |
||
21 |
87160 |
BVHModelOBConst_Ptr_t GetModel( |
|
22 |
const hpp::pinocchio::CollisionObjectConstPtr_t object, |
||
23 |
hpp::pinocchio::DeviceData& deviceData) { |
||
24 |
✓✗✓✗ ✗✓ |
87160 |
assert(object->fcl()->collisionGeometry()->getNodeType() == fcl::BV_OBBRSS); |
25 |
const BVHModelOBConst_Ptr_t model = |
||
26 |
static_pointer_cast<const hpp::fcl::BVHModel<hpp::fcl::OBBRSS> >( |
||
27 |
✓✗ | 174320 |
object->fcl()->collisionGeometry()); |
28 |
✗✓ | 87160 |
assert(model->getModelType() == hpp::fcl::BVH_MODEL_TRIANGLES); |
29 |
// todo avoid recopy, but if we keep the same ptr the geometry is changed |
||
30 |
✓✗✓✗ ✓✗ |
87160 |
const BVHModelOBConst_Ptr_t modelTransform(new BVHModelOB(*model)); |
31 |
✓✓ | 938373 |
for (int i = 0; i < model->num_vertices; i++) { |
32 |
851213 |
modelTransform->vertices[i] = |
|
33 |
✓✗✓✗ |
1702426 |
object->fcl(deviceData)->getTransform().transform(model->vertices[i]); |
34 |
} |
||
35 |
174320 |
return modelTransform; |
|
36 |
} |
||
37 |
|||
38 |
double dot(CPointRef a, CPointRef b) { return a[0] * b[0] + a[1] * b[1]; } |
||
39 |
|||
40 |
19028110 |
double isLeft(CPointRef lA, CPointRef lB, CPointRef p2) { |
|
41 |
19028110 |
return (lB[0] - lA[0]) * (p2[1] - lA[1]) - (p2[0] - lA[0]) * (lB[1] - lA[1]); |
|
42 |
} |
||
43 |
|||
44 |
130740 |
CIT_Point leftMost(CIT_Point pointsBegin, CIT_Point pointsEnd) { |
|
45 |
130740 |
CIT_Point current = pointsBegin + 1; |
|
46 |
130740 |
CIT_Point res = pointsBegin; |
|
47 |
✓✓ | 1697894 |
while (current != pointsEnd) { |
48 |
✓✗✓✗ ✓✓ |
1567154 |
if (current->operator[](0) < res->operator[](0)) res = current; |
49 |
1567154 |
++current; |
|
50 |
} |
||
51 |
130740 |
return res; |
|
52 |
} |
||
53 |
|||
54 |
double area(CIT_Point pointsBegin, CIT_Point pointsEnd) { |
||
55 |
double a = 0; |
||
56 |
|||
57 |
if ((pointsBegin == pointsEnd) || ((pointsBegin + 1) == pointsEnd)) return 0; |
||
58 |
|||
59 |
for (CIT_Point it = pointsBegin + 1; it != pointsEnd - 1; ++it) { |
||
60 |
a += (*it)[0] * ((*(it + 1))[1] - (*(it - 1))[1]); |
||
61 |
} |
||
62 |
a += |
||
63 |
(*(pointsEnd - 1))[0] * ((*(pointsBegin + 1))[1] - (*(pointsEnd - 2))[1]); |
||
64 |
a /= 2; |
||
65 |
return fabs(a); |
||
66 |
} |
||
67 |
|||
68 |
386 |
Point center(CIT_Point pointsBegin, CIT_Point pointsEnd) { |
|
69 |
386 |
double cx = 0; |
|
70 |
386 |
double cy = 0; |
|
71 |
386 |
double cz = 0; |
|
72 |
386 |
size_t i = 0; |
|
73 |
✓✓ | 2360 |
for (CIT_Point it = pointsBegin; it != pointsEnd - 1; ++it) { |
74 |
✓✗ | 1974 |
cx += (*it)[0]; |
75 |
✓✗ | 1974 |
cy += (*it)[1]; |
76 |
✓✗ | 1974 |
cz += (*it)[2]; |
77 |
1974 |
i++; |
|
78 |
} |
||
79 |
386 |
cx = cx / (double)i; |
|
80 |
386 |
cy = cy / (double)i; |
|
81 |
386 |
cz = cz / (double)i; |
|
82 |
|||
83 |
✓✗ | 772 |
return Point(cx, cy, cz); |
84 |
} |
||
85 |
|||
86 |
/// see https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon |
||
87 |
Point centroid(CIT_Point pointsBegin, CIT_Point pointsEnd, double& area) { |
||
88 |
area = 0; |
||
89 |
double cx = 0; |
||
90 |
double cy = 0; |
||
91 |
double cz = 0; |
||
92 |
|||
93 |
for (CIT_Point pit = pointsBegin; pit != pointsEnd - 1; ++pit) { |
||
94 |
area += ((*pit)[0] * (*(pit + 1))[1]) - (((*(pit + 1))[0]) * ((*pit)[1])); |
||
95 |
cx += ((*pit)[0] + (*(pit + 1))[0]) * |
||
96 |
((*pit)[0] * (*(pit + 1))[1] - (*(pit + 1))[0] * (*pit)[1]); |
||
97 |
cy += ((*pit)[1] + (*(pit + 1))[1]) * |
||
98 |
((*pit)[0] * (*(pit + 1))[1] - (*(pit + 1))[0] * (*pit)[1]); |
||
99 |
} |
||
100 |
area = area / 2.; |
||
101 |
cx = cx / (6. * area); |
||
102 |
cy = cy / (6. * area); |
||
103 |
|||
104 |
// compute cz in the plan : |
||
105 |
// TODO |
||
106 |
return Point(cx, cy, cz); |
||
107 |
} |
||
108 |
|||
109 |
Point centerPlanar(T_Point points, const fcl::Vec3f& n, double t) { |
||
110 |
double cx = 0; |
||
111 |
double cy = 0; |
||
112 |
double a = area(points.begin(), points.end()); |
||
113 |
for (size_t i = 0; i < (points.size() - 1); ++i) { |
||
114 |
cx += |
||
115 |
(points[i][0] + points[i + 1][0]) * |
||
116 |
((points[i][0] * points[i + 1][1]) - (points[i + 1][0] * points[i][1])); |
||
117 |
cy += |
||
118 |
(points[i][1] + points[i + 1][1]) * |
||
119 |
((points[i][0] * points[i + 1][1]) - (points[i + 1][0] * points[i][1])); |
||
120 |
} |
||
121 |
|||
122 |
cx = cx / (6 * a); |
||
123 |
cy = cy / (6 * a); |
||
124 |
double cz = -(n[0] * cx + n[1] * cy + t) / |
||
125 |
n[3]; // deduce z from x,y and the plan equation |
||
126 |
return Point(cx, cy, cz); |
||
127 |
} |
||
128 |
|||
129 |
void projectZ(IT_Point pointsBegin, IT_Point pointsEnd) { |
||
130 |
for (IT_Point current = pointsBegin; current != pointsEnd; ++current) { |
||
131 |
(*current)[2] = 0; |
||
132 |
} |
||
133 |
} |
||
134 |
|||
135 |
130740 |
T_Point convexHull(CIT_Point pointsBegin, CIT_Point pointsEnd) { |
|
136 |
130740 |
T_Point res; |
|
137 |
✗✓ | 130740 |
if (pointsBegin == pointsEnd) return res; |
138 |
✓✗✓✗ |
130740 |
Point pointOnHull = *leftMost(pointsBegin, pointsEnd); |
139 |
✓✗ | 130740 |
Point lastPoint = *pointsBegin; |
140 |
1000944 |
do { |
|
141 |
✓✗ | 1131684 |
lastPoint = *pointsBegin; |
142 |
✓✓ | 17579067 |
for (CIT_Point current = pointsBegin + 1; current != pointsEnd; ++current) { |
143 |
✓✗✓✓ |
32733984 |
if ((lastPoint == pointOnHull) || |
144 |
✓✗✓✗ ✓✗✓✗ ✓✓✓✓ |
32733984 |
(isLeft(pointOnHull, lastPoint, *current) > 0)) { |
145 |
✓✗✓✓ |
3275955 |
if ((std::find(res.begin(), res.end(), *current) == res.end()) || |
146 |
✓✗✓✓ ✓✓ |
3275955 |
((*current) == (*(res.begin())))) // only selected it if not on the |
147 |
// list (or the first) |
||
148 |
✓✗ | 1975020 |
lastPoint = *current; |
149 |
} |
||
150 |
} |
||
151 |
✓✗ | 1131684 |
res.insert(res.end(), pointOnHull); |
152 |
✓✗ | 1131684 |
pointOnHull = lastPoint; |
153 |
✓✗ | 1131684 |
} while (lastPoint != |
154 |
✓✓ | 2263368 |
*res.begin()); // infinite loop with fcl types (instead of eigen) |
155 |
✓✗ | 130740 |
res.insert(res.end(), lastPoint); |
156 |
130740 |
return res; |
|
157 |
} |
||
158 |
43580 |
bool containsHull(T_Point hull, CPointRef aPoint, const double epsilon) { |
|
159 |
43580 |
int n = (int)hull.size(); |
|
160 |
✗✓ | 43580 |
if (n < 1) |
161 |
return false; |
||
162 |
✗✓ | 43580 |
else if (n == 1) { |
163 |
double x = aPoint[0] - hull.front()[0]; |
||
164 |
double y = aPoint[1] - hull.front()[1]; |
||
165 |
return sqrt(x * x + y * y) < epsilon; |
||
166 |
✗✓ | 43580 |
} else if (n == 2) { |
167 |
double x = hull.back()[0] - hull.front()[0]; |
||
168 |
double y = hull.back()[1] - hull.front()[1]; |
||
169 |
return sqrt(x * x + y * y) < epsilon; |
||
170 |
} |
||
171 |
|||
172 |
// loop through all edges of the polygon |
||
173 |
43580 |
CIT_Point current = hull.begin(); |
|
174 |
43580 |
CIT_Point next = current + 1; |
|
175 |
✓✓ | 518880 |
for (; next != hull.end(); ++current, ++next) { |
176 |
✓✗✓✗ ✓✗✓✓ |
475686 |
if (isLeft(*current, *next, aPoint) > 0) return false; |
177 |
} |
||
178 |
43194 |
return true; |
|
179 |
} |
||
180 |
|||
181 |
bool contains(T_Point points, CPointRef aPoint, const double epsilon) { |
||
182 |
T_Point hull = convexHull(points.begin(), points.end()); |
||
183 |
return containsHull(hull, aPoint, epsilon); |
||
184 |
} |
||
185 |
|||
186 |
Point lineSect(CPointRef p1, CPointRef p2, CPointRef p3, CPointRef p4) { |
||
187 |
Point res; |
||
188 |
double x1 = p1[0], x2 = p2[0], x3 = p3[0], x4 = p4[0]; |
||
189 |
double y1 = p1[1], y2 = p2[1], y3 = p3[1], y4 = p4[1]; |
||
190 |
|||
191 |
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); |
||
192 |
// If d is zero, there is no intersection |
||
193 |
// not supposed to happen |
||
194 |
// if (d == 0) throw; |
||
195 |
|||
196 |
// Get the x and y |
||
197 |
double pre = (x1 * y2 - y1 * x2), post = (x3 * y4 - y3 * x4); |
||
198 |
double x = (pre * (x3 - x4) - (x1 - x2) * post) / d; |
||
199 |
double y = (pre * (y3 - y4) - (y1 - y2) * post) / d; |
||
200 |
|||
201 |
// Check if the x and y coordinates are within both lines |
||
202 |
// not supposed to happen |
||
203 |
// if (x < min(x1, x2) || x > max(x1, x2) || |
||
204 |
// x < min(x3, x4) || x > max(x3, x4)) return NULL; |
||
205 |
// if (y < min(y1, y2) || y > max(y1, y2) || |
||
206 |
// y < min(y3, y4) || y > max(y3, y4)) return NULL; |
||
207 |
|||
208 |
// Return the point of intersection |
||
209 |
res[0] = x; |
||
210 |
res[1] = y; |
||
211 |
return res; |
||
212 |
} |
||
213 |
|||
214 |
4500 |
Point lineSect3D(CPointRef p1, CPointRef p2, CPointRef p3, CPointRef p4) { |
|
215 |
✓✗ | 4500 |
Point res; |
216 |
✓✗✓✗ ✓✗✓✗ |
4500 |
double x1 = p1[0], x2 = p2[0], x3 = p3[0], x4 = p4[0]; |
217 |
✓✗✓✗ ✓✗✓✗ |
4500 |
double y1 = p1[1], y2 = p2[1], y3 = p3[1], y4 = p4[1]; |
218 |
✓✗ | 4500 |
double z1 = p1[2]; |
219 |
✓✗✓✗ |
4500 |
Point u = p2 - p1; // vector director of the first line |
220 |
|||
221 |
4500 |
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); |
|
222 |
// If d is zero, there is no intersection |
||
223 |
// not supposed to happen |
||
224 |
// if (d == 0) throw; |
||
225 |
|||
226 |
// Get the x and y |
||
227 |
4500 |
double pre = (x1 * y2 - y1 * x2), post = (x3 * y4 - y3 * x4); |
|
228 |
4500 |
double x = (pre * (x3 - x4) - (x1 - x2) * post) / d; |
|
229 |
4500 |
double y = (pre * (y3 - y4) - (y1 - y2) * post) / d; |
|
230 |
|||
231 |
// Check if the x and y coordinates are within both lines |
||
232 |
// not supposed to happen |
||
233 |
// if (x < min(x1, x2) || x > max(x1, x2) || |
||
234 |
// x < min(x3, x4) || x > max(x3, x4)) return NULL; |
||
235 |
// if (y < min(y1, y2) || y > max(y1, y2) || |
||
236 |
// y < min(y3, y4) || y > max(y3, y4)) return NULL; |
||
237 |
|||
238 |
// Return the point of intersection |
||
239 |
✓✗ | 4500 |
res[0] = x; |
240 |
✓✗ | 4500 |
res[1] = y; |
241 |
// find the correct z coordinate : |
||
242 |
double t; |
||
243 |
✓✗✓✗ |
4500 |
if (u[0] != 0) |
244 |
✓✗ | 4500 |
t = (x - x1) / u[0]; |
245 |
else if (u[1] != 0) |
||
246 |
t = (y - y1) / u[1]; |
||
247 |
else { |
||
248 |
hppDout(notice, "in linesect there is no unique z value"); |
||
249 |
t = 1; |
||
250 |
} |
||
251 |
|||
252 |
✓✗✓✗ |
4500 |
res[2] = z1 + t * u[2]; |
253 |
|||
254 |
9000 |
return res; |
|
255 |
} |
||
256 |
|||
257 |
T_Point compute2DIntersection(CIT_Point subBegin, CIT_Point subEndHull, |
||
258 |
CIT_Point clipBegin, CIT_Point clipEndHull) { |
||
259 |
T_Point outputList, inputList; |
||
260 |
CIT_Point from = subBegin, to = subEndHull; |
||
261 |
for (CIT_Point edge = clipBegin; edge != clipEndHull - 1; ++edge) { |
||
262 |
CIT_Point E = from; |
||
263 |
double dirE, dirS = isLeft(*edge, *(edge + 1), *E); |
||
264 |
for (CIT_Point S = from + 1; S != to; ++E, ++S) { |
||
265 |
dirE = dirS; |
||
266 |
dirS = isLeft(*edge, *(edge + 1), *S); |
||
267 |
if (dirE < 0) { |
||
268 |
if (dirS < 0) |
||
269 |
outputList.insert(outputList.end(), *S); |
||
270 |
else |
||
271 |
outputList.insert(outputList.end(), |
||
272 |
lineSect(*S, *E, *edge, *(edge + 1))); |
||
273 |
} else if (dirS < 0) { |
||
274 |
outputList.insert(outputList.end(), |
||
275 |
lineSect(*S, *E, *edge, *(edge + 1))); |
||
276 |
outputList.insert(outputList.end(), *S); |
||
277 |
} |
||
278 |
} |
||
279 |
if (outputList.empty()) return outputList; |
||
280 |
inputList = outputList; |
||
281 |
if (inputList.size() > 3) |
||
282 |
inputList.insert(inputList.end(), *(inputList.begin())); |
||
283 |
from = inputList.begin(); |
||
284 |
to = inputList.end(); |
||
285 |
outputList.clear(); |
||
286 |
} |
||
287 |
return inputList; |
||
288 |
} |
||
289 |
|||
290 |
T_Point compute2DIntersection(T_Point subPolygon, T_Point clipPolygon) { |
||
291 |
T_Point outputList, inputList; |
||
292 |
double dirE, dirS; |
||
293 |
outputList = subPolygon; |
||
294 |
for (CIT_Point edge = clipPolygon.begin(); edge != clipPolygon.end() - 1; |
||
295 |
++edge) { |
||
296 |
inputList = outputList; |
||
297 |
outputList.clear(); |
||
298 |
CIT_Point s = inputList.end() - 1; |
||
299 |
dirS = isLeft(*edge, *(edge + 1), *s); |
||
300 |
for (CIT_Point e = inputList.begin(); e != inputList.end(); ++e) { |
||
301 |
dirE = isLeft(*edge, *(edge + 1), *e); |
||
302 |
if (dirE <= 0) // e is inside |
||
303 |
{ |
||
304 |
if (dirS > 0) // s not inside |
||
305 |
{ |
||
306 |
outputList.insert(outputList.end(), |
||
307 |
lineSect(*s, *e, *edge, *(edge + 1))); |
||
308 |
} |
||
309 |
outputList.insert(outputList.end(), *e); |
||
310 |
} else if (dirS <= 0) // s is inside |
||
311 |
{ |
||
312 |
outputList.insert(outputList.end(), |
||
313 |
lineSect(*s, *e, *edge, *(edge + 1))); |
||
314 |
} |
||
315 |
s = e; |
||
316 |
dirS = dirE; |
||
317 |
} |
||
318 |
} |
||
319 |
return outputList; |
||
320 |
} |
||
321 |
|||
322 |
43580 |
T_Point compute3DIntersection(T_Point subPolygon, T_Point clipPolygon) { |
|
323 |
87160 |
T_Point outputList, inputList; |
|
324 |
double dirE, dirS; |
||
325 |
✓✗ | 43580 |
outputList = subPolygon; |
326 |
✓✓ | 217900 |
for (CIT_Point edge = clipPolygon.begin(); edge != clipPolygon.end() - 1; |
327 |
174320 |
++edge) { |
|
328 |
✓✗ | 174320 |
inputList = outputList; |
329 |
174320 |
outputList.clear(); |
|
330 |
174320 |
CIT_Point s = inputList.end() - 1; |
|
331 |
✓✗✓✗ ✓✗✓✗ |
174320 |
dirS = isLeft(*edge, *(edge + 1), *s); |
332 |
✓✓ | 2265823 |
for (CIT_Point e = inputList.begin(); e != inputList.end(); ++e) { |
333 |
✓✗✓✗ ✓✗✓✗ |
2091503 |
dirE = isLeft(*edge, *(edge + 1), *e); |
334 |
✓✓ | 2091503 |
if (dirE <= 0) // e is inside |
335 |
{ |
||
336 |
✓✓ | 2085866 |
if (dirS > 0) // s not inside |
337 |
{ |
||
338 |
1263 |
outputList.insert(outputList.end(), |
|
339 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
2526 |
lineSect3D(*s, *e, *edge, *(edge + 1))); |
340 |
} |
||
341 |
✓✗ | 2085866 |
outputList.insert(outputList.end(), *e); |
342 |
✓✓ | 5637 |
} else if (dirS <= 0) // s is inside |
343 |
{ |
||
344 |
1263 |
outputList.insert(outputList.end(), |
|
345 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
2526 |
lineSect3D(*s, *e, *edge, *(edge + 1))); |
346 |
} |
||
347 |
2091503 |
s = e; |
|
348 |
2091503 |
dirS = dirE; |
|
349 |
} |
||
350 |
} |
||
351 |
43580 |
if (outputList.size() == 0) { |
|
352 |
hppDout(warning, "In computeIntersection3D : intersection is empty"); |
||
353 |
} |
||
354 |
✓✗ | 43580 |
outputList = convexHull(outputList.begin(), outputList.end()); |
355 |
/* |
||
356 |
std::ostringstream ss; |
||
357 |
ss<<"["; |
||
358 |
for(size_t i = 0; i < outputList.size() ; ++i){ |
||
359 |
ss<<"["<<outputList[i][0]<<","<<outputList[i][1]<<","<<outputList[i][2]<<"]"; |
||
360 |
if(i< (outputList.size() -1)) |
||
361 |
ss<<","; |
||
362 |
} |
||
363 |
ss<<"]"; |
||
364 |
hppDout(notice,"intersection3D = "<<ss.str()); |
||
365 |
*/ |
||
366 |
|||
367 |
87160 |
return outputList; |
|
368 |
} |
||
369 |
|||
370 |
double distanceToPlane(const fcl::Vec3f& n, double t, const fcl::Vec3f& v) { |
||
371 |
return n.dot(v) - t; |
||
372 |
} |
||
373 |
|||
374 |
double distanceToPlane(CPointRef point, CPointRef Pn, CPointRef P0) { |
||
375 |
Point v = point - P0; |
||
376 |
return fabs(v.dot(Pn)); |
||
377 |
} |
||
378 |
|||
379 |
43580 |
Point projectPointOnPlane(CPointRef point, CPointRef Pn, CPointRef P0) { |
|
380 |
✓✗✓✗ |
43580 |
Point v = (point - P0); |
381 |
✓✗ | 43580 |
double d = v.dot(Pn); |
382 |
// hppDout(notice,"project point on plane, signed distance = "<<d); |
||
383 |
✓✗✓✗ ✓✗ |
43580 |
Point proj = point - d * Pn; |
384 |
// hppDout(notice,"projected point from "<<point.transpose()<<" to |
||
385 |
// "<<proj.transpose()); |
||
386 |
87160 |
return proj; |
|
387 |
} |
||
388 |
|||
389 |
43580 |
double projectPointInsidePlan(T_Point plan, CPointRef point, CPointRef Pn, |
|
390 |
CPointRef P0, Eigen::Ref<Point> res) { |
||
391 |
// hppDout(notice,"project point "<<point.transpose()<<" inside plan, with |
||
392 |
// normal "<<Pn.transpose()<<" and point in plan : "<<P0.transpose()); |
||
393 |
// hppDout(notice,"number of points defining the plan : "<<plan.size()); |
||
394 |
✓✗ | 43580 |
Point proj_ortho = projectPointOnPlane(point, Pn, P0); |
395 |
✓✗✓✗ ✓✗✓✓ |
43580 |
if (containsHull(plan, proj_ortho, 1e-4)) { |
396 |
// hppDout(notice,"orthogonal projection is already inside the plan."); |
||
397 |
✓✗ | 43194 |
res = proj_ortho; |
398 |
✓✗✓✗ |
43194 |
return fabs((proj_ortho - point).norm()); |
399 |
} else { |
||
400 |
// hppDout(notice,"orthogonal projection is not inside the plan, compute the |
||
401 |
// closest point inside the plan :"); |
||
402 |
386 |
double d_min = std::numeric_limits<double>::max(); |
|
403 |
double d; |
||
404 |
✓✗ | 386 |
Point proj; |
405 |
✓✗ | 386 |
Point c = center(plan.begin(), plan.end()); |
406 |
// look for the intersection between the lines (proj_ortho -> center of the |
||
407 |
// intersection) and each edge of 'plan' return the intersection point which |
||
408 |
// lead to the smallest distance (original point -> intersection) plan is a |
||
409 |
// convexHull, the first point and the last points are equal so we don't |
||
410 |
// need specific case to handle the last point |
||
411 |
✓✓ | 2360 |
for (CIT_Point e = plan.begin(); e != plan.end() - 1; ++e) { |
412 |
✓✗✓✗ ✓✗✓✗ ✓✗ |
1974 |
proj = lineSect3D(proj_ortho, c, *e, *(e + 1)); |
413 |
✓✗✓✗ |
1974 |
d = fabs((proj - point).norm()); |
414 |
✓✓ | 1974 |
if (d < d_min) { |
415 |
923 |
d_min = d; |
|
416 |
✓✗ | 923 |
res = proj; |
417 |
} |
||
418 |
} |
||
419 |
// hppDout(notice,"new proj with min distance : "<<d_min<<" : |
||
420 |
// "<<res.transpose()); |
||
421 |
386 |
return d_min; |
|
422 |
} |
||
423 |
} |
||
424 |
|||
425 |
void computeTrianglePlaneDistance(fcl::Vec3f* tri_point, const fcl::Vec3f& n, |
||
426 |
double t, fcl::Vec3f* distance, |
||
427 |
unsigned int* num_penetrating_points) { |
||
428 |
*num_penetrating_points = 0; |
||
429 |
|||
430 |
for (unsigned int i = 0; i < 3; ++i) { |
||
431 |
(*distance)[i] = distanceToPlane(n, t, tri_point[i]); |
||
432 |
if ((*distance)[i] < EPSILON) { |
||
433 |
(*num_penetrating_points)++; |
||
434 |
} |
||
435 |
} |
||
436 |
} |
||
437 |
|||
438 |
bool insideTriangle(const fcl::Vec3f& a, const fcl::Vec3f& b, |
||
439 |
const fcl::Vec3f& c, const fcl::Vec3f& p) { |
||
440 |
fcl::Vec3f ab = b - a; |
||
441 |
fcl::Vec3f ac = c - a; |
||
442 |
fcl::Vec3f n = ab.cross(ac); |
||
443 |
|||
444 |
fcl::Vec3f pa = a - p; |
||
445 |
fcl::Vec3f pb = b - p; |
||
446 |
fcl::Vec3f pc = c - p; |
||
447 |
|||
448 |
if ((pb.cross(pc)).dot(n) < -EPSILON) return false; |
||
449 |
if ((pc.cross(pa)).dot(n) < -EPSILON) return false; |
||
450 |
if ((pa.cross(pb)).dot(n) < -EPSILON) return false; |
||
451 |
|||
452 |
return true; |
||
453 |
} |
||
454 |
|||
455 |
void intersect3DGeoms(BVHModelOBConst_Ptr_t model1, |
||
456 |
BVHModelOBConst_Ptr_t model2, |
||
457 |
fcl::CollisionResult result) { |
||
458 |
std::ostringstream ss7; |
||
459 |
ss7 << "["; |
||
460 |
|||
461 |
for (size_t c = 0; c < result.numContacts(); ++c) { |
||
462 |
int i = result.getContact(c).b1; // triangle index |
||
463 |
int j = result.getContact(c).b2; |
||
464 |
|||
465 |
fcl::Vec3f tri[3] = {model1->vertices[model1->tri_indices[i][0]], |
||
466 |
model1->vertices[model1->tri_indices[i][1]], |
||
467 |
model1->vertices[model1->tri_indices[i][2]]}; |
||
468 |
fcl::Vec3f tri2[3] = {model2->vertices[model2->tri_indices[j][0]], |
||
469 |
model2->vertices[model2->tri_indices[j][1]], |
||
470 |
model2->vertices[model2->tri_indices[j][2]]}; |
||
471 |
|||
472 |
intersectTriangles(tri, tri2, &ss7); |
||
473 |
intersectTriangles(tri2, tri, &ss7); |
||
474 |
|||
475 |
} // for each contact point |
||
476 |
// hppDout(notice,"clipped point : "); |
||
477 |
ss7 << "]"; |
||
478 |
// std::cout<<ss7.str()<<std::endl; |
||
479 |
} |
||
480 |
|||
481 |
T_Point intersectTriangles(fcl::Vec3f* tri, fcl::Vec3f* tri2, |
||
482 |
std::ostringstream* ss) { |
||
483 |
T_Point res; |
||
484 |
|||
485 |
fcl::Vec3f n2 = (tri2[1] - tri2[0]).cross(tri2[2] - tri2[0]).normalized(); |
||
486 |
fcl::FCL_REAL t2 = n2.dot(tri2[0]); |
||
487 |
|||
488 |
fcl::Vec3f distance; |
||
489 |
unsigned int num_penetrating_points = 0; |
||
490 |
|||
491 |
geom::computeTrianglePlaneDistance(tri, n2, t2, &distance, |
||
492 |
&num_penetrating_points); |
||
493 |
/* |
||
494 |
hppDout(notice,"Intersection between triangles : "); |
||
495 |
hppDout(notice,"[["<<tri[0][0]<<","<<tri[0][1]<<","<<tri[0][2]<<"],["<<tri[1][0]<<","<<tri[1][1]<<","<<tri[1][2]<<"],["<<tri[2][0]<<","<<tri[2][1]<<","<<tri[2][2]<<"],["<<tri[0][0]<<","<<tri[0][1]<<","<<tri[0][2]<<"]]"); |
||
496 |
hppDout(notice,"[["<<tri2[0][0]<<","<<tri2[0][1]<<","<<tri2[0][2]<<"],["<<tri2[1][0]<<","<<tri2[1][1]<<","<<tri2[1][2]<<"],["<<tri2[2][0]<<","<<tri2[2][1]<<","<<tri2[2][2]<<"],["<<tri2[0][0]<<","<<tri2[0][1]<<","<<tri2[0][2]<<"]]"); |
||
497 |
*/ |
||
498 |
if (num_penetrating_points > 2) { |
||
499 |
hppDout(error, |
||
500 |
"triangle in the wrong side of the plane"); // shouldn't happen |
||
501 |
return res; |
||
502 |
} |
||
503 |
if (num_penetrating_points == 2) |
||
504 |
distance = |
||
505 |
-distance; // like this we always work with the same case for later |
||
506 |
// computation (one point of the triangle inside the plan) |
||
507 |
|||
508 |
// distance have one and only one negative distance, we want to separate them |
||
509 |
double dneg = 0; |
||
510 |
fcl::Vec3f pneg; |
||
511 |
fcl::Vec3f ppos[2]; |
||
512 |
double dpos[2]; |
||
513 |
int numPos = 0; |
||
514 |
for (int k = 0; k < 3; ++k) { |
||
515 |
if (distance[k] < 0) { |
||
516 |
dneg = distance[k]; |
||
517 |
pneg = tri[k]; |
||
518 |
} else { |
||
519 |
dpos[numPos] = distance[k]; |
||
520 |
ppos[numPos] = tri[k]; |
||
521 |
numPos++; |
||
522 |
} |
||
523 |
} |
||
524 |
// TODO case : intersection with vertice : only 1 intersection point |
||
525 |
// compute the first intersection point |
||
526 |
double s1 = dneg / (dneg - dpos[0]); |
||
527 |
fcl::Vec3f i1 = pneg + (ppos[0] - pneg) * s1; |
||
528 |
// compute the second intersection point |
||
529 |
double s2 = dneg / (dneg - dpos[1]); |
||
530 |
fcl::Vec3f i2 = pneg + (ppos[1] - pneg) * s2; |
||
531 |
if (geom::insideTriangle(tri2[0], tri2[1], tri2[2], i1)) { |
||
532 |
res.push_back(Eigen::Vector3d(i1[0], i1[1], i1[2])); |
||
533 |
// hppDout(notice,"first intersection : |
||
534 |
// "<<"["<<i1[0]<<","<<i1[1]<<","<<i1[2]<<"]"); |
||
535 |
if (ss) *ss << "[" << i1[0] << "," << i1[1] << "," << i1[2] << "],"; |
||
536 |
} |
||
537 |
if (geom::insideTriangle(tri2[0], tri2[1], tri2[2], i2)) { |
||
538 |
res.push_back(Eigen::Vector3d(i2[0], i2[1], i2[2])); |
||
539 |
// hppDout(notice,"second intersection : |
||
540 |
// "<<"["<<i2[0]<<","<<i2[1]<<","<<i2[2]<<"]"); |
||
541 |
if (ss) *ss << "[" << i2[0] << "," << i2[1] << "," << i2[2] << "],"; |
||
542 |
} |
||
543 |
return res; |
||
544 |
} |
||
545 |
/* |
||
546 |
T_Point intersectPolygonePlane(BVHModelOBConst_Ptr_t polygone, |
||
547 |
BVHModelOBConst_Ptr_t model2, fcl::Vec3f n , double t, fcl::CollisionResult |
||
548 |
result, bool useT, double epsilon){ T_Point res,triRes,sortedRes; |
||
549 |
std::ostringstream ss; ss<<"["; |
||
550 |
|||
551 |
|||
552 |
for(size_t c = 0 ; c < result.numContacts() ; ++c){ |
||
553 |
// hppDout(info,"normal = "<<result.getContact(c).normal); |
||
554 |
if(result.getContact(c).normal.equal(-n,epsilon)){ // only compute |
||
555 |
intersection for contact with the plane |
||
556 |
// need the -n because .normal are oriented from o1 to o2 |
||
557 |
int i = result.getContact(c).b1; // triangle index |
||
558 |
int j = result.getContact(c).b2; |
||
559 |
|||
560 |
|||
561 |
fcl::Vec3f tri[3] = |
||
562 |
{polygone->vertices[polygone->tri_indices[i][0]],polygone->vertices[polygone->tri_indices[i][1]],polygone->vertices[polygone->tri_indices[i][2]]}; |
||
563 |
fcl::Vec3f tri2[3] = |
||
564 |
{model2->vertices[model2->tri_indices[j][0]],model2->vertices[model2->tri_indices[j][1]],model2->vertices[model2->tri_indices[j][2]]}; |
||
565 |
fcl::Vec3f n2=0; |
||
566 |
fcl::FCL_REAL t2=0; |
||
567 |
fcl::Intersect::buildTrianglePlane(tri2[0],tri2[1],tri2[2], &n2, &t2); |
||
568 |
// hppDout(info,"n = "<<n2); |
||
569 |
// hppDout(info,"t = "<<t2); |
||
570 |
if(n2.equal(n,epsilon) && ((!useT) ||((t2 + EPSILON >= t ) && (t2-EPSILON |
||
571 |
<= t )))){ triRes = intersectTriangles(tri,tri2); |
||
572 |
res.insert(res.end(),triRes.begin(),triRes.end()); |
||
573 |
triRes = intersectTriangles(tri2,tri); |
||
574 |
res.insert(res.end(),triRes.begin(),triRes.end()); |
||
575 |
|||
576 |
|||
577 |
} |
||
578 |
} |
||
579 |
|||
580 |
} // for each contact point |
||
581 |
if(res.empty()){ |
||
582 |
hppDout(notice,"~ Intersection between polygon and plane is empty"); |
||
583 |
std::cout<<"~ Intersection between polygon and plane is empty"<<std::endl; |
||
584 |
return res; |
||
585 |
} |
||
586 |
sortedRes = convexHull(res.begin(),res.end()); |
||
587 |
hppDout(notice,"clipped point : "); |
||
588 |
for(size_t i = 0; i < sortedRes.size() ; ++i){ |
||
589 |
ss<<"["<<sortedRes[i][0]<<","<<sortedRes[i][1]<<","<<sortedRes[i][2]<<"]"; |
||
590 |
if(i< (sortedRes.size() -1)) |
||
591 |
ss<<","; |
||
592 |
} |
||
593 |
ss<<"]"; |
||
594 |
std::cout<<"intersection : "<<std::endl; |
||
595 |
std::cout<<ss.str()<<std::endl; |
||
596 |
hppDout(notice,"area = "<<area(sortedRes.begin(),sortedRes.end())); |
||
597 |
return sortedRes; |
||
598 |
} |
||
599 |
*/ |
||
600 |
|||
601 |
// cf http://geomalgorithms.com/a05-_intersect-1.html |
||
602 |
3538398 |
T_Point intersectSegmentPlane(Point s0, Point s1, Eigen::Vector3d pn, |
|
603 |
Point p0) { |
||
604 |
3538398 |
T_Point res; |
|
605 |
✓✗✓✗ |
3538398 |
Point u = s1 - s0; |
606 |
✓✗✓✗ |
3538398 |
Point w = s0 - p0; |
607 |
|||
608 |
✓✗ | 3538398 |
double d = pn.dot(u); |
609 |
✓✗ | 3538398 |
double n = -pn.dot(w); |
610 |
|||
611 |
✓✓ | 3538398 |
if (fabs(d) < EPSILON) { // segment parrallel to plane |
612 |
✗✓ | 24 |
if (fabs(n) < EPSILON) { // segment in plane |
613 |
res.insert(res.end(), s0); |
||
614 |
res.insert(res.end(), s1); |
||
615 |
return res; |
||
616 |
} else |
||
617 |
24 |
return res; // no intersection |
|
618 |
} |
||
619 |
// there ONE intersection point : |
||
620 |
3538374 |
double di = n / d; |
|
621 |
✓✓✓✓ |
3538374 |
if (di < 0 || di > 1) return res; // unknow error ? |
622 |
|||
623 |
✓✗✓✗ ✓✗ |
1002080 |
Point si = s0 + di * u; |
624 |
✓✗ | 1002080 |
res.insert(res.end(), si); |
625 |
1002080 |
return res; |
|
626 |
} |
||
627 |
|||
628 |
43580 |
T_Point intersectPolygonePlane(BVHModelOBConst_Ptr_t polygone, |
|
629 |
BVHModelOBConst_Ptr_t plane, |
||
630 |
Eigen::Ref<Point> Pn) { |
||
631 |
87160 |
T_Point res, sortedRes; |
|
632 |
87160 |
T_Point intersection; |
|
633 |
// compute plane equation (normal, point inside the plan) |
||
634 |
✓✗ | 43580 |
Point P0; |
635 |
✓✗✓✗ ✓✗ |
43580 |
computePlanEquation(plane, Pn, P0); |
636 |
✓✓ | 1223046 |
for (int i = 0; i < polygone->num_tris; |
637 |
i++) { // FIXME : can test 2 times the same line (in both triangles), |
||
638 |
// avoid this ? |
||
639 |
// hppDout(info,"triangle : "<<i); |
||
640 |
✓✓ | 4717864 |
for (int j = 0; j < 3; j++) { |
641 |
// hppDout(info,"couple : "<<j); |
||
642 |
✓✗✓✗ ✓✗ |
10615194 |
intersection = intersectSegmentPlane( |
643 |
✓✗ | 3538398 |
polygone->vertices[polygone->tri_indices[i][j]], |
644 |
polygone |
||
645 |
✓✓✓✗ |
3538398 |
->vertices[polygone->tri_indices[i][((j == 2) ? 0 : (j + 1))]], |
646 |
3538398 |
Pn, P0); |
|
647 |
✓✓ | 3538398 |
if (intersection.size() > 0) |
648 |
✓✗ | 1002080 |
res.insert(res.end(), intersection.begin(), intersection.end()); |
649 |
} |
||
650 |
} |
||
651 |
|||
652 |
// ordonate the point in the vector (clockwise) first point and last point are |
||
653 |
// the same |
||
654 |
✗✓ | 43580 |
if (res.size() == 0) return res; |
655 |
✓✗ | 43580 |
sortedRes = convexHull(res.begin(), res.end()); |
656 |
/* hppDout(notice,"clipped point : "); |
||
657 |
std::ostringstream ss; |
||
658 |
ss<<"["; |
||
659 |
for(size_t i = 0; i < sortedRes.size() ; ++i){ |
||
660 |
ss<<"["<<sortedRes[i][0]<<","<<sortedRes[i][1]<<","<<sortedRes[i][2]<<"]"; |
||
661 |
if(i< (sortedRes.size() -1)) |
||
662 |
ss<<","; |
||
663 |
} |
||
664 |
ss<<"]"; |
||
665 |
hppDout(notice,"intersection = "<<ss.str()); |
||
666 |
*/ |
||
667 |
// std::cout<<"intersection : "<<std::endl; |
||
668 |
// std::cout<<ss.str()<<std::endl; |
||
669 |
43580 |
return sortedRes; |
|
670 |
} |
||
671 |
|||
672 |
43580 |
T_Point convertBVH(BVHModelOBConst_Ptr_t obj) { |
|
673 |
43580 |
T_Point result; |
|
674 |
✓✓ | 217900 |
for (int i = 0; i < obj->num_vertices; ++i) { |
675 |
✓✗✓✗ ✓✗✓✗ |
174320 |
result.push_back(Eigen::Vector3d(obj->vertices[i][0], obj->vertices[i][1], |
676 |
✓✗ | 174320 |
obj->vertices[i][2])); |
677 |
} |
||
678 |
|||
679 |
✓✗ | 87160 |
return convexHull(result.begin(), result.end()); |
680 |
} |
||
681 |
|||
682 |
43580 |
void computePlanEquation(BVHModelOBConst_Ptr_t plane, Eigen::Ref<Point> Pn, |
|
683 |
Eigen::Ref<Point> P0) { |
||
684 |
✓✗ | 43580 |
TrianglePoints triPlane; |
685 |
triPlane.p1 = |
||
686 |
plane |
||
687 |
✓✗ | 43580 |
->vertices[plane->tri_indices[0][0]]; // FIXME : always use the first |
688 |
// triangle, is it an issue ? |
||
689 |
✓✗ | 43580 |
triPlane.p2 = plane->vertices[plane->tri_indices[0][1]]; |
690 |
✓✗ | 43580 |
triPlane.p3 = plane->vertices[plane->tri_indices[0][2]]; |
691 |
✓✗✓✗ |
43580 |
Pn = TriangleNormal(triPlane); |
692 |
✓✗ | 43580 |
P0 = triPlane.p1; // FIXME : better point ? |
693 |
43580 |
} |
|
694 |
|||
695 |
} // namespace geom |
Generated by: GCOVR (Version 4.2) |