Moka kernel
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gmg-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-generic.hh"
26 using namespace GMap3d;
27 //******************************************************************************
29  int AMarkToExtrude)
30 {
31  assert(ADart!=NULL);
32  assert(ADim>=0 && ADim<=2);
33 
34  // Il faut vérifier que tous les brins de l'orbite (ADart, ORBIT_INF[ADim])
35  // sont ADim-libres:
36 
37  switch (ADim)
38  {
39  case 0:
40  return
41  isFree0(ADart) ||
42  (AMarkToExtrude>=0 && isMarked(alpha0(ADart), AMarkToExtrude));
43 
44  case 1:
45  return
46  (isFree1(ADart) ||
47  (AMarkToExtrude>=0 && isMarked(alpha1 (ADart), AMarkToExtrude))) &&
48  (isFree1(alpha0(ADart)) ||
49  (AMarkToExtrude>=0 && isMarked(alpha01(ADart), AMarkToExtrude))) ;
50 
51  case 2:
52  for (CDynamicCoverage01 it(this, ADart); it.cont(); ++it)
53  if (!isFree2(*it) &&
54  (AMarkToExtrude<0 || !isMarked(alpha2(*it), AMarkToExtrude)))
55  return false;
56 
57  return true;
58  }
59 
60  return false; // Pour éviter un warning à la compilation...
61 }
62 //******************************************************************************
63 bool CGMapGeneric::canExtrudeCell(CDart* ADart, int ADim)
64 {
65  assert(ADart!=NULL);
66  assert(ADim>=0 && ADim<=2);
67 
68  return isFree(ADart, ADim+1) || canExtrudeHalfCell(ADart, ADim);
69 }
70 //******************************************************************************
72 {
73  assert(ADart!=NULL);
74 
75  for (int dim=0; dim<=2; ++dim)
76  if (canExtrudeHalfCell(ADart, dim))
77  return dim;
78 
79  if (canExtrudeCell(ADart, 2))
80  return 2;
81 
82  return 3;
83 }
84 //******************************************************************************
86  bool AExtrusionWithAdjacentSews,
87  int AMarkExtruded, int ADirectInfoIndex)
88 {
89  assert(ADart!=NULL);
90  assert(ADim>=0 && ADim<=2);
91  assert(canExtrudeCell(ADart, ADim));
92 
93  CDart* initial = ADart;
94  CDart* halfCell;
95  CDart* opposite=NULL;
96 
97  // Duplication si nécessaire de la cellule à extruder:
98  if (canExtrudeHalfCell(ADart, ADim))
99  halfCell = ADart;
100  else
101  {
102  switch (ADim)
103  {
104  case 0:
105  {
106  CDynamicCoverage3 it(this, ADart);
107 
108  // Duplication sommet:
109  for (; it.cont(); ++it)
110  linkAlpha1(*it, addMapDart());
111 
112  for (it.reinit(); it.cont(); ++it)
113  {
114  if (!isFree3(*it) && isFree3(alpha1(*it)))
115  linkAlpha3(alpha1(*it), alpha31(*it));
116  }
117  }
118  break;
119 
120  case 1:
121  {
122  CDynamicCoverage0 it(this, ADart);
123 
124  // Duplication arête:
125  for (; it.cont(); ++it)
126  linkAlpha2(*it, addMapDart());
127 
128  for (it.reinit(); it.cont(); ++it)
129  {
130  if (!isFree0(*it) && isFree0(alpha2(*it)))
131  linkAlpha0(alpha2(*it), alpha02(*it));
132  }
133  }
134  break;
135 
136  case 2:
137  {
138  CDynamicCoverage01 it(this, ADart);
139 
140  // Duplication face:
141  for (; it.cont(); ++it)
142  linkAlpha3(*it, addMapDart());
143 
144  for (it.reinit(); it.cont(); ++it)
145  {
146  if (!isFree0(*it) && isFree0(alpha3(*it)))
147  linkAlpha0(alpha3(*it), alpha03(*it));
148 
149  if (!isFree1(*it) && isFree1(alpha3(*it)))
150  linkAlpha1(alpha3(*it), alpha13(*it));
151  }
152  }
153  break;
154  }
155 
156  halfCell = alpha(ADart, ADim+1);
157  }
158 
159  // Extrusion:
160  assert(canExtrudeHalfCell(halfCell, ADim));
161 
162  switch (ADim)
163  {
164  case 0:
165  {
166  CDynamicCoverage3 it(this, halfCell);
167 
168  // Extrusion sommet:
169  for (; it.cont(); ++it)
170  linkAlpha0(*it, addMapDart());
171 
172  for (it.reinit(); it.cont(); ++it)
173  if (!isFree3(*it) && isFree3(alpha0(*it)))
174  linkAlpha3(alpha0(*it), alpha30(*it));
175 
176  opposite = alpha0(halfCell);
177  }
178  break;
179 
180  case 1:
181  {
182  // Extrusion arête:
183  for (CDynamicCoverage0 it(this, halfCell); it.cont(); ++it)
184  {
185  CDart* d1 = addMapDart();
186  CDart* d2 = addMapDart();
187  CDart* opposite = addMapDart();
188 
189  linkAlpha0(d1, d2);
190  linkAlpha1(*it, d1);
191  linkAlpha1(d2, opposite);
192 
193  if (it.prevOperationType()!=OP_NONE)
194  linkAlpha0(opposite, alpha0101(*it));
195  }
196 
197  opposite = alpha101(halfCell);
198  }
199  break;
200 
201  case 2:
202  {
203  // Extrusion face:
204  for (CDynamicCoverage01 it(this, halfCell); it.cont(); ++it)
205  {
206  CDart* d0 = addMapDart();
207  CDart* d1 = addMapDart();
208  CDart* d2 = addMapDart();
209  CDart* d3 = addMapDart();
210  CDart* opposite = addMapDart();
211 
212  linkAlpha0(d1, d2);
213  linkAlpha1(d1, d0); linkAlpha2(d0, *it);
214  linkAlpha1(d2, d3); linkAlpha2(d3, opposite);
215 
216  if (!isFree0(*it) && !isFree2(alpha0(*it)))
217  {
218  linkAlpha0(d0, alpha02(*it));
219  linkAlpha0(d3, alpha02101(*it));
220  linkAlpha0(opposite, alpha02(d3));
221  }
222 
223  if (!isFree1(*it) && !isFree2(alpha1(*it)))
224  {
225  linkAlpha2(d1, alpha121(*it));
226  linkAlpha2(d2, alpha20(d1));
227  linkAlpha1(opposite, alpha212(d2));
228  }
229  }
230 
231  opposite = alpha21012(halfCell);
232  }
233  break;
234  }
235 
236  if (AExtrusionWithAdjacentSews && ADim>0 && AMarkExtruded>=0)
237  {
238  // Couture avec les cellules voisines:
239  CCoverage * cov = getDynamicCoverage(initial, ORBIT_INF[ADim]);
240 
241  for (; cov->cont(); ++(*cov))
242  {
243  CDart* first = **cov;
244  CDart* semiFirst = initial==halfCell ? first : alpha(first, ADim+1);
245 
246  if (isFree(alpha(semiFirst, ADim), ADim+1))
247  {
248  CDart* second =
249  ADirectInfoIndex < 0
250  ? alpha(**cov, ADim)
251  : (CDart*) getDirectInfo(**cov, ADirectInfoIndex);
252 
253  // Orbite ADim+1 o ADim:
254  bool finished = first==second;
255 
256  while (!finished && !isMarked(second, AMarkExtruded))
257  {
258  if (isFree(second, ADim+1))
259  finished = true;
260  else
261  {
262  second = alpha(second, ADim+1);
263 
264  CDart* next =
265  ADirectInfoIndex < 0
266  ? alpha(second, ADim)
267  : (CDart*) getDirectInfo(second, ADirectInfoIndex);
268 
269  if (next==second)
270  finished = true;
271  else
272  second = next;
273  }
274  }
275 
276  // ADim+1 Couture:
277  if (!finished)
278  {
279  CDart* semiSecond =
280  initial==halfCell ? second : alpha(second, ADim+1);
281 
282  assert(!isFree(semiSecond, ADim));
283  sew(alpha(semiFirst, ADim), alpha(semiSecond, ADim), ADim+1);
284  }
285  }
286  }
287 
288  delete cov;
289 
290  // Marquage de la cellule pour indiquer qu'elle alpha été extrudée:
291  markOrbit(initial, ORBIT_INF[ADim], AMarkExtruded);
292  }
293 
294  return opposite;
295 }
296 //******************************************************************************
298  bool AExtrusionWithAdjacentSews,
299  TCoordinate /*AExtrusionCoef*/,
300  int /*AMarkToExtrude*/, int AMarkExtruded)
301 {
302  return topoExtrude(ADart, ADim, AExtrusionWithAdjacentSews, AMarkExtruded);
303 }
304 //******************************************************************************
305 int CGMapGeneric::extrudeByNormalMarkedCells(int AMarkNumber, int ADim,
306  bool AExtrusionWithAdjacentSews,
307  TCoordinate AExtrusionCoef)
308 {
309  int selected = getNewMark();
310 
311  markCellsToBeExtrudedByNormal(ADim, AMarkNumber, selected);
312 
313  int nb = extrudeByNormalMarkedCells(selected, ADim, -1,
314  AExtrusionWithAdjacentSews,
315  AExtrusionCoef);
316 
317  unmarkAll(selected);
318  freeMark(selected);
319 
320  return nb;
321 }
322 //******************************************************************************
323 int CGMapGeneric::
325  bool AExtrusionWithAdjacentSews,
326  TCoordinate AExtrusionCoef)
327 {
328  int nb = 0;
329  int treated = getNewMark();
330  int selected = getNewMark();
331 
332 
333  markCellsToBeExtrudedByNormal(2, AMarkNumber, selected);
334 
335  nb+= extrudeByNormalMarkedCells(selected, 0, treated,
336  AExtrusionWithAdjacentSews,
337  AExtrusionCoef);
338  nb+= extrudeByNormalMarkedCells(selected, 1, treated,
339  AExtrusionWithAdjacentSews,
340  AExtrusionCoef);
341  nb+= extrudeByNormalMarkedCells(selected, 2, treated,
342  AExtrusionWithAdjacentSews,
343  AExtrusionCoef);
344 
345  unmarkAll(treated);
346  freeMark(treated);
347 
348  unmarkAll(selected);
349  freeMark(selected);
350 
351  return nb;
352 }
353 //******************************************************************************
354 // Méthode protégée!
356  int AMarkNumberSrce,
357  int AMarkNumberDest)
358 {
359  markIncidentCells(ORBIT_INF[ADim], AMarkNumberSrce, AMarkNumberDest);
360 }
361 //******************************************************************************
362 // Méthode protégée!
363 int CGMapGeneric::extrudeByNormalMarkedCells(int AMarkNumber, int ADim,
364  int AMarkTreated,
365  bool AExtrusionWithAdjacentSews,
366  TCoordinate AExtrusionCoef)
367 {
368  int nbExtruded = 0;
369  int treated = getNewMark();
370  int extruded = getNewMark();
371 
372  for (CDynamicCoverageAll it(this); it.cont(); ++it)
373  if (!isMarked(*it, treated))
374  {
375  if (isMarked(*it, AMarkNumber) &&
376  (AMarkTreated<0 || !isMarked(*it, AMarkTreated)))
377  {
378  if ((AMarkTreated<0 && canExtrudeCell(*it, ADim)) ||
379  (AMarkTreated>=0 &&
380  (canExtrudeHalfCell(*it, ADim) ||
381  (ADim==2 && canExtrudeCell(*it, ADim)))))
382  {
383  bool free = isFree(*it, ADim+1);
384 
385  extrudeByNormal(*it, ADim,
386  AExtrusionWithAdjacentSews,
387  AExtrusionCoef,
388  AMarkNumber, extruded);
389  ++nbExtruded;
390 
391  if (free && !isFree(*it, ADim+1))
392  {
393  markOrbit(*it, ORBIT_INF[ADim], treated);
394  markOrbit(alpha(*it, ADim+1), ORBIT_CELL[ADim+1], treated);
395 
396  if (AMarkTreated>=0)
397  markOrbit(alpha(*it, ADim+1),
398  ORBIT_CELL[ADim+1], AMarkTreated);
399  }
400  else
401  {
402  markOrbit(*it, ORBIT_CELL[ADim+1], treated);
403 
404  if (AMarkTreated>=0)
405  markOrbit(*it, ORBIT_CELL[ADim+1], AMarkTreated);
406  }
407  }
408  else
409  markOrbit(*it, ORBIT_CELL[ADim], treated);
410  }
411  else
412  setMark(*it, treated);
413  }
414 
415  unmarkAll(extruded);
416  freeMark(extruded);
417 
418  negateMaskMark(treated);
419  freeMark(treated);
420 
421  return nbExtruded;
422 }
423 //******************************************************************************
424 bool CGMapGeneric::canExtrudeByPath(CDart* ADart, int ADim, CDart* APath)
425 {
426  assert(ADart!=NULL);
427  assert(1<=ADim && ADim<=2);
428  assert(APath!=NULL);
429 
430  bool extremity = isFree0(APath) || isFree1(APath) || isFree0(alpha1(APath));
431 
432  // Cas où le chemin est ouvert:
433  if (extremity)
434  return canExtrudeCell(ADart, ADim);
435 
436  // Cas où le chemin est fermé:
437  return isFree(ADart, ADim+1);
438 }
439 //******************************************************************************
440 CDart* CGMapGeneric::extrudeByPath(CDart* ADart, int ADim, CDart* APath,
441  bool AExtrusionWithAdjacentSews,
442  int AMarkExtruded, int ADirectInfoIndex)
443 {
444  assert(canExtrudeByPath(ADart, ADim, APath));
445 
446  CDart* current = ADart;
447  bool jumped = isFree0(APath) || isFree1(APath) || isFree0(alpha1(APath));
448 
449  // Déconnexion de la cellule dans le cas où le chemin est fermé:
450  // (ou si on est au milieu du chemin)
451  if (!jumped)
452  {
453  CCoverage * cov = getDynamicCoverage(ADart, ORBIT_INF[ADim]);
454 
455  for (; cov->cont(); ++(*cov))
456  if (!isFree(**cov, ADim))
457  unsew(**cov, ADim);
458 
459  delete cov;
460  }
461 
462  // On se place sur l'extrémité de la première arête:
463  CDynamicCoverage01 path(this, APath);
464 
465  if (isFree0(*path))
466  ++path;
467 
468  if (path.cont())
469  ++path;
470 
471  while (path.cont())
472  {
473  // Extrusion:
474  assert(!isFree0(*path));
475  current = topoExtrude(current, ADim, AExtrusionWithAdjacentSews,
476  AMarkExtruded,
477  current==ADart ? ADirectInfoIndex : -1);
478 
479  // Passage à l'arête suivante:
480  ++path; if (!path.cont()) break;
481 
482  if (isFree0(*path))
483  { ++path; if (!path.cont()) break; }
484 
485  if (path.prevOperationType()==OP_JUMP)
486  {
487  current = ADart;
488  jumped = true;
489  }
490 
491  ++path;
492  }
493 
494  // Fermeture (dans le cas où le chemin est un circuit):
495  if (!jumped)
496  topoSew(current, ADart, ADim+1);
497 
498  return current;
499 }
500 //******************************************************************************
501 int CGMapGeneric::extrudeByPathMarkedCells(int AMarkNumber, int ADim,
502  CDart* APath,
503  bool AExtrusionWithAdjacentSews)
504 {
505  assert(APath!=NULL);
506  assert(1<=ADim && ADim<=2);
507 
508  int nbExtruded = 0;
509  int treated = getNewMark();
510  int toExtrude = getNewMark();
511  int extruded = getNewMark();
512 
513  int directInfoIndex = getNewDirectInfo();
514 
515  CDynamicCoverageAll it(this);
516 
517  for (; it.cont(); ++it)
518  setDirectInfo(*it, directInfoIndex, alpha(*it, ADim));
519 
520  markIncidentCells(ORBIT_CELL[ADim], AMarkNumber, toExtrude);
521 
522  for (it.reinit(); it.cont(); ++it)
523  if (!isMarked(*it, treated) && isMarked(*it, AMarkNumber))
524  {
525  markOrbit(*it, ORBIT_CELL[ADim], treated);
526 
527  if (canExtrudeByPath(*it, ADim, APath))
528  {
529  extrudeByPath(*it, ADim, APath, AExtrusionWithAdjacentSews,
530  extruded, directInfoIndex);
531  ++nbExtruded;
532  }
533  }
534 
535  freeDirectInfo(directInfoIndex);
536 
537  unmarkAll(treated);
538  freeMark(treated);
539 
540  unmarkAll(toExtrude);
541  freeMark(toExtrude);
542 
543  unmarkAll(extruded);
544  freeMark(extruded);
545 
546  return nbExtruded;
547 }
548 //******************************************************************************
549 bool CGMapGeneric::canExtrudeByRevolution(CDart* ADart, int ADim, bool AClosed)
550 {
551  assert(ADart!=NULL);
552  assert(1<=ADim && ADim<=2);
553 
554  // Cas où le chemin est ouvert:
555  if (!AClosed)
556  return canExtrudeCell(ADart, ADim);
557 
558  // Cas où le chemin est fermé:
559  return isFree(ADart, ADim+1);
560 }
561 //******************************************************************************
562 CDart* CGMapGeneric::createRevolutionPath(bool AClosed, int ANbEdges)
563 {
564  assert(ANbEdges>=3);
565 
566  CDart* extremity = createTopoPolygon(ANbEdges);
567 
568  if (!AClosed)
569  topoUnsew1(extremity);
570 
571  return extremity;
572 }
573 //******************************************************************************
575 {
576  assert(ADart!=NULL);
577  assert(isIsolatedPolyline(ADart));
578 
579  for (CStaticCoverage01 cov(this, ADart); cov.cont(); ++cov)
580  delMapDart(*cov);
581 }
582 //******************************************************************************
584  bool AClosed, int ANbEdges,
585  bool AExtrusionWithAdjacentSews,
586  int AMarkExtruded /*-1*/,
587  int ADirectInfoIndex /*-1*/)
588 {
589  assert(canExtrudeByRevolution(ADart, ADim, AClosed));
590  assert(ANbEdges>=3);
591 
592  // 1) Création du chemin:
593  CDart* path = CGMapGeneric::createRevolutionPath(AClosed, ANbEdges);
594 
595  // 2) Appel à la méthode 'extrudeByPath':
596  CDart* result = CGMapGeneric::extrudeByPath(ADart, ADim, path,
597  AExtrusionWithAdjacentSews,
598  AMarkExtruded, ADirectInfoIndex);
599 
600  // 3) Destruction du chemin:
601  destroyRevolutionPath(path);
602 
603  return result;
604 }
605 //******************************************************************************
606 int CGMapGeneric::extrudeByRevolutionMarkedCells(int AMarkNumber, int ADim,
607  bool AClosed, int ANbEdges,
608  bool AExtrusionWithAdjacentSews)
609 {
610  assert(1<=ADim && ADim<=2);
611  assert(ANbEdges>=3);
612 
613  // 1) Création du chemin:
614  CDart* path = CGMapGeneric::createRevolutionPath(AClosed, ANbEdges);
615 
616  // 2) Extrusion:
617  int nbExtruded = extrudeByPathMarkedCells(AMarkNumber, ADim, path,
618  AExtrusionWithAdjacentSews);
619 
620  // 3) Destruction du chemin:
621  destroyRevolutionPath(path);
622 
623  return nbExtruded;
624 }
625 //******************************************************************************