Moka kernel
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gmv-extrusion.cc
Go to the documentation of this file.
1 /*
2  * lib-gmapkernel : Un noyau de 3-G-cartes et des opérations.
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-gmapkernel
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 //******************************************************************************
25 #include "g-map-vertex.hh"
26 #include "geometry.hh"
27 using namespace GMap3d;
28 //******************************************************************************
30  bool AExtrusionWithAdjacentSews,
31  TCoordinate AExtrusionCoef,
32  int AMarkToExtrude, int AMarkExtruded)
33 {
34  assert(canExtrudeCell(ADart, ADim));
35 
36  TOrbit orbitPieceOfVertex = AND_ORBIT(ORBIT_VERTEX, ORBIT_INF[ADim]);
37  CVertex normal = AExtrusionCoef * faceNormalVector(ADart);
38 
39  // Topologie:
41  AExtrusionWithAdjacentSews,
42  AMarkToExtrude,
43  AMarkExtruded);
44 
45  // Affectation des plongements:
46  int treated = getNewMark();
47 
48  CCoverage * cov1 = getDynamicCoverage(ADart , ORBIT_INF[ADim]);
49  CCoverage * cov2 = getDynamicCoverage(newDart, ORBIT_INF[ADim]);
50 
51  for (; cov1->cont(); ++(*cov1), ++(*cov2))
52  if (!isMarked(**cov1, treated))
53  {
54  markOrbit(**cov1, orbitPieceOfVertex, treated);
55 
56  if (findVertex(**cov2)==NULL)
57  {
58  CVertex vector;
59 
60  if (AExtrusionWithAdjacentSews && ADim==2)
61  vector = AExtrusionCoef *
62  regionNormalVector(**cov1, 0, AMarkToExtrude);
63  else
64  vector = normal;
65 
66  setVertex(**cov2, *findVertex(**cov1) + vector);
67  }
68  }
69 
70  delete cov1;
71  delete cov2;
72 
73  unmarkOrbit(ADart, ORBIT_INF[ADim], treated);
74  freeMark(treated);
75 
76  return newDart;
77 }
78 //******************************************************************************
79 // Méthode protégée !
81  int AMarkNumberSrce,
82  int AMarkNumberDest)
83 {
84  halfMarkIncidentCells(ORBIT_INF[ADim], AMarkNumberSrce, AMarkNumberDest);
85 
86  // Désélection des cellules sélectionnées des deux côtés:
87  if (ADim>0)
88  {
89  int treated = getNewMark();
90 
91  for (CDynamicCoverageAll it(this); it.cont(); ++it)
92  if (!isMarked(*it, treated))
93  {
94  if (isMarked(*it, AMarkNumberDest) && !isFree0(*it) &&
95  isMarked(alpha0(*it), AMarkNumberDest))
96  {
97  markOrbit(*it, ORBIT_INF[ADim], treated);
98  unmarkOrbit(*it, ORBIT_INF[ADim], AMarkNumberDest);
99  }
100  else
101  setMark(*it, treated);
102  }
103 
104  negateMaskMark(treated);
105  freeMark(treated);
106  }
107 }
108 //******************************************************************************
110  int ADim,
111  CDart* APath,
112  bool AExtrusionWithAdjacentSews,
113  bool ARotateExtrudedCells,
114  bool AScaleExtrudedCells,
115  CDart* APonderationPath,
116  int AMarkExtruded,
117  int ADirectInfoIndex)
118 {
119  assert(canExtrudeByPath(ADart, ADim, APath));
120  assert(APonderationPath==NULL || !isClosedPolyline(APonderationPath));
121 
122  int treated = getNewMark();
123 
124  bool change =
125  !canExtrudeHalfCell(ADart, ADim) &&
126  (isFree0(APath) || isFree1(APath) || isFree0(alpha1(APath)));
127 
128  // Topologie:
129  CDart* returned =
130  CGMapGeneric::extrudeByPath(ADart, ADim, APath,
131  AExtrusionWithAdjacentSews,
132  AMarkExtruded, ADirectInfoIndex);
133 
134  CDart* current = change ? alpha(ADart, ADim+1) : ADart;
135 
136  // Calcul des coefficients de pondération:
137  int pathNbVertices = getNbPolylineVertices(APath);
138  int pathInitialPos = 0;
139 
140  if (!isClosedPolyline(APath))
141  {
142  CDart* current = APath;
143 
144  while (!isFree1(current) && !isFree0(alpha1(current)))
145  {
146  current = alpha10(current);
147  ++pathInitialPos;
148  }
149  }
150 
151  TCoordinate * pathCoefs = new TCoordinate[pathNbVertices];
152 
153  if (APonderationPath!=NULL)
154  {
155  int ponderationNbVertices = getNbPolylineVertices(APonderationPath);
156 
157  // On se place au début du chemin:
158  while (!isFree1(APonderationPath) && !isFree0(alpha1(APonderationPath)))
159  APonderationPath = alpha10(APonderationPath);
160 
161  TCoordinate * ponderationCoefs = new TCoordinate[ponderationNbVertices];
162 
163  // Récupération des ordonnées:
164  {
165  int i = 0;
166  for (CDynamicCoverage01 cov(this, APonderationPath); cov.cont(); ++cov)
167  if (!isMarked(*cov, treated))
168  {
169  ponderationCoefs[i++] = findVertex(*cov)->getY();
170  markOrbit(*cov, ORBIT_1, treated);
171  }
172 
173  assert(i==ponderationNbVertices);
174  unmarkOrbit(APonderationPath, ORBIT_01, treated);
175  }
176 
177  // Interpolation:
178  for (int pathI=0; pathI<pathNbVertices; ++pathI)
179  if (ponderationNbVertices==1)
180  pathCoefs[pathI] = ponderationCoefs[0];
181  else
182  {
183  float t = ((float) pathI*ponderationNbVertices)/pathNbVertices;
184 
185  int i = (int) t;
186 
187  pathCoefs[pathI] = ponderationCoefs[i];
188 
189  if (!isZero(t-i))
190  pathCoefs[pathI] +=
191  (t-i)*(ponderationCoefs[i+1]-ponderationCoefs[i]);
192  }
193 
194  delete [] ponderationCoefs;
195  }
196 
197  // Affectation des plongements:
198  CDynamicCoverage01 path(this, APath);
199 
200  // On se place sur l'extrémité de la première arête:
201  if (isFree0(*path))
202  ++path;
203 
204  if (path.cont())
205  ++path;
206 
207  int pathIndex = pathInitialPos;
208  int pathDirection = +1;
209 
210  while (path.cont())
211  {
212  current = ADim==1 ? alpha1012(current) : alpha210123(current);
213 
214  // Pour chaque arête du chemin:
215  if (alpha1(*path)!=APath)
216  {
217  assert(!isFree0(*path));
218 
219  // Calcul de la matrice de transformation:
220  CVertex & vertex1 = * findVertex(alpha0(*path));
221  CVertex & vertex2 = * findVertex(*path);
222 
223  CVertex vertex0, vertex3 ;
224 
225  if (isFree1(alpha0(*path)) || isFree0(alpha01(*path)))
226  vertex0 = vertex1 - (vertex2 - vertex1);
227  else
228  vertex0 = * findVertex(alpha010(*path));
229 
230  if (isFree1(*path) || isFree0(alpha1(*path)))
231  vertex3 = vertex2 + (vertex2 - vertex1);
232  else
233  vertex3 = * findVertex(alpha10(*path));
234 
235  CVertex vector0 = vertex1 - vertex0;
236  CVertex vector1 = vertex2 - vertex1;
237  CVertex vector2 = vertex3 - vertex2;
238 
239  CVertex axis0 = vector0 * vector1;
240  CVertex axis1 = vector1 * vector2;
241 
242  if (axis0.isNull()) axis0 = OZ;
243  if (axis1.isNull()) axis1 = OZ;
244 
245  TCoordinate angle0 = CGeometry::getAngle(vector0, vector1);
246  TCoordinate angle1 = CGeometry::getAngle(vector1, vector2);
247 
248  CTransformationMatrix matrix;
249 
250  if (AScaleExtrudedCells)
251  {
252  TCoordinate cos0 = dCos(angle0/2);
253 
254  if (isZero(cos0))
255  cos0 = 1;
256 
257  matrix.axialScale(vertex1, axis0, cos0);
258  }
259 
260  if (ARotateExtrudedCells)
261  matrix.rotate(vertex1, axis0, angle0/2);
262 
263  matrix.translate(vector1);
264 
265  if (ARotateExtrudedCells)
266  matrix.rotate(vertex2, axis1, angle1/2);
267 
268  if (AScaleExtrudedCells)
269  {
270  TCoordinate cos1 = dCos(angle1/2);
271 
272  if (isZero(cos1))
273  cos1 = 1;
274 
275  matrix.axialScale(vertex2, axis1, 1/cos1);
276  }
277 
278  // Pondération du rayon de la section:
279  if (APonderationPath!=NULL)
280  {
281  TCoordinate coef = 1;
282 
283  if (!isZero(pathCoefs[pathIndex]))
284  coef /= pathCoefs[pathIndex];
285 
286  pathIndex += pathDirection;
287  coef *= pathCoefs[pathIndex];
288  matrix.scale(vertex2, coef);
289  }
290 
291  // Utilisation de cette matrice pour plonger les sommets de la face:
292  CCoverage * cov = getDynamicCoverage(current, ORBIT_INF[ADim]);
293 
294  for (; cov->cont(); ++(*cov))
295  if (!isMarked(**cov, treated))
296  {
297  markOrbit(**cov, AND_ORBIT(ORBIT_VERTEX, ORBIT_INF[ADim]),
298  treated);
299 
300  if (findVertex(**cov)==NULL)
301  {
302  CVertex result;
303  CDart* prev =
304  ADim==1 ? alpha2101(**cov) : alpha321012(**cov);
305 
306  matrix.applyOn(* findVertex(prev), result);
307 
308  setVertex(**cov, result);
309  }
310  }
311 
312  delete cov;
313 
314  unmarkOrbit(current, ORBIT_INF[ADim], treated);
315  }
316 
317  // Passage à l'arête suivante du chemin:
318  ++path; if (!path.cont()) break;
319 
320  if (isFree0(*path))
321  { ++path; if (!path.cont()) break; }
322 
323  if (path.prevOperationType()==OP_JUMP)
324  {
325  current = alpha(ADart, ADim+1);
326 
327  pathIndex = pathInitialPos;
328  pathDirection = - pathDirection;
329  }
330 
331  ++path;
332  }
333 
334  freeMark(treated);
335  delete [] pathCoefs;
336 
337  return returned;
338 }
339 //******************************************************************************
340 int CGMapVertex::extrudeByPathMarkedCells(int AMarkNumber, int ADim,
341  CDart* APath,
342  bool AExtrusionWithAdjacentSews,
343  int AInitialTranslateExtrudedCells,
344  int AInitialRotateExtrudedCells,
345  bool ARotateExtrudedCells,
346  bool AScaleExtrudedCells,
347  CDart* APonderationPath)
348 {
349  assert(APath!=NULL);
350  assert(1<=ADim && ADim<=2);
351  assert(0<=AInitialTranslateExtrudedCells
352  && AInitialTranslateExtrudedCells<=2);
353  assert(0<=AInitialRotateExtrudedCells
354  && AInitialRotateExtrudedCells<=2);
355 
356 
357  CVertex pathOrigin , pathDirection ;
358  CVertex cellsOrigin, cellsDirection;
359 
360  int treated = getNewMark();
361  int toExtrude = getNewMark();
362  int nbExtruded = 0;
363 
364  if (isFree0(APath))
365  {
366  if (isFree1(APath))
367  return 0;
368 
369  APath = alpha1(APath);
370  }
371 
372  CDynamicCoverageAll it(this);
373 
374  // Repérage des cellules qui peuvent être extrudées:
375  if (AInitialRotateExtrudedCells==0)
376  markIncidentCells(ORBIT_INF[ADim], AMarkNumber, toExtrude);
377  else
378  {
379  halfMarkIncidentCells(ORBIT_INF[ADim], AMarkNumber, toExtrude);
380 
381  for (it.reinit(); it.cont(); ++it)
382  if (!isMarked(*it, treated))
383  {
384  if (isMarked(*it, toExtrude) && !isFree0(*it) &&
385  isMarked(alpha0(*it), toExtrude))
386  {
387  markOrbit(*it, ORBIT_INF[ADim], treated);
388  unmarkOrbit(*it, ORBIT_INF[ADim], toExtrude);
389  }
390  else
391  setMark(*it, treated);
392  }
393 
394  negateMaskMark(treated);
395  }
396 
397  for (it.reinit(); it.cont(); ++it)
398  if (!isMarked(*it, treated))
399  {
400  if (isMarked(*it, toExtrude))
401  {
402  markOrbit(*it, ORBIT_CELL[ADim], treated);
403 
404  if (!canExtrudeByPath(*it, ADim, APath))
405  unmarkOrbit(*it, ORBIT_CELL[ADim], toExtrude);
406  }
407  else
408  setMark(*it, treated);
409  }
410 
411  negateMaskMark(treated);
412 
413  // Calcul des positions initiales du chemin et des cellules:
414  if (AInitialTranslateExtrudedCells!=0 || AInitialRotateExtrudedCells!=0)
415  {
416  // Barycentres:
417  pathOrigin = *findVertex(APath);
418 
419  markIncidentCells(ORBIT_CELL[ADim], toExtrude, treated);
420  cellsOrigin = barycenter(treated);
421  unmarkAll(treated);
422 
423  // Vecteurs directeurs:
424  if (AInitialRotateExtrudedCells!=0)
425  {
426  // Vecteur directeur du chemin:
427  CVertex vector1 = * findVertex(alpha0(APath)) - pathOrigin;
428 
429  if (vector1.isNull())
430  vector1 = OZ;
431  else
432  vector1 /= vector1.norm();
433 
434  if (isFree1(APath) || isFree0(alpha1(APath)))
435  pathDirection = vector1;
436  else
437  {
438  CVertex vector0 = pathOrigin - * findVertex(alpha10(APath));
439 
440  if (vector0.isNull())
441  vector0 = OZ;
442  else
443  vector0 /= vector0.norm();
444 
445  pathDirection = (vector0 + vector1) / 2;
446  }
447 
448  if (pathDirection.isNull())
449  pathDirection = OZ;
450 
451  // Vecteur normal des cellules à extruder:
452  int nbCells = 0;
453 
454  for (it.reinit(); it.cont(); ++it)
455  if (!isMarked(*it, treated))
456  {
457  if (isMarked(*it, toExtrude))
458  {
459  markOrbit(*it, ORBIT_CELL[ADim], treated);
460  ++nbCells;
461  cellsDirection +=
462  /* cellNormalVector(ADim, *it); */
463  faceNormalVector(*it);
464  }
465  else
466  setMark(*it, treated);
467  }
468 
469  if (nbCells>0)
470  cellsDirection /= nbCells;
471 
472  if (cellsDirection.isNull())
473  cellsDirection = ADim==0 ? OX : ADim==1 ? OY : OZ;
474 
475  negateMaskMark(treated);
476  }
477  }
478 
479  // Orientation initiale du chemin par rapport aux cellules:
480  if (AInitialRotateExtrudedCells!=0)
481  {
482  if (AInitialRotateExtrudedCells==1)
483  {
484  // Rotation des cellules à extruder:
485  CTransformationMatrix matrix;
486  matrix.orientate(cellsOrigin, cellsDirection, pathDirection);
487 
488  markIncidentCells(ORBIT_CC, toExtrude, treated);
489  applyMatrix(matrix, treated);
490  unmarkAll(treated);
491  }
492  else
493  {
494  // Rotation du chemin d'extrusion:
495  CTransformationMatrix matrix;
496  matrix.orientate(pathOrigin, pathDirection, cellsDirection);
497  applyMatrix(matrix, APath, ORBIT_CC);
498  }
499  }
500 
501  // Positionnement initial du chemin par rapport aux cellules:
502  if (AInitialTranslateExtrudedCells!=0)
503  {
504  if (AInitialTranslateExtrudedCells==1)
505  {
506  // Translation des cellules à extruder:
507  markIncidentCells(ORBIT_CC, toExtrude, treated);
508  translate(treated, pathOrigin - cellsOrigin);
509  unmarkAll(treated);
510  }
511  else
512  {
513  // Translation du chemin d'extrusion:
514  markOrbit(APath, ORBIT_CC, treated);
515  translate(treated, cellsOrigin - pathOrigin);
516  unmarkOrbit(APath, ORBIT_CC, treated);
517  }
518  }
519 
520  // Extrusion:
521  int extruded = getNewMark();
522 
523  int directInfoIndex = getNewDirectInfo();
524 
525  for (it.reinit(); it.cont(); ++it)
526  setDirectInfo(*it, directInfoIndex, alpha(*it, ADim));
527 
528  for (it.reinit(); it.cont(); ++it)
529  if (isMarked(*it, toExtrude))
530  {
531  unmarkOrbit(*it, ORBIT_CELL[ADim], toExtrude);
532  extrudeByPath(*it, ADim, APath, AExtrusionWithAdjacentSews,
533  ARotateExtrudedCells, AScaleExtrudedCells,
534  APonderationPath,
535  extruded, directInfoIndex);
536  ++nbExtruded;
537  }
538 
539  freeDirectInfo(directInfoIndex);
540 
541  freeMark(treated);
542 
543  unmarkAll(extruded);
544  freeMark(extruded);
545 
546  unmarkAll(toExtrude);
547  freeMark(toExtrude);
548 
549  // Replacement du chemin à sa position initiale:
550  if (AInitialTranslateExtrudedCells==2)
551  {
552  CTransformationMatrix matrix;
553  matrix.translate(pathOrigin - cellsOrigin);
554  applyMatrix(matrix, APath, ORBIT_CC);
555  }
556 
557  // Replacement du chemin dans sa direction initiale:
558  if (AInitialRotateExtrudedCells==2)
559  {
560  CTransformationMatrix matrix;
561  matrix.orientate(pathOrigin, cellsDirection, pathDirection);
562  applyMatrix(matrix, APath, ORBIT_CC);
563  }
564 
565  return nbExtruded;
566 }
567 //******************************************************************************
569  const CVertex & AAxeDirection,
570  const CVertex & AFirstVertex,
571  TCoordinate AAngle, int ANbEdges)
572 {
573  assert(!AAxeDirection.isNull());
574  assert(ANbEdges>=3);
575 
576  // Topologie:
577  TCoordinate nbRounds = fabs(AAngle)/360.0;
578  bool closed = isZero(nbRounds - floor(nbRounds));
579 
580  CDart* extremity = CGMapGeneric::createRevolutionPath(closed, ANbEdges);
581 
582  // Plongements:
583  CVertex vertex(AFirstVertex);
584 
585  CTransformationMatrix matrix;
586  matrix.rotate(AAxeVertex, AAxeDirection, AAngle/ANbEdges);
587 
588  int nbVertices = closed ? ANbEdges : ANbEdges + 1;
589 
590  CDart* current = extremity;
591 
592  for (int i=0; i<nbVertices; ++i)
593  {
594  setVertex(current, vertex);
595  matrix.applyOn(vertex);
596  current= alpha01(current);
597  }
598 
599  return extremity;
600 }
601 //******************************************************************************
603  const CVertex & AAxeVertex,
604  const CVertex & AAxeDirection,
605  const CVertex & AFirstVertex,
606  TCoordinate AAngle, int ANbEdges,
607  bool AExtrusionWithAdjacentSews,
608  bool ARotateExtrudedCells,
609  bool AScaleExtrudedCells,
610  CDart* APonderationPath,
611  int AMarkExtruded, int ADirectInfoIndex)
612 {
613 #ifndef NDEBUG
614  TCoordinate nbRounds = fabs(AAngle)/360.0;
615  bool closed = isZero(nbRounds - floor(nbRounds));
616 
617  assert(canExtrudeByRevolution(ADart, ADim, closed));
618  assert(ANbEdges>=3);
619  assert(!AAxeDirection.isNull());
620 #endif
621 
622  // 1) Création du chemin:
623  CDart* path = createRevolutionPath(AAxeVertex, AAxeDirection,
624  AFirstVertex, AAngle, ANbEdges);
625 
626  // 2) Extrusion:
627  CDart* result = extrudeByPath(ADart, ADim, path,
628  AExtrusionWithAdjacentSews,
629  ARotateExtrudedCells, AScaleExtrudedCells,
630  APonderationPath,
631  AMarkExtruded, ADirectInfoIndex);
632 
633  // 3) Destruction du chemin:
634  destroyRevolutionPath(path);
635 
636  return result;
637 }
638 //******************************************************************************
639 int CGMapVertex::
640 extrudeByRevolutionMarkedCells(int AMarkNumber, int ADim,
641  const CVertex & AAxeVertex,
642  const CVertex & AAxeDirection,
643  TCoordinate AAngle, int ANbEdges,
644  bool AExtrusionWithAdjacentSews,
645  int AInitialTranslateExtrudedCells,
646  int AInitialRotateExtrudedCells,
647  bool ARotateExtrudedCells,
648  bool AScaleExtrudedCells,
649  CDart* APonderationPath)
650 {
651  assert(ANbEdges>=3);
652  assert(!AAxeDirection.isNull());
653  assert(0<=AInitialTranslateExtrudedCells
654  && AInitialTranslateExtrudedCells<=2);
655  assert(0<=AInitialRotateExtrudedCells
656  && AInitialRotateExtrudedCells<=2);
657 
658  TCoordinate nbRounds = fabs(AAngle)/360.0;
659  bool closed = isZero(nbRounds - floor(nbRounds));
660 
661  int toExtrude = getNewMark();
662  int treated = getNewMark();
663 
664  // 1) Repérage des cellules qui peuvent être extrudées:
665  if (AInitialRotateExtrudedCells==0)
666  markIncidentCells(ORBIT_INF[ADim], AMarkNumber, toExtrude);
667  else
668  {
669  halfMarkIncidentCells(ORBIT_INF[ADim], AMarkNumber, toExtrude);
670 
671  for (CDynamicCoverageAll it(this); it.cont(); ++it)
672  if (!isMarked(*it, treated))
673  {
674  if (isMarked(*it, toExtrude) && !isFree0(*it) &&
675  isMarked(alpha0(*it), toExtrude))
676  {
677  markOrbit(*it, ORBIT_INF[ADim], treated);
678  unmarkOrbit(*it, ORBIT_INF[ADim], toExtrude);
679  }
680  else
681  setMark(*it, treated);
682  }
683 
684  negateMaskMark(treated);
685  }
686 
687  for (CDynamicCoverageAll it(this); it.cont(); ++it)
688  if (!isMarked(*it, treated))
689  {
690  if (isMarked(*it, toExtrude))
691  {
692  markOrbit(*it, ORBIT_CELL[ADim], treated);
693 
694  if (!canExtrudeByRevolution(*it, ADim, closed))
695  unmarkOrbit(*it, ORBIT_CELL[ADim], toExtrude);
696  }
697  else
698  setMark(*it, treated);
699  }
700 
701  negateMaskMark(treated);
702 
703  // 2) Calcul du barycentre des cellules:
704  markIncidentCells(ORBIT_CELL[ADim], toExtrude, treated);
705  CVertex bary = barycenter(treated);
706  unmarkAll(treated);
707  freeMark(treated);
708  freeMark(toExtrude);
709 
710  // 3) Création du chemin:
711  CDart* path = createRevolutionPath(AAxeVertex, AAxeDirection,
712  bary, AAngle, ANbEdges);
713 
714  // 4) Extrusion:
715  int result = extrudeByPathMarkedCells(AMarkNumber, ADim, path,
716  AExtrusionWithAdjacentSews,
717  0, AInitialRotateExtrudedCells,
718  ARotateExtrudedCells,
719  AScaleExtrudedCells,
720  APonderationPath);
721 
722  // 5) Destruction du chemin:
723  destroyRevolutionPath(path);
724 
725  return result;
726 }
727 //******************************************************************************