Moka kernel
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gmv-triangulation.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 "plane.hh"
27 #include <list>
28 using namespace std;
29 using namespace GMap3d;
30 //******************************************************************************
32 {
33  assert(ADart!=NULL);
34  // Inutile d'affecter un plongement au nouveau sommet créé, car
35  // CGMapGeneric::triangulateEdge fait appel à la méthode
36  // CGMapGeneric::insertVertex qui est virtuelle.
37  // La méthode CGMapVertex::insertVertex est donc appelée.
38  // C'est elle qui se charge de plonger le nouveau sommet.
39  return CGMapGeneric::triangulateEdge(ADart);
40 }
41 //******************************************************************************
43 {
44  assert(ADart!=NULL);
45 
46  CVertex bary = barycenter(ADart, ORBIT_01);
47  CDart * center= CGMapGeneric::triangulateFace(ADart);
48  setVertex(center, bary);
49 
50  return center;
51 }
52 //******************************************************************************
54 {
55  assert(ADart!=NULL);
56 
57  CVertex bary = barycenter(ADart, ORBIT_012);
58  CDart * center= CGMapGeneric::triangulateVolume(ADart);
59  setVertex(center, bary);
60 
61  return center;
62 }
63 //******************************************************************************
64 #define VTX(d) (AVertexDI < 0 ? findVertex(d) : \
65  (CAttributeVertex*)getDirectInfo(d, AVertexDI))
66 //------------------------------------------------------------------------------
67 void CGMapVertex::triangulateGeoFace(CDart * AFace, int ANewEdgesMark,
68  int AVertexDI)
69 {
70  if ( alpha101(AFace) == alpha010(AFace) )
71  return;
72 
73  CVertex v1, v2, v3, pt, normal;
74  CDart *face, *d1, *d2, *d3, *iter, *best;
75  TCoordinate coef, best_coef;
76  int mark = getNewMark();
77  list<CDart*> new_edges;
78 
79  normal = faceNormalVector(AFace);
80 
81  face = AFace;
82  while (alpha101(face) != alpha010(face)) {
83  // Recherche du meilleur triangle
84  d1 = face;
85  best = NULL;
86  best_coef = 0;
87  do {
88  d2 = alpha01(d1);
89  d3 = alpha10(d1);
90 
91  v1 = *VTX(d1);
92  v2 = *VTX(d2);
93  v3 = *VTX(d3);
94 
95  if (((v2 - v1) * (v3 - v1)).dot(normal) > 0.0) {
96  markOrbit(d1, ORBIT_VERTEX, mark);
97  markOrbit(d2, ORBIT_VERTEX, mark);
98  markOrbit(d3, ORBIT_VERTEX, mark);
99  iter = alpha01(d2);
100  while (iter != d3 &&
101  (isMarked(iter, mark) ||
102  !isPointInTriangle(*VTX(iter), v1, v2, v3, normal)))
103  iter = alpha01(iter);
104  unmarkOrbit(d1, ORBIT_VERTEX, mark);
105  unmarkOrbit(d2, ORBIT_VERTEX, mark);
106  unmarkOrbit(d3, ORBIT_VERTEX, mark);
107  if (iter == d3) {
108  coef = getTriangleCoef(v1, v2, v3);
109  if (coef > best_coef) {
110  best_coef = coef;
111  best = d1;
112  }
113  }
114  }
115 
116  d1 = d2;
117  }
118  while(d1 != face);
119 
120  if (!best) {
121  unmarkAll(1);
122  setMark(face, 1);
123  save("triangulateGeoFace.moka", BinaryFormat);
124  }
125 
126  assert(best != NULL);
127 
128  // Ajout d'une arête
129  d1 = best;
130  d2 = alpha01(d1);
131  d3 = alpha10(d1);
132  insertEdge(alpha1(d2), d3);
133 
134  new_edges.push_back(alpha1(d3));
135  if (ANewEdgesMark >= 0)
136  markOrbit(alpha1(d3), ORBIT_EDGE, ANewEdgesMark);
137  if (AVertexDI >= 0) {
138  pointDirectInfoToAttributeVertex(AVertexDI, d2);
139  pointDirectInfoToAttributeVertex(AVertexDI, d3);
140  }
141  face = d2;
142  normal = faceNormalVector(face);
143  }
144 
145  while (!new_edges.empty()) {
146  if (shouldSwapEdge(new_edges.front(), AVertexDI))
147  swapEdge(new_edges.front(), AVertexDI);
148  new_edges.pop_front();
149  }
150 
151  freeMark(mark);
152 }
153 //******************************************************************************
155  int ANewEdgesMark,
156  int AVertexDI)
157 {
158  bool closed;
159  int mark = getNewMark();
160 
161  for (CDynamicCoverageAll dca(this); dca.cont(); ++dca)
162  {
163  if (isMarked(*dca, AMark) )
164  {
165  if (!isMarked(*dca, mark))
166  {
167  closed = true;
168 
169  for (CDynamicCoverageFace dcf(this, *dca); dcf.cont(); ++dcf)
170  {
171  setMark(*dcf, mark);
172  if (isFree0(*dcf) || isFree1(*dcf))
173  closed = false;
174  }
175 
176  if (closed)
177  {
178  triangulateGeoFace(*dca, ANewEdgesMark, AVertexDI);
179  }
180  }
181  }
182  else
183  setMark(*dca, mark);
184  }
185 
186  unmarkAll(mark);
187  freeMark(mark);
188 }
189 //******************************************************************************
190 bool CGMapVertex::shouldSwapEdge(CDart * AEdge, int AVertexDI)
191 {
192  CVertex p[4];
193  bool result = false;
194 
195  p[0] = *VTX(AEdge);
196  p[1] = *VTX(alpha210(AEdge));
197  p[2] = *VTX(alpha0(AEdge));
198  p[3] = *VTX(alpha10(AEdge));
199 
200  CVertex v01 = p[1] - p[0];
201  CVertex v03 = p[3] - p[0];
202  CVertex v23 = p[3] - p[2];
203  CVertex v21 = p[1] - p[2];
204 
205  CVertex v013 = v01 * v03;
206  CVertex v231 = v23 * v21;
207 
208  CVertex n013 = CGeometry::getNormalVector(p[0],p[1], p[3]);
209  CVertex n123 = CGeometry::getNormalVector(p[1], p[2], p[3]);
210 
211  if (v013.dot(v231) > 0 && !n013.isNull() && !n123.isNull()) {
212  CVertex v120 = v21 * v01;
213  CVertex v302 = v03 * v23;
214 
215  TCoordinate diff1 = fabs(v013.norm() - v231.norm());
216  TCoordinate diff2 = fabs(v120.norm() - v302.norm());
217 
218  result = diff2 > diff1;
219  }
220 
221  return result;
222 }
223 //******************************************************************************
224 bool CGMapVertex::swapEdge(CDart * AEdge, int AVertexDI)
225 {
226  if ( isFree2(AEdge) || isFree1(AEdge) || isFree1(alpha0(AEdge)) ||
227  isFree1(alpha2(AEdge)) || isFree1(alpha20(AEdge)) )
228  return false;
229 
230  CDart *d[2] = {AEdge, alpha20(AEdge)};
231  CDart *old[2] = {alpha1(d[0]), alpha1(d[1])};
232  CDart *d1, *d2;
233 
234  for (int i = 0; i < 2; i++) {
235  d1 = alpha1(d[i]);
236  d2 = alpha21(d[i]);
237 
238  unsew1(d1);
239  unsew1(d2);
240  sew1(d1, d2);
241 
242  d1 = alpha0(d2);
243  d2 = alpha1(d1);
244 
245  unsew1(d1);
246  sew1(d[i], d1);
247  sew1(alpha2(d[i]), d2);
248  }
249 
250  if (AVertexDI >= 0)
251  for (int i = 0; i < 2; i++)
252  {
253  pointDirectInfoToAttributeVertex(AVertexDI, d[i]);
254  pointDirectInfoToAttributeVertex(AVertexDI, old[i]);
255  }
256 
257  return true;
258 }
259 //******************************************************************************
261  const CVertex & AVertex1,
262  const CVertex & AVertex2,
263  const CVertex & AVertex3,
264  const CVertex & ANormal)
265 {
266  CPlane plane1(ANormal * (AVertex2 - AVertex1), AVertex1);
267  CPlane plane2(ANormal * (AVertex3 - AVertex2), AVertex2);
268  CPlane plane3(ANormal * (AVertex1 - AVertex3), AVertex3);
269  return (isPositive(plane1.pointDistance(APoint)) &&
270  isPositive(plane2.pointDistance(APoint)) &&
271  isPositive(plane3.pointDistance(APoint)));
272 }
273 //******************************************************************************
275  const CVertex & AVertex2,
276  const CVertex & AVertex3)
277 {
278  if ( CGeometry::areColinear(AVertex1-AVertex2, AVertex2-AVertex3) )
279  return 0.0;
280 
281  CVertex AB = AVertex2 - AVertex1;
282  CVertex AC = AVertex3 - AVertex1;
283  CVertex BC = AVertex3 - AVertex2;
284 
285  TCoordinate a = BC.norm();
286  TCoordinate b = AC.norm();
287  TCoordinate c = AB.norm();
288 
289  CPlane plane(AB, (AVertex1 + AVertex2) / 2.0);
290  CVertex line = (AB * AC) * BC;
291  CVertex pt;
292 
293  if (!plane.getLineIntersection((AVertex2 + AVertex3) / 2.0, line, &pt)) {
294  cerr << "CTriangulationTools::getTriangleCoef: "
295  << "Erreur dans le calcul du coefficient !" << endl
296  << AVertex1 << endl
297  << AVertex2 << endl
298  << AVertex3 << endl;
299  assert(false);
300  }
301 
302  TCoordinate R = (AVertex1 - pt).norm();
303  TCoordinate coef = (a*b*c) / (4 * M_PI * R*R*R);
304  assert(coef >= 0.0 && coef < 1.0);
305  return coef;
306 }
307 //------------------------------------------------------------------------------
308 #undef VTX
309 //******************************************************************************
310