GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/utils/algorithms.cc Lines: 169 358 47.2 %
Date: 2024-02-02 12:21:48 Branches: 203 800 25.4 %

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