Moka libraries
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
corefine-3d-tools.cc
Go to the documentation of this file.
1 /*
2  * lib-corefinement : Opérations de corafinement.
3  * Copyright (C) 2004, Moka Team, Université de Poitiers, Laboratoire SIC
4  * http://www.sic.sp2mi.univ-poitiers.fr/
5  * Copyright (C) 2009, Guillaume Damiand, CNRS, LIRIS,
6  * guillaume.damiand@liris.cnrs.fr, http://liris.cnrs.fr/
7  *
8  * This file is part of lib-corefinement
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "corefine-3d-tools.hh"
25 
26 // #define DEBUG_MESSAGES
27 #include "message-macros.hh"
28 
29 using namespace std;
30 using namespace GMap3d;
31 
32 //******************************************************************************
33 
34 #define a0 FMap->alpha0
35 #define a1 FMap->alpha1
36 #define a2 FMap->alpha2
37 #define a3 FMap->alpha3
38 
39 #define VTX(d) (AVertexDI < 0 ? FMap->findVertex(d) : \
40  (CAttributeVertex*)FMap->getDirectInfo(d, AVertexDI))
41 
42 //******************************************************************************
43 
44 CCorefine3dTools::CCorefine3dTools(CGMapVertex * AMap,
45  TCoordinate AEpsilon)
46  : CCorefine2dTools(AMap, AEpsilon)
47 {
48 }
49 
50 //******************************************************************************
51 
52 bool CCorefine3dTools::isVectorInSector(const CVertex & AVector,
53  const CVertex & ASectorVector1,
54  const CVertex & ASectorVector2,
55  const CPlane & APlane,
56  bool AThickVector1,
57  bool AThickVector2)
58 {
59  TCoordinate pv = (ASectorVector1 * ASectorVector2).dot(APlane.getNormal());
60  TCoordinate pv1 = (ASectorVector1 * AVector).dot(APlane.getNormal());
61  TCoordinate pv2 = (ASectorVector2 * AVector).dot(APlane.getNormal());
62  bool result = pv < 0.0 ? pv1 >= 0.0 || pv2 <= 0.0 : pv1 >= 0.0 && pv2 <= 0.0;
63 
64  if (!result && AThickVector1 && pv1 >= -FEps &&
65  AVector.dot(ASectorVector1) > 0.0) result = true;
66  if (!result && AThickVector2 && pv2 <= FEps &&
67  AVector.dot(ASectorVector2) > 0.0) result = true;
68 
69  return result;
70 }
71 
72 //******************************************************************************
73 
74 bool CCorefine3dTools::isVectorInSector(const CVertex & AVector,
75  CDart * ASector,
76  const CPlane & APlane,
77  bool ATestBorders,
78  int AVertexDI)
79 {
80  CVertex pt = *VTX(ASector);
81 
82  if (a2(ASector) != a1(ASector))
83  if (!ATestBorders)
84  return isVectorInSector(AVector,
85  *VTX(a0(ASector)) - pt,
86  *VTX(a0(a1(ASector))) - pt,
87  APlane);
88  else
89  return (isVectorInSector(AVector,
90  *VTX(a0(ASector)) - pt,
91  *VTX(a0(a1(ASector))) - pt,
92  APlane) ||
93  isPointOnLine(*VTX(a0(ASector)), pt,
94  pt + AVector) ||
95  isPointOnLine(*VTX(a0(a1(ASector))), pt,
96  pt + AVector));
97  else
98  return true;
99 }
100 
101 //******************************************************************************
102 
103 bool CCorefine3dTools::areVectorsColinear(const CVertex & AVector1,
104  const CVertex & AVector2)
105 {
106  return CGeneralTools::areVectorsColinear(AVector1, AVector2);
107 }
108 
109 //******************************************************************************
110 
111 TCoordinate CCorefine3dTools::pointParameterOnLine(const CVertex & APoint,
112  const CVertex & ALineVertex1,
113  const CVertex & ALineVertex2)
114 {
115  return CGeneralTools::pointParameterOnLine(APoint, ALineVertex1,
116  ALineVertex2);
117 }
118 
119 //******************************************************************************
120 
121 CDart * CCorefine3dTools::findSectorOfVector(const CVertex & AVector,
122  CDart * AVertex,
123  const CPlane & APlane,
124  int AVertexDI)
125 {
126  CDart *d = AVertex;
127  CDart *best = NULL;
128 
129  do {
130  if (isVectorInSector(AVector, d, APlane, false, AVertexDI))
131  best = d;
132 
133  d = a2(a1(d));
134  }
135  while (d != AVertex && best == NULL);
136 
137  if (best == NULL || !FMap->isSameOrbit(best, AVertex, ORBIT_01)) {
138  best = AVertex;
139  WARN_BB("<findSectorOfVector> Aucun secteur valide sur la face !");
140  }
141 
142  return best;
143 }
144 
145 //******************************************************************************
146 
147 bool CCorefine3dTools::areFacesCoplanar(const CVertex & AVertex1,
148  const CPlane & APlane1,
149  const CVertex & AVertex2,
150  const CPlane & APlane2)
151 {
152  CVertex normal1 = APlane1.getNormal();
153  CVertex normal2 = APlane2.getNormal();
154 
155  normal1 = normalizeVector(normal1);
156  normal2 = normalizeVector(normal2);
157 
158  return (isVectorNull(normal1 * normal2) &&
159  isPointOnPlane(AVertex2, APlane1) &&
160  isPointOnPlane(AVertex1, APlane2));
161 }
162 
163 //******************************************************************************
164 
165 CDart * CCorefine3dTools::findWellOrientedDart(CDart * AVertex, int AVertexDI)
166 {
167  TCoordinate n1[4], n2[4];
168  volumeNormalVector(AVertex, n1, AVertexDI);
169  volumeNormalVector(a3(AVertex), n2, AVertexDI);
170 
171  if ((n1[3] < 0.0 && n2[3] < 0.0) ||
172  (n1[3] > 0.0 && n2[3] > 0.0)) {
173  /* Nous sommes ici dans le cas où un des deux volume est un volume
174  * extérieur et nous devons donc comparer la taille des deux volumes.
175  */
176  CBoundingBox bb1, bb2;
177 
178  bb1 = orbitBoundingBox(AVertex, ORBIT_VOLUME, AVertexDI);
179  bb2 = orbitBoundingBox(a3(AVertex), ORBIT_VOLUME, AVertexDI);
180 
181  if (bb1.getSurface() <= bb2.getSurface()) {
182  // AVertex n'est pas le volume extérieur, sa normale doit donc être > 0
183  if (n1[3] < 0.0) {
184  AVertex = a1(AVertex);
185  }
186  }
187  else {
188  // AVertex est le volume extérieur, sa normale doit donc être < 0
189  if (n1[3] > 0.0) {
190  AVertex = a1(AVertex);
191  }
192  }
193  }
194  else if (n1[3] < 0.0) {
195  AVertex = a1(AVertex);
196  }
197 
198  return AVertex;
199 }
200 
201 //******************************************************************************
202 
205  const CVertex & ALinePoint2,
206  const CVertex & AEdgePoint1,
207  const CVertex & AEdgePoint2,
208  TCoordinate * ALineParam,
209  TCoordinate * AEdgeParam)
210 {
211  assert(AEdgeParam != NULL && ALineParam != NULL);
212 
213  if (localizePointOnEdge(AEdgePoint2, ALinePoint1,
214  ALinePoint2, ALineParam) != EP_OutOfEdge) {
215 
216  *AEdgeParam = 1.0;
217  return EP_OnSecondVertex;
218  }
219 
220  if (localizePointOnEdge(AEdgePoint1, ALinePoint1,
221  ALinePoint2, ALineParam) != EP_OutOfEdge) {
222  *AEdgeParam = 0.0;
223  return EP_OnFirstVertex;
224  }
225 
226  CPlane plane;
227 
228  if (sqrt(squareDistanceBetweenLines(ALinePoint1, ALinePoint2,
229  AEdgePoint1, AEdgePoint2, &plane)) > FEps)
230  return EP_OutOfEdge;
231 
232  if (isVectorNull(plane.getNormal()))
233  return EP_OutOfEdge;
234 
235  if (!getLinesIntersection(ALinePoint1, ALinePoint2, AEdgePoint1, AEdgePoint2,
236  ALineParam, AEdgeParam, plane))
237  return EP_OutOfEdge;
238 
239  if (*AEdgeParam >= 0.0 && *AEdgeParam <= 1.0)
240  return EP_OnEdge;
241 
242  return EP_OutOfEdge;
243 }
244 
245 //******************************************************************************
246 
249  CVertex AEdgePoint2,
250  const CPlane & APlane,
251  TCoordinate * AEdgeParam)
252 {
253  assert(AEdgeParam != NULL);
254 
255  CVertex v = AEdgePoint2 - AEdgePoint1;
256 
257  if (isPointOnPlane(AEdgePoint2, APlane)) {
258  *AEdgeParam = 1.0;
259  return EP_OnSecondVertex;
260  }
261 
262  if (isPointOnPlane(AEdgePoint1, APlane)) {
263  *AEdgeParam = 0.0;
264  return EP_OnFirstVertex;
265  }
266 
267  if (!APlane.getLineIntersection(AEdgePoint1, v, AEdgeParam))
268  return EP_OutOfEdge;
269 
270 // if (*AEdgeParam >= 0.0 && *AEdgeParam <= 1.0 &&
271 // isPointInFace(AFace, AEdgePoint1 + *AEdgeParam * v, &plane))
272 // return EP_OnEdge;
273 
274  if (*AEdgeParam >= 0.0 && *AEdgeParam <= 1.0)
275  return EP_OnEdge;
276 
277  return EP_OutOfEdge;
278 }
279 
280 //******************************************************************************
281 
284  const CVertex & ADirection,
285  CDart * AFace,
286  const CPlane & APlane,
287  bool AExcludeOrigin,
288  int AVertexDI)
289 {
290  ENTER;
291 
292  TProjection proj = APlane.getBestProjection();
293 
294  CVertex projOrigin = APlane.projectPoint(AOrigin, proj);
295  CVertex projDirection = APlane.projectPoint(ADirection, proj);
296 
297  CDart *d = AFace;
298  CEdgeIntersection inter;
299  TPositionOnEdge pos;
300  int edge_mark = FMap->getNewMark();
301  TCoordinate t1 = 0.0, t2 = 0.0;
302  CVertex pt1, pt2, pt3;
303  CVertex extremity = projOrigin + projDirection;
304 
305  if (projOrigin != extremity) {
306  MSG("Parcours des sommets de la face");
307  do {
308  pt1 = APlane.projectPoint(*VTX(d), proj);
309 
310  if (CCorefine2dTools::isPointOnLine(pt1, projOrigin, extremity)) {
311  if (!AExcludeOrigin || !arePointsEqual(projOrigin, pt1)) {
312  t1 = CCorefine2dTools::pointParameterOnLine(pt1, projOrigin,
313  extremity);
314 
315  if (t1 >= 0.0 && (t1 <= inter.getParameter() ||
316  inter.getCell() == NULL)) {
317  inter.setCell(d);
318  inter.setCellDimension(0);
319  inter.setPosition(EP_OnEdge);
320  inter.setParameter(t1);
321  inter.setPoint(*VTX(d));
322 
323  MSG("une intersection trouvée :" << endl << inter);
324  }
325  }
326 
327  // Marquage des arêtes adjacentes pour ne pas les tester
328  FMap->setMark(d, edge_mark);
329  FMap->setMark(a0(d), edge_mark);
330  FMap->setMark(a1(d), edge_mark);
331  FMap->setMark(a0(a1(d)), edge_mark);
332  }
333 
334  d = a1(a0(d));
335  }
336  while (d != AFace);
337 
338  MSG("Parcours des arêtes de la face");
339  do {
340  pt1 = APlane.projectPoint(*VTX(d), proj);
341  pt2 = APlane.projectPoint(*VTX(a0(d)), proj);
342 
343  if (FMap->isMarked(d, edge_mark)) {
344  FMap->unsetMark(d, edge_mark);
345  FMap->unsetMark(a0(d), edge_mark);
346  }
347  else if (fabs((pt2 - pt1).norm()) > FEps / 2.0 &&
348  (!AExcludeOrigin ||
349  !CCorefine2dTools::isPointOnLine(projOrigin, pt1, pt2))) {
350  pos = CCorefine2dTools::localizeEdgesIntersection(projOrigin, extremity,
351  pt1, pt2, &t1, &t2);
352 
353 // pt3 = pt1 + t2 * (pt2 - pt1);
354 
355  if (pos != EP_OutOfEdge &&
356 // !arePointsEqual(projOrigin, pt3) &&
357  t1 >= 0.0 && (t1 <= inter.getParameter() ||
358  inter.getCell() == NULL)) {
359  inter.setCell(d);
360  inter.setCellDimension(1);
361  inter.setPosition(EP_OnEdge);
362  inter.setParameter(t1);
363  inter.setPoint(*VTX(d) + t2 * (*VTX(a0(d)) - *VTX(d)));
364 
365  MSG("une intersection trouvée :" << endl << inter);
366  }
367  }
368 
369  d = a1(a0(d));
370  }
371  while (d != AFace);
372 
373 // if (inter.getCell() != NULL)
374 // inter.setPoint(AOrigin + inter.getParameter() * ADirection);
375  }
376 
377  FMap->freeMark(edge_mark);
378 
379  EXIT;
380 
381  return inter;
382 }
383 
384 //******************************************************************************
385 
388  const CVertex & ADirection,
389  CDart * AFace,
390  const CPlane & AFacePlane,
391  const CPlane & ACutPlane,
392  bool AExcludeOrigin,
393  int AVertexDI)
394 {
395  DEBUG_FUNCTION;
396 
397  CDart *d = AFace;
398  CEdgeIntersection inter;
399  TCoordinate dist, t;
400  CVertex pt1, pt2, pt3, dir, extremity = AOrigin + ADirection;
401 
402  int pos_mark = FMap->getNewMark();
403  int neg_mark = FMap->getNewMark();
404  int face_mark = FMap->getNewMark();
405 
406  FMap->markOrbit(AFace, ORBIT_01, face_mark);
407 
408  MSG("Parcours des sommets de la face");
409  do {
410  pt1 = *VTX(d);
411  MSG("sommet testé : " << pt1);
412  dist = ACutPlane.pointDistance(pt1);
413  if (dist < -FEps) {
414  MSG("le sommet se trouve du côté négatif");
415  for (CDynamicCoverageVertex dcv(FMap, d); dcv.cont(); ++dcv)
416  if (FMap->isMarked(*dcv, face_mark)) FMap->setMark(*dcv, neg_mark);
417  }
418  else if (dist > FEps) {
419  MSG("le sommet se trouve du côté positif");
420  for (CDynamicCoverageVertex dcv(FMap, d); dcv.cont(); ++dcv)
421  if (FMap->isMarked(*dcv, face_mark)) FMap->setMark(*dcv, pos_mark);
422  }
423  else if (!AExcludeOrigin || !arePointsEqual(pt1, AOrigin)) {
424  t = pointParameterOnLine(pt1, AOrigin, extremity);
425  if (t >= 0.0 && (t <= inter.getParameter() || !inter.getCell())) {
426  MSG("le sommet se trouve sur la ligne de coupe");
427  inter.setCell(d);
428  inter.setCellDimension(0);
429  inter.setPosition(EP_OnEdge);
430  inter.setParameter(t);
431  inter.setPoint(pt1);
432  }
433  }
434  d = FMap->alpha01(d);
435  }
436  while (d != AFace);
437 
438  MSG("Parcours des arêtes de la face");
439  do {
440  pt1 = *VTX(d);
441  pt2 = *VTX(a0(d));
442  MSG("arête testée : [" << pt1 << ";" << pt2 << "]");
443  dir = pt2 - pt1;
444  if ((FMap->isMarked(d, pos_mark) && FMap->isMarked(a0(d), neg_mark)) ||
445  (FMap->isMarked(d, neg_mark) && FMap->isMarked(a0(d), pos_mark))) {
446  if (!AExcludeOrigin ||
447  !(abs(CPlane(AFacePlane.getNormal() * (pt2-pt1), pt1).
448  pointDistance(AOrigin)) <= FEps)) {
449  if (ACutPlane.getLineIntersection(pt1, dir, &t)) {
450  assert(t > 0.0 && t < 1.0);
451  pt3 = pt1 + dir * t;
452  t = pointParameterOnLine(pt3, AOrigin, extremity);
453  if (t >= 0.0 && (t <= inter.getParameter() || !inter.getCell())) {
454  MSG("la ligne de coupe intersecte l'arête en " << pt3);
455  inter.setCell(d);
456  inter.setCellDimension(1);
457  inter.setPosition(EP_OnEdge);
458  inter.setParameter(t);
459  inter.setPoint(pt3);
460  }
461  }
462  else
463  assert(false);
464  }
465  }
466  FMap->unsetMark(d, face_mark);
467  FMap->unsetMark(a0(d), face_mark);
468  for (CDynamicCoverageEdge dce(FMap, d); dce.cont(); ++dce) {
469  FMap->unsetMark(*dce, pos_mark);
470  FMap->unsetMark(*dce, neg_mark);
471  }
472  d = FMap->alpha01(d);
473  }
474  while (d != AFace);
475 
476 // assert(FMap->isWholeMapUnmarked(pos_mark));
477 // assert(FMap->isWholeMapUnmarked(neg_mark));
478 // assert(FMap->isWholeMapUnmarked(face_mark));
479  FMap->freeMark(pos_mark);
480  FMap->freeMark(neg_mark);
481  FMap->freeMark(face_mark);
482 
483  return inter;
484 }
485 
486 //******************************************************************************
487 
490  const CVertex & ADirection,
491  CDart * ADart, TOrbit AOrbit,
492  int AVertexDI)
493 {
494  CEdgeIntersection inter;
495  TCoordinate t1 = 0.0, t2 = 0.0;
496  CVertex *pt1, *pt2, pt, extremity = AOrigin + ADirection;
497  CPlane plane;
498  CDart *face;
499  int mark = FMap->getNewMark();
500  int edge_mark = FMap->getNewMark();
501  int face_mark = FMap->getNewMark();
502  int orient_mark = FMap->getNewMark();
503 
504  TOrbit orbit_vertex = AND_ORBIT(ORBIT_VERTEX, AOrbit);
505  TOrbit orbit_edge = AND_ORBIT(ORBIT_EDGE, AOrbit);
506  TOrbit orbit_face = AND_ORBIT(ORBIT_FACE, AOrbit);
507 
508  CCoverage *cov = FMap->getDynamicCoverage(ADart, AOrbit);
509  CCoverage *dcf, *tmp_cov;
510 
511  FMap->halfMarkOrbit(ADart, AOrbit, orient_mark);
512 
513  inter.setCell(NULL);
514 
515  // Recherche d'une éventuelle intersection avec les sommets
516  for (cov->reinit(); cov->cont(); ++(*cov)) {
517  dcf = FMap->getDynamicCoverage(**cov, orbit_face);
518 
519  for (; dcf->cont(); ++(*dcf)) {
520  if (!FMap->isMarked(**dcf, mark) && FMap->isMarked(**dcf, orient_mark)) {
521  // Marquage du sommet comme traité
522  FMap->markOrbit(**dcf, orbit_vertex, mark);
523 
524  pt = *VTX(**dcf);
525 
526  if (isPointOnLine(pt, AOrigin, extremity)) {
527  t2 = pointParameterOnLine(pt, AOrigin, extremity);
528 
529  if (t2 > 0.0) {
530  if (t2 < inter.getParameter() || inter.getCell() == NULL) {
531  inter.setCell(**dcf);
532  inter.setCellDimension(0);
533  inter.setPoint(pt);
534  inter.setParameter(t2);
535  }
536 
537  tmp_cov = FMap->getDynamicCoverage(**dcf, orbit_vertex);
538 
539  for (; tmp_cov->cont(); ++(*tmp_cov)) {
540  // Marquage des arêtes incidentes pour ne pas les tester
541  if (!FMap->isMarked(**tmp_cov, edge_mark))
542  FMap->markOrbit(**tmp_cov, orbit_edge, edge_mark);
543 
544  // Marquage des faces incidentes pour ne pas les tester
545  if (!FMap->isMarked(**tmp_cov, face_mark))
546  FMap->markOrbit(**tmp_cov, orbit_face, face_mark);
547  }
548 
549  delete tmp_cov;
550  }
551  }
552  }
553  }
554 
555  delete dcf;
556  }
557 
558  // Recherche d'une éventuelle intersection avec les arêtes
559  for (cov->reinit(); cov->cont(); ++(*cov)) {
560  dcf = FMap->getDynamicCoverage(**cov, orbit_face);
561 
562  for (; dcf->cont(); ++(*dcf)) {
563  if (FMap->isMarked(**dcf, edge_mark)) {
564  FMap->unmarkOrbit(**dcf, orbit_edge, edge_mark);
565  FMap->unmarkOrbit(**dcf, orbit_edge, mark);
566  }
567  else if (FMap->isMarked(**dcf, mark) &&
568  FMap->isMarked(**dcf, orient_mark)) {
569  FMap->unmarkOrbit(**dcf, orbit_edge, mark);
570 
571  pt1 = VTX(**dcf);
572  pt2 = VTX(a0(**dcf));
573 
574  if (sqrt(squareDistanceBetweenLines(*pt1, *pt2, AOrigin, extremity,
575  &plane)) <= FEps) {
576 
577  if (!isVectorNull(plane.getNormal()) &&
578  getLinesIntersection(*pt1, *pt2, AOrigin, extremity,
579  &t1, &t2, plane)) {
580 
581  pt = AOrigin + t2 * ADirection;
582 
583  if (t1 >= 0.0 && t1 <= 1.0 && t2 > 0) {
584  if (t2 < inter.getParameter() || inter.getCell() == NULL) {
585  inter.setCell(**dcf);
586  inter.setCellDimension(1);
587  inter.setPoint(pt);
588  inter.setParameter(t2);
589  }
590 
591  tmp_cov = FMap->getDynamicCoverage(**dcf, orbit_edge);
592 
593  for (; tmp_cov->cont(); ++(*tmp_cov)) {
594  // Marquage des faces incidentes pour ne pas les tester
595  if (!FMap->isMarked(**tmp_cov, face_mark))
596  FMap->markOrbit(**tmp_cov, orbit_face, face_mark);
597  }
598 
599  delete tmp_cov;
600  }
601  }
602  }
603  }
604  }
605 
606  delete dcf;
607  }
608 
609  // Recherche d'une éventuelle intersection avec les faces
610  for (cov->reinit(); cov->cont(); ++(*cov)) {
611  if (FMap->isMarked(**cov, face_mark)) {
612  FMap->unmarkOrbit(**cov, orbit_face, face_mark);
613  FMap->markOrbit(**cov, orbit_face, mark);
614  }
615  else if (!FMap->isMarked(**cov, mark)) {
616  face = (FMap->isMarked(**cov, orient_mark)) ? **cov : a3(**cov);
617  FMap->markOrbit(face, orbit_face, mark);
618 
619  plane = facePlane(face, AVertexDI);
620 
621  if (plane.getLineIntersection(AOrigin, ADirection, &t2)) {
622  if (t2 > 0.0 &&
623  (t2 < inter.getParameter() || inter.getCell() == NULL)) {
624  pt = AOrigin + t2 * ADirection;
625 
626  if (isPointInFace(pt, face, &plane, AVertexDI)) {
627  inter.setCell(face);
628  inter.setCellDimension(2);
629  inter.setPoint(pt);
630  inter.setParameter(t2);
631  }
632  }
633  }
634  }
635  }
636 
637  for (cov->reinit(); cov->cont(); ++(*cov)) {
638  FMap->unsetMark(**cov, mark);
639  FMap->unsetMark(**cov, orient_mark);
640  }
641 
642  delete cov;
643 
644  FMap->freeMark(mark);
645  FMap->freeMark(edge_mark);
646  FMap->freeMark(face_mark);
647  FMap->freeMark(orient_mark);
648 
649  return inter;
650 }
651 
652 //******************************************************************************
653 
654 bool CCorefine3dTools::isPointInFace(const CVertex & APoint, CDart * AFace,
655  const CPlane * APlane, int AVertexDI)
656 {
657  bool result;
658  CPlane plane;
659 
660  if (APlane == NULL)
661  plane = facePlane(AFace, AVertexDI);
662  else
663  plane = *APlane;
664 
665  if (APoint == *VTX(AFace))
666  result = true;
667  else {
668  CVertex direction = *VTX(AFace) - APoint;
669  CEdgeIntersection inter;
670 
671  inter = findNearestIntersectionInFace(APoint, direction, AFace, plane,
672  false, AVertexDI);
673 
674  if (inter.getCell() == NULL) {
675  result = false;
676  }
677  else {
678  if (inter.getCellDimension() == 0) {
679  result = isVectorInSector(-direction, inter.getCell(), plane, false,
680  AVertexDI);
681  }
682  else {
683  CVertex v = edgeVector(inter.getCell(), AVertexDI);
684  result = (plane.getNormal() * v).dot(direction) < 0.0;
685  }
686  }
687  }
688 
689  return result;
690 }
691 
692 //******************************************************************************
693 #define LINK(d1, d2) (FMap->setDirectInfo(d1, ALinkDirectInfo, d2), \
694  FMap->setDirectInfo(d2, ALinkDirectInfo, d1), \
695  FMap->setDirectInfo(a0(d1), ALinkDirectInfo, a0(d2)), \
696  FMap->setDirectInfo(a0(d2), ALinkDirectInfo, a0(d1)))
697 
698 #define UNLINK(d) (FMap->setDirectInfo(d, ALinkDirectInfo, NULL), \
699  FMap->setDirectInfo(a0(d), ALinkDirectInfo, NULL))
700 
701 #define ALPHA2(d) ((FMap->getDirectInfo(d, ALinkDirectInfo) != NULL) ? \
702  (CDart*)FMap->getDirectInfo(d, ALinkDirectInfo) : \
703  alpha2(d))
704 
706  CDart * AEdge2,
707  int ALinkDirectInfo,
708  int AVertexDI)
709 {
710  CPlane plane(edgeVector(AEdge1, AVertexDI), *VTX(AEdge1));
711 
712  CDart *d1, *d2;
713  CVertex v, v1, v2;
714  CDart *best, *tmp1, *tmp2;
715 
716  d1 = AEdge1;
717  do {
718  v = faceNormalVector(d1, AVertexDI);
719 
720  best = NULL;
721  d2 = AEdge2;
722  v2 = faceNormalVector(d2, AVertexDI);
723  do {
724  tmp2 = a3(alpha2(d2));
725 
726  v1 = v2;
727  v2 = faceNormalVector(tmp2, AVertexDI);
728 
729  if (isVectorInSector(v, v1, v2, plane))
730  best = d2;
731 
732  d2 = tmp2;
733  }
734  while (d2 != AEdge2 && best == NULL);
735 
736  if (best == NULL) {
737  WARN_BB("<sortFacesAroundEdges_Naive> Aucun secteur trouvé !");
738  d2 = AEdge2;
739  }
740  else
741  d2 = best;
742 
743  // Liaison avec la face précédente
744  tmp1 = alpha2(d1);
745  if (FMap->getDirectInfo(tmp1, ALinkDirectInfo) == d2) {
746  UNLINK(tmp1);
747  UNLINK(d2);
748  }
749  if (FMap->getDirectInfo(d2, ALinkDirectInfo) == NULL)
750  LINK(d2, a3(d1));
751 
752  // Liaison avec la face suivante
753  tmp1 = alpha2(a3(d1));
754  tmp2 = alpha2(d2);
755  if (FMap->getDirectInfo(tmp1, ALinkDirectInfo) == tmp2) {
756  UNLINK(tmp1);
757  UNLINK(tmp2);
758  }
759  if (FMap->getDirectInfo(tmp2, ALinkDirectInfo) == NULL)
760  LINK(d1, tmp2);
761 
762  d1 = a3(alpha2(d1));
763  }
764  while (d1 != AEdge1);
765 }
766 
767 //******************************************************************************
768 
770  CDart * AEdge2,
771  int ALinkDirectInfo,
772  int AVertexDI)
773 {
774  CPlane plane(edgeVector(AEdge1, AVertexDI), *VTX(AEdge1));
775 
776  CDart *d1, *d2;
777  CVertex v, v1, v2;
778  CDart *best, *tmp;
779  int mark = FMap->getNewMark();
780 
781  for (CDynamicCoverageEdge dce1(FMap, AEdge1); dce1.cont(); dce1++)
782  FMap->setDirectInfo(*dce1, ALinkDirectInfo, NULL);
783  for (CDynamicCoverageEdge dce2(FMap, AEdge2); dce2.cont(); dce2++)
784  FMap->setDirectInfo(*dce2, ALinkDirectInfo, NULL);
785 
786  d1 = AEdge1;
787  d2 = AEdge2;
788  do {
789  v = faceNormalVector(d1, AVertexDI);
790 
791  best = NULL;
792  v2 = faceNormalVector(d2, AVertexDI);
793  do {
794  FMap->setMark(d2, mark);
795 
796 // tmp = a3(alpha2(d2));
797  tmp = a3(ALPHA2(d2));
798 
799  v1 = v2;
800  v2 = faceNormalVector(tmp, AVertexDI);
801 
802  if (isVectorInSector(v, v1, v2, plane))
803  best = d2;
804 
805  d2 = tmp;
806  }
807  while (best == NULL && !FMap->isMarked(d2, mark));
808 
809  FMap->unmarkOrbit(AEdge1, ORBIT_23, mark);
810  FMap->unmarkOrbit(AEdge2, ORBIT_23, mark);
811 
812  if (best == NULL) {
813  WARN_BB("<sortFacesAroundEdges_NaiveBis> Aucun secteur trouvé !");
814  d2 = AEdge2;
815  }
816  else
817  d2 = best;
818 
819 // if (isVectorInSector(calculateFaceNormal(d2), getAlpha2(a3(d1)), plane)) {
820 // if (FMap->getDirectInfo(d2, ALinkDirectInfo) != NULL)
821 // UNLINK((Dart*)FMap->getDirectInfo(d2, ALinkDirectInfo));
822 // LINK(d2, a3(d1));
823 // }
824 
825 // tmp = getAlpha2(d2);
826 // if (isVectorInSector(calculateFaceNormal(a3(tmp)), d1, plane)) {
827 // if (FMap->getDirectInfo(tmp, ALinkDirectInfo) != NULL)
828 // UNLINK((Dart*)FMap->getDirectInfo(tmp, ALinkDirectInfo));
829 // LINK(d1, tmp);
830 // }
831 
832  if (FMap->getDirectInfo(d2, ALinkDirectInfo) != NULL) {
833  tmp = (CDart*)FMap->getDirectInfo(d2, ALinkDirectInfo);
834  UNLINK(tmp);
835  UNLINK(d2);
836  }
837  else
838  tmp = alpha2(d2);
839 
840  LINK(d2, a3(d1));
841  LINK(d1, tmp);
842 
843  d1 = a3(alpha2(d1));
844  }
845  while (d1 != AEdge1);
846 
847  FMap->freeMark(mark);
848 }
849 
850 //******************************************************************************
851 
853  CDart * AEdge2,
854  int ALinkDirectInfo,
855  int AVertexDI)
856 {
857  int mark = FMap->getNewMark();
858 
859  CPlane plane(edgeVector(AEdge1, AVertexDI), *VTX(AEdge1));
860 
861  CDart *d = AEdge1;
862  CVertex v = faceNormalVector(d, AVertexDI);
863 
864  CDart *tmp = a3(alpha2(AEdge2));
865  CVertex v1 = faceNormalVector(AEdge2, AVertexDI);
866  CVertex v2 = faceNormalVector(tmp, AVertexDI);
867 
868 // cout << endl << "Arête : [" << *VTX(AEdge1) << ","
869 // << *VTX(a0(AEdge1)) << "]" << endl;
870 
871  while (!isVectorInSector(v, v1, v2, plane)) {
872 // cout << v << endl << v1 << endl << v2 << endl;
873  v1 = v2;
874  AEdge2 = tmp;
875 
876  tmp = a3(alpha2(AEdge2));
877  v2 = faceNormalVector(tmp, AVertexDI);
878  }
879 
880  CDart *d1 = a3(alpha2(AEdge1));
881  CDart *d2 = a3(alpha2(AEdge2));
882 
883  v1 = faceNormalVector(d1, AVertexDI);
884  v2 = faceNormalVector(d2, AVertexDI);
885 
886  do {
887  FMap->setMark(d, mark);
888 
889  if (areVectorsColinear(v1, v2)) {
890  if (!FMap->isMarked(d2, mark)) {
891  LINK(d, a3(d2));
892  FMap->setMark(d2, mark);
893  d = d2;
894  }
895 
896  LINK(d, a3(d1));
897 
898  d = d1;
899  v = v1;
900 
901  d1 = a3(alpha2(d1));
902  d2 = a3(alpha2(d2));
903 
904  v1 = faceNormalVector(d1, AVertexDI);
905  v2 = faceNormalVector(d2, AVertexDI);
906  }
907  else if (isVectorInSector(v2, v, v1, plane)) { // v2 est entre v et v1
908  LINK(d, a3(d2));
909 
910  d = d2;
911  v = v2;
912 
913  d2 = a3(alpha2(d2));
914  v2 = faceNormalVector(d2, AVertexDI);
915  }
916  else { // v1 est entre v et v2
917  LINK(d, a3(d1));
918 
919  d = d1;
920  v = v1;
921 
922  d1 = a3(alpha2(d1));
923  v1 = faceNormalVector(d1, AVertexDI);
924  }
925  }
926  while (!FMap->isMarked(d, mark));
927 
928  bool problem = false;
929 
930  // Démarquage des brins de la deuxième arête
931  d2 = AEdge2;
932  do {
933  if (FMap->isMarked(d2, mark))
934  FMap->unsetMark(d2, mark);
935  else {
936  WARN_BR("<sortFacesAroundEdges> Brin de la deuxième arête non marqué !");
937  problem = true;
938  }
939 
940  d2 = a3(alpha2(d2));
941  }
942  while (d2 != AEdge2);
943 
944  // Démarquage des brins de la première arête
945  d1 = AEdge1;
946  do {
947  if (FMap->isMarked(d1, mark))
948  FMap->unsetMark(d1, mark);
949  else {
950  WARN_BR("<sortFacesAroundEdges> Brin de la première arête non marqué !");
951  problem = true;
952  }
953 
954  d1 = a3(alpha2(d1));
955  }
956  while (d1 != AEdge1);
957 
958  FMap->freeMark(mark);
959 
960  if (problem) {
961  d1 = AEdge1;
962  do {
963  FMap->setDirectInfo(d1, ALinkDirectInfo, NULL);
964  d1 = a3(alpha2(d1));
965  }
966  while (d1 != AEdge1);
967 
968  d2 = AEdge2;
969  do {
970  FMap->setDirectInfo(d2, ALinkDirectInfo, NULL);
971  d2 = a3(alpha2(d2));
972  }
973  while (d2 != AEdge2);
974  }
975 
976  return !problem;
977 }
978 
979 //******************************************************************************
980 
982 {
983 public:
984  CFaceComparator(CCorefine3dTools & ATools, const CVertex & AAxis,
985  int AVertexDI = -1)
986  : FTools(ATools), FAxis(AAxis), FVertexDI(AVertexDI) {}
987 
988  bool operator () (CDart * AFace1, CDart * AFace2)
989  {
990  CVertex v1 = FTools.faceNormalVector(AFace1, FVertexDI);
991  CVertex v2 = FTools.faceNormalVector(AFace2, FVertexDI);
992  return (v1 * v2).dot(FAxis) > 0.0;
993  }
994 
995 private:
996  CCorefine3dTools & FTools;
997  CVertex FAxis;
998  int FVertexDI;
999 };
1000 
1001 //******************************************************************************
1002 
1004  CDart * AEdge2,
1005  int ALinkDirectInfo,
1006  int AVertexDI)
1007 {
1008  CDart *d1, *d2;
1009  CVertex axis = edgeVector(AEdge1, AVertexDI);
1010  CFaceComparator comp(*this, axis, AVertexDI);
1011  multiset<CDart*, CFaceComparator> faces(comp);
1012  multiset<CDart*, CFaceComparator>::iterator it, tmp_it;
1013 
1014  for (CDynamicCoverageEdge dce1(FMap, AEdge1); dce1.cont(); ++dce1)
1015  FMap->setDirectInfo(*dce1, ALinkDirectInfo, NULL);
1016  for (CDynamicCoverageEdge dce2(FMap, AEdge2); dce2.cont(); ++dce2)
1017  FMap->setDirectInfo(*dce2, ALinkDirectInfo, NULL);
1018 
1019  d1 = AEdge1;
1020  do {
1021  faces.insert(d1);
1022  d1 = a3(alpha2(d1));
1023  }
1024  while (d1 != AEdge1);
1025 
1026  d2 = AEdge2;
1027  do {
1028  faces.insert(d2);
1029  d2 = a3(alpha2(d2));
1030  }
1031  while (d2 != AEdge2);
1032 
1033  for (it = faces.begin(); it != faces.end(); ) {
1034  tmp_it = it++;
1035 
1036  d1 = *tmp_it;
1037  d2 = (it != faces.end()) ? *it : *faces.begin();
1038 
1039  LINK(d1, a3(d2));
1040  }
1041 }
1042 
1043 #undef LINK
1044 #undef UNLINK
1045 #undef ALPHA2
1046 //******************************************************************************
1047 
1048 TCoordinate CCorefine3dTools::matrixDet(TCoordinate AMat[3][3])
1049 {
1050  return (AMat[0][0] * (AMat[1][1] * AMat[2][2] - AMat[2][1] * AMat[1][2]) -
1051  AMat[0][1] * (AMat[1][0] * AMat[2][2] - AMat[2][0] * AMat[1][2]) -
1052  AMat[0][2] * (AMat[1][0] * AMat[2][1] - AMat[2][0] * AMat[1][1]));
1053 }
1054 
1055 //******************************************************************************
1056 
1057 void CCorefine3dTools::vectProduct4d(const CVertex & AV1,
1058  const CVertex & AV2,
1059  const CVertex & AV3,
1060  TCoordinate ANormal[4])
1061 {
1062  TCoordinate mat[3][3];
1063 
1064 // mat[0][0] = AV1.getY();
1065 // mat[0][1] = AV1.getZ();
1066 // mat[0][2] = 0;
1067 
1068 // mat[1][0] = AV2.getY();
1069 // mat[1][1] = AV2.getZ();
1070 // mat[1][2] = 0;
1071 
1072 // mat[2][0] = AV3.getY();
1073 // mat[2][1] = AV3.getZ();
1074 // mat[2][2] = 0;
1075 
1076 // ANormal[0] = matrixDet(mat);
1077 
1078 // mat[0][0] = AV1.getX();
1079 // mat[0][1] = AV1.getZ();
1080 // mat[0][2] = 0;
1081 
1082 // mat[1][0] = AV2.getX();
1083 // mat[1][1] = AV2.getZ();
1084 // mat[1][2] = 0;
1085 
1086 // mat[2][0] = AV3.getX();
1087 // mat[2][1] = AV3.getZ();
1088 // mat[2][2] = 0;
1089 
1090 // ANormal[1] = matrixDet(mat);
1091 
1092 // mat[0][0] = AV1.getX();
1093 // mat[0][1] = AV1.getY();
1094 // mat[0][2] = 0;
1095 
1096 // mat[1][0] = AV2.getX();
1097 // mat[1][1] = AV2.getY();
1098 // mat[1][2] = 0;
1099 
1100 // mat[2][0] = AV3.getX();
1101 // mat[2][1] = AV3.getY();
1102 // mat[2][2] = 0;
1103 
1104 // ANormal[2] = matrixDet(mat);
1105 
1106  mat[0][0] = AV1.getX();
1107  mat[0][1] = AV1.getY();
1108  mat[0][2] = AV1.getZ();
1109 
1110  mat[1][0] = AV2.getX();
1111  mat[1][1] = AV2.getY();
1112  mat[1][2] = AV2.getZ();
1113 
1114  mat[2][0] = AV3.getX();
1115  mat[2][1] = AV3.getY();
1116  mat[2][2] = AV3.getZ();
1117 
1118  ANormal[3] = matrixDet(mat);
1119 }
1120 
1121 //******************************************************************************
1122 
1124  TCoordinate ANormal[4],
1125  int AVertexDI)
1126 {
1127  int orient_mark = FMap->getNewMark();
1128  CVertex v1, v2, v3;
1129  TCoordinate tmp[4];
1130 
1131  ANormal[0] = ANormal[1] = ANormal[2] = ANormal[3] = 0.0;
1132 
1133  FMap->halfMarkOrbit(AVolume, ORBIT_VOLUME, orient_mark);
1134 
1135  for (CDynamicCoverageVolume dcv(FMap, AVolume); dcv.cont(); dcv++) {
1136  if (FMap->isMarked(*dcv, orient_mark)) {
1137  FMap->unsetMark(*dcv, orient_mark);
1138 
1139  if (!FMap->isFree2(*dcv)) {
1140  v1 = edgeVector(a1(a2(*dcv)), AVertexDI);
1141  v2 = edgeVector(*dcv, AVertexDI);
1142  v3 = edgeVector(a1(*dcv), AVertexDI);
1143 
1144  vectProduct4d(v1, v2, v3, tmp);
1145 
1146 // for (int i = 0; i < 4; i++)
1147 // ANormal[i] += tmp[i];
1148  ANormal[3] += tmp[3];
1149  }
1150  }
1151  }
1152 
1153  FMap->freeMark(orient_mark);
1154 }
1155 
1156 //******************************************************************************
1157