Moka kernel
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gmv-off.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 "streams.hh"
27 #include <cstring>
28 #include <map>
29 using namespace std;
30 using namespace GMap3d;
31 
32 //******************************************************************************
33 void CGMapVertex::linkFaceAlpha2OFF(vector< list<CDart*> >& ATestVertices,
34  int AIndex, CDart* ADart)
35 {
36  CDart* current = ADart;
37  do
38  {
39  unsigned long int v1 = (unsigned long int)getDirectInfo(current, AIndex);
40  unsigned long int v2 = (unsigned long int)getDirectInfo(alpha0(current), AIndex);
41 
42  list<CDart*>& tmp1 = ATestVertices[v1];
43  list<CDart*>& tmp2 = ATestVertices[v2];
44 
45  // Recherche s'il existe déjà une arête v1->v2. Si oui couture par alpha2.
46  list<CDart*>::iterator it;
47  CDart* foundEdge = NULL;
48  for (it = tmp1.begin(); foundEdge == NULL && it != tmp1.end(); ++it)
49  {
50  if (((unsigned long int)getDirectInfo(alpha0(*it), AIndex)) == v2)
51  {
52  foundEdge = *it;
53  }
54  }
55 
56  if (foundEdge != NULL)
57  {
58  // Le vecteur associé à l'arête autour de laquelle on tourne.
59  CVertex edge = edgeVector(foundEdge);
60  CVertex vect1 =
62 
63  CVertex vect2;
64  CVertex vectNew =
66 
67  // On va tourner autour de l'arête pour trouver l'endroit ou
68  // insérer la face courante.
69  bool here = false;
70  bool roundingError = false;
71  CDart* first = foundEdge;
72 
73  TCoordinate angle1, angle2;
74 
75  if (!isFree2(foundEdge))
76  while (!here)
77  {
79  (faceNormalVector(alpha23(foundEdge)), edge);
80 
81  angle1 = positifAngle
82  (CGeometry::getAngle(vect1, vect2, edge));
83 
84  angle2 =
86  (CGeometry::getAngle(vect1, vectNew, edge)) +
88  (CGeometry::getAngle(vectNew, vect2, edge));
89 
90  if (areEqual(angle1, angle2))
91  here = true;
92  else
93  {
94  vect1 = vect2;
95  foundEdge = alpha23(foundEdge);
96  }
97 
98  // Pour gérer les erreurs d'arrondi...
99  if (!here && foundEdge == first)
100  {
101  roundingError = true;
102  here = true;
103  }
104  }
105 
106  if (!roundingError)
107  {
108  if (isFree2(foundEdge))
109  {
110  sew2(alpha3(current), foundEdge);
111  sew2(current, alpha3(foundEdge));
112  }
113  else
114  {
115  CDart* prev1 = alpha2(foundEdge);
116  unsew2(foundEdge);
117 
118  sew2(alpha3(current), foundEdge);
119  sew2(current, prev1);
120  }
121  }
122  }
123  else
124  {
125  // On ajoute les 2 brins dart1 et dart2 dans les listes associées à
126  // v1 et v2 pour la prochaine recherche d'arête.
127  tmp1.push_back(current);
128  tmp2.push_back(alpha03(current));
129 
130  // tmp1.push_back(alpha3(dart1));
131  // tmp2.push_back(alpha3(dart2));
132  }
133 
134  current = alpha01(current);
135  }
136  while (current != ADart);
137 }
138 //******************************************************************************
139 CDart* CGMapVertex::importOff2D(std::istream & AStream)
140 {
141  // Lecture des sommets à charger:
142  vector< CVertex > initVertices;
143  vector< list<CDart*> > testVertices;
144 
145  string txt;
146  TCoordinate x, y;
147  CDart *d1 = NULL, *d2 = NULL;
148  unsigned int v1, v2;
149 
150  AStream >> txt;
151  if (txt != "OFF2D")
152  {
153  cout << "Problème d'entête : fichier non OFF" << endl;
154  return NULL;
155  }
156 
157  unsigned int nbSommets = 0;
158  unsigned int nbAretes = 0;
159 
160  AStream >> nbSommets >> nbAretes;
161  while (nbSommets > 0)
162  {
163  if (!AStream.good())
164  {
165  cout << "Problème de lecture : pas assez de sommets" << endl;
166  return NULL;
167  }
168 
169  AStream >> x >> y;
170  initVertices.push_back(CVertex(x, y, 0));
171  testVertices.push_back(list<CDart*>());
172  --nbSommets;
173  }
174 
175  while (nbAretes > 0)
176  {
177  if (!AStream.good())
178  {
179  cout << "Problème de lecture : pas assez d'arêtes" << endl;
180  return NULL;
181  }
182 
183  // Le nombre de sommets
184  AStream >> v1 >> v2; AStream.ignore(256,'\n');
185  --nbAretes;
186 
187  assert(v1 < initVertices.size());
188  assert(v2 < initVertices.size());
189 
190  d1 = addMapDart(initVertices[v1]);
191  d2 = addMapDart(initVertices[v2]);
192  linkAlpha0(d1, d2);
193 
194  linkAlpha2(d1, addMapDart());
195  linkAlpha2(d2, addMapDart());
196  linkAlpha0(alpha2(d1), alpha2(d2));
197 
198  testVertices[v1].push_back(d1);
199  testVertices[v2].push_back(alpha2(d2));
200  }
201 
202  map<double, CDart*> tabDart;
203  list<CDart*>::iterator it;
204  map<double, CDart*>::iterator it2;
205 
206  CDart* first=NULL;
207  CDart* prec=NULL;
208  CVertex vectNormal(0, 0, 1);
209  CVertex vect1, vect2, sommet;
210 
211  for (unsigned int i = 0; i < initVertices.size(); ++i)
212  {
213  it = testVertices[i].begin();
214  if (it != testVertices[i].end()) // Si la liste n'est pas vide.
215  {
216  // 1. on insère tout les brins en les triant selon l'angle
217  // avec first
218  tabDart.clear();
219  first = *it;
220 
221  sommet = *findVertex(*it);
222  vect1 = *findVertex(alpha0(*it)) - sommet;
223  ++it;
224  while (it != testVertices[i].end())
225  {
226  vect2 = *findVertex(alpha0(*it)) - sommet;
227  tabDart.insert
228  (pair<double, CDart*>
229  (positifAngle(CGeometry::getAngle(vect1, vect2, vectNormal)),
230  *it));
231  ++it;
232  }
233 
234  // 2. On parcours le tableau des brins trié et on couds.
235  it2 = tabDart.begin();
236  prec = first;
237  while (it2 != tabDart.end())
238  {
239  sew1(prec, alpha2(it2->second));
240  prec = it2->second;
241  ++it2;
242  }
243  sew1(prec, alpha2(first));
244  }
245  }
246 
247  // On retourne un brin chargé (n'importe lequel)
248  return first;
249 }
250 //******************************************************************************
251 CDart* CGMapVertex::addEdgeOFF(vector< CVertex >& AInitVertices,
252  unsigned long int AV1, unsigned long int AV2,
253  int AIndex, CDart* APrec)
254 {
255  CDart* dart1 = addMapDart(AInitVertices[AV1]);
256  CDart* dart2 = addMapDart();
257 
258  setDirectInfo(dart1, AIndex, (void*)AV1);
259  setDirectInfo(dart2, AIndex, (void*)AV2);
260 
261  // Coutures par alpha0 et alpha1
262  linkAlpha0(dart1, dart2);
263 
264  linkAlpha3(dart1, addMapDart());
265  linkAlpha3(dart2, addMapDart());
266  linkAlpha0(alpha3(dart1), alpha3(dart2));
267 
268  setDirectInfo(alpha3(dart1), AIndex, (void*)AV1);
269  setDirectInfo(alpha3(dart2), AIndex, (void*)AV2);
270 
271  if (APrec != NULL)
272  {
273  linkAlpha1(APrec, dart1);
274  linkAlpha1(alpha3(APrec), alpha3(dart1));
275  }
276 
277  return dart2;
278 }
279 //******************************************************************************
280 CDart* CGMapVertex::importOff3D(std::istream & AStream)
281 {
282  // Lecture des sommets à charger:
283  vector< CVertex > initVertices;
284  vector< list<CDart*> > testVertices;
285 
286  string txt;
287  TCoordinate x, y, z;
288  CDart *prec = NULL, *first = NULL;
289  unsigned int i, n;
290  unsigned long int v1, v2, vf;
291 
292  AStream >> txt;
293  if (txt != "OFF" && txt != "OFF3D")
294  {
295  cout << "Problème d'entête : fichier non OFF" << endl;
296  return NULL;
297  }
298 
299  unsigned int nbSommets = 0;
300  unsigned int nbFaces = 0;
301  unsigned int doubleNbAretes = 0;
302 
303  AStream >> nbSommets >> nbFaces >> doubleNbAretes;
304  while (nbSommets > 0)
305  {
306  if (!AStream.good())
307  {
308  cout << "Problème de lecture : pas assez de sommets" << endl;
309  return NULL;
310  }
311 
312  AStream >> x >> y >> z;
313  initVertices.push_back(CVertex(x, y, z));
314  testVertices.push_back(list<CDart*>());
315  --nbSommets;
316  }
317 
318  int index = getNewDirectInfo();
319 
320  while (nbFaces > 0)
321  {
322  if (!AStream.good())
323  {
324  cout << "Problème de lecture : pas assez de faces" << endl;
325  freeDirectInfo(index);
326  return NULL;
327  }
328 
329  // Le nombre de sommets
330  AStream >> n;
331  prec = NULL;
332  first = NULL;
333 
334  // Le premier sommet.
335  AStream >> v1; --n;
336  vf = v1;
337  assert(v1 < initVertices.size());
338 
339  // Les autres.
340  for (i = 0;i < n;++i)
341  {
342  AStream >> v2;
343  assert(v2 < initVertices.size());
344 
345  prec = addEdgeOFF(initVertices, v1, v2, index,
346  prec);
347 
348  if (first == NULL) first = alpha0(prec);
349 
350  v1 = v2;
351  }
352  AStream.ignore(256,'\n'); // Ignore the end of the line.
353 
354  prec = addEdgeOFF(initVertices, v1, vf, index,
355  prec);
356 
357  linkAlpha1(first, prec);
358  linkAlpha1(alpha3(first), alpha3(prec));
359 
360  linkFaceAlpha2OFF(testVertices, index, first);
361 
362  --nbFaces;
363  }
364 
365  freeDirectInfo(index);
366 
367  return first;
368 }
369 //******************************************************************************
370 int CGMapVertex::getOffDimension(const char * AFilename)
371 {
372  ifstream stream;
373  stream.open(AFilename);
374  string txt;
375  stream >> txt;
376  stream.close();
377 
378  if (txt == "OFF2D") return 2;
379  else if (txt == "OFF" || txt == "OFF3D") return 3;
380 
381  return -1;
382 }
383 //******************************************************************************
384 CDart* CGMapVertex::importOff(const char * AFilename)
385 {
386  ifstream stream;
387  stream.open(AFilename);
388  int dim = getOffDimension(AFilename);
389 
390  switch (dim)
391  {
392  case 2: return importOff2D(stream); break;
393  case 3: return importOff3D(stream); break;
394  }
395  return NULL;
396 }
397 //******************************************************************************
398 bool CGMapVertex::exportOff2D(std::ostream & AStream)
399 {
400  CDynamicCoverageAll it(this);
401 
402  // 1) Numérotation des sommets de 0 à n-1
403  int directInfoIndex = getNewDirectInfo();
404  int markVertex = getNewMark();
405  int markEdge = getNewMark();
406  unsigned long int nbV = 0;
407  unsigned long int nbE = 0;
408  for (it.reinit(); it.cont(); ++it)
409  {
410  if (!isMarked(*it, markVertex))
411  {
412  for (CBasicDynamicCoverageVertex it2(this, *it, markVertex);
413  it2.cont(); ++it2)
414  setDirectInfo(*it2, directInfoIndex, (void*)nbV);
415  ++nbV;
416  }
417  if (!isMarked(*it, markEdge))
418  {
419  markOrbit(*it, ORBIT_EDGE, markEdge);
420  ++nbE;
421  }
422  }
423 
424  // 2) Sauvegarde de l'entête
425  AStream << "OFF2D" << endl;
426  AStream << nbV << " " << nbE << endl;
427  AStream << endl;
428 
429  // 3) Sauvegarde des sommets
430  negateMaskMark(markVertex);
431  for (it.reinit(); it.cont(); ++it)
432  {
433  if (!isMarked(*it, markVertex))
434  {
435  CVertex* v = findVertex(*it);
436  AStream << v->getX() << " " << v->getY() << endl;
437  markOrbit(*it, ORBIT_VERTEX, markVertex);
438  }
439  }
440 
441  AStream << endl;
442 
443  // 4) Sauvegarde des arêtes
444  negateMaskMark(markEdge);
445  for (it.reinit(); it.cont(); ++it)
446  {
447  if (!isMarked(*it, markEdge))
448  {
449  AStream << (unsigned long int)getDirectInfo(*it, directInfoIndex)
450  << " " << (unsigned long int)getDirectInfo(alpha0(*it),
451  directInfoIndex) << endl;
452  markOrbit(*it, ORBIT_EDGE, markEdge);
453  }
454  }
455 
456  negateMaskMark(markVertex); freeMark(markVertex);
457  negateMaskMark(markEdge); freeMark(markEdge);
458  freeDirectInfo(directInfoIndex);
459 
460  return true;
461 }
462 //******************************************************************************
463 bool CGMapVertex::exportOff3D(std::ostream & AStream)
464 {
465  CDynamicCoverageAll it(this);
466 
467  // 1) Numérotation des sommets de 0 à n-1
468  int directInfoIndex = getNewDirectInfo();
469  int markVertex = getNewMark();
470  int markFace = getNewMark();
471  unsigned long int nbV = 0;
472  unsigned int nbE = 0; // TODO compter les arêtes
473  unsigned int nbF = 0;
474 
475  for (it.reinit(); it.cont(); ++it)
476  {
477  if (!isMarked(*it, markVertex))
478  {
479  for (CBasicDynamicCoverageVertex it2(this, *it, markVertex);
480  it2.cont(); ++it2)
481  setDirectInfo(*it2, directInfoIndex, (void*)nbV);
482  ++nbV;
483  }
484  if (!isMarked(*it, markFace))
485  {
486  bool faceOuverte = false;
487  for (CDynamicCoverage01 itFace(this,*it); itFace.cont(); ++itFace)
488  {
489  if (isFree0(*it)||isFree1(*it)) faceOuverte=true;
490  setMark(alpha3(*itFace), markFace);
491  setMark(*itFace, markFace);
492  }
493  if ( !faceOuverte ) ++nbF;
494  }
495  }
496 
497  // 3) Sauvegarde de l'entête
498  AStream << "OFF" << endl;
499  AStream << nbV << " " << nbF << " " << nbE << endl;
500  AStream << endl;
501 
502  // 4) Sauvegarde des sommets
503  negateMaskMark(markVertex);
504  for (it.reinit(); it.cont(); ++it)
505  {
506  if (!isMarked(*it, markVertex))
507  {
508  CVertex* v = findVertex(*it);
509  AStream << v->getX() << " " << v->getY() << " " << v->getZ() << endl;
510  markOrbit(*it, ORBIT_VERTEX, markVertex);
511  }
512  }
513 
514  AStream << endl;
515 
516  // 5) Sauvegarde des faces (sauf les faces ouvertes)
517  negateMaskMark(markFace);
518  for (it.reinit(); it.cont(); ++it)
519  {
520  if (!isMarked(*it, markFace))
521  {
522  CDynamicCoverage01 itFace(this,*it);
523  int n=0; bool faceOuverte = false;
524  for (; !faceOuverte && itFace.cont(); ++itFace)
525  {
526  if (isFree0(*it)||isFree1(*it)) faceOuverte=true;
527  ++n;
528  }
529 
530  if ( !faceOuverte )
531  {
532  // Sauvegarde du nombre de sommet de la face
533  AStream << (n/2) <<" ";
534  itFace.reinit();
535  while( itFace.cont() )
536  {
537  AStream << (unsigned long int)getDirectInfo(*itFace, directInfoIndex)
538  << " ";
539 
540  setMark(alpha3(*itFace), markFace);
541  setMark(itFace++, markFace); assert(itFace.cont());
542 
543  setMark(alpha3(*itFace), markFace);
544  setMark(itFace++, markFace);
545  }
546  AStream << endl;
547  }
548  else
549  markOrbit(*it, ORBIT_FACE, markFace);
550  }
551  }
552 
553  negateMaskMark(markVertex); freeMark(markVertex);
554  negateMaskMark(markFace); freeMark(markFace);
555  freeDirectInfo(directInfoIndex);
556 
557  return true;
558 }
559 //******************************************************************************
560 bool CGMapVertex::exportOff(const char * AFilename)
561 {
562  ofstream stream;
563  stream.open(AFilename, ios::trunc);
564 
565  int dim = getMapDimension();
566  bool res = false;
567 
568  if ( dim==3 ) res = exportOff3D(stream);
569  else res = exportOff2D(stream);
570 
571  stream.close();
572  return res;
573 }
574 //******************************************************************************
575 bool CGMapVertex::exportOff3D(const char * AFilename)
576 {
577  ofstream stream;
578  stream.open(AFilename, ios::trunc);
579 
580  bool res = exportOff3D(stream);
581 
582  stream.close();
583  return res;
584 }
585 //******************************************************************************