1 /****************************************************************************
2 * Rgb Triangulations Plugin *
3 * *
4 * Author: Daniele Panozzo (daniele.panozzo@gmail.com) *
5 * Copyright(C) 2007 *
6 * DISI - Department of Computer Science *
7 * University of Genova *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 ****************************************************************************/
22
23
24 #include "rgbPrimitives.h"
25 #include <algorithm>
26 #include <topologicalOp.h>
27
28 namespace rgbt
29 {
30
31 vector<FaceInfo::FaceColor>* RgbPrimitives::r4p = 0;
32 vector<FaceInfo::FaceColor>* RgbPrimitives::r2gb1p = 0;
33 vector<FaceInfo::FaceColor>* RgbPrimitives::r2gb2p = 0;
34 vector<FaceInfo::FaceColor>* RgbPrimitives::gbgb1p = 0;
35 vector<FaceInfo::FaceColor>* RgbPrimitives::gbgb2p = 0;
36 vector<FaceInfo::FaceColor>* RgbPrimitives::g2b21p = 0;
37 vector<FaceInfo::FaceColor>* RgbPrimitives::g2b22p = 0;
38
39 vector<FaceInfo::FaceColor>* RgbPrimitives::s6gp = 0;
40 vector<FaceInfo::FaceColor>* RgbPrimitives::s4g1bggr = 0;
41 vector<FaceInfo::FaceColor>* RgbPrimitives::s4g1brgg = 0;
42 vector<FaceInfo::FaceColor>* RgbPrimitives::s3g2rp = 0;
43
44 RgbPrimitives::subtype RgbPrimitives::stype = MODBUTFLY;
45
triangleVertexCorrectness(RgbTriangleC & t)46 bool RgbPrimitives::triangleVertexCorrectness(RgbTriangleC& t)
47 {
48 int vl[3];
49 vl[0] = t.getVl(0);
50 vl[1] = t.getVl(1);
51 vl[2] = t.getVl(2);
52 int l = t.getFaceLevel();
53 std::sort(vl,vl+3);
54
55 switch (t.getFaceColor())
56 {
57 case FaceInfo::FACE_BLUE_GGR:
58 case FaceInfo::FACE_BLUE_RGG:
59 return ((vl[0] <= l) && (vl[1] == l+1) && (vl[2] == l+1));
60 break;
61 case FaceInfo::FACE_GREEN:
62 return ((vl[0] <= l) && (vl[1] <= l) && (vl[2] <= l));
63 break;
64 case FaceInfo::FACE_RED_GGR:
65 case FaceInfo::FACE_RED_RGG:
66 return ((vl[0] <= l) && (vl[1] <= l) && (vl[2] == l+1));
67 break;
68 }
69 return false;
70 }
71
triangleAdjCorrectness(RgbTriangleC & t)72 bool RgbPrimitives::triangleAdjCorrectness(RgbTriangleC& t)
73 {
74 for (int i = 0; i <= 2; ++i)
75 {
76 if (t.getEdgeColor(i) != t.FF(i).getEdgeColor(t.FFi(i)) ||t.getEdgeLevel(i) != t.FF(i).getEdgeLevel(t.FFi(i)))
77 return false;
78 }
79 return true;
80 }
81
triangleVertexAngleCorrectness(RgbTriangleC & t)82 bool RgbPrimitives::triangleVertexAngleCorrectness(RgbTriangleC& t)
83 {
84 bool res = true;
85 for (int i=0; i<3;i++)
86 {
87 RgbVertexC& v = t.V(i);
88 if (!v.getIsBorder())
89 {
90 int rank = ModButterfly::baseArity(v);
91 Pos p = Pos(t.face(),i);
92 ModButterfly::rotate(v,p,2*rank);
93
94 assert(p.v == v.vp());
95 assert(p.f == t.face());
96 assert(p.z == i);
97 res == res && (p.v == v.vp()) && (p.f == t.face()) && (p.z == i);
98 }
99 }
100 return res;
101 }
102
triangleCorrectness(RgbTriangleC & t)103 bool RgbPrimitives::triangleCorrectness(RgbTriangleC& t)
104 {
105 bool a = triangleAdjCorrectness(t);
106 bool v = triangleVertexCorrectness(t);
107 bool angle = triangleVertexAngleCorrectness(t);
108 return a && v && angle;
109 }
110
gg_Split_Possible(RgbTriangleC & t,int EdgeIndex)111 bool RgbPrimitives::gg_Split_Possible(RgbTriangleC& t, int EdgeIndex)
112 {
113 if (t.getEdgeIsBorder(EdgeIndex))
114 return false; // edge is on the border
115
116 assert(triangleCorrectness(t));
117 RgbTriangleC t2 = t.FF(EdgeIndex);
118 assert(triangleCorrectness(t2));
119
120 return
121 (
122
123 (t.getFaceColor() == FaceInfo::FACE_GREEN) && // t is green
124 (t2.getFaceColor() == FaceInfo::FACE_GREEN) && // t2 is green
125 (t.getFaceLevel() == t2.getFaceLevel()) // t is at the same level of t2
126 );
127
128 }
rg_Split_Possible(RgbTriangleC & t,int EdgeIndex)129 bool RgbPrimitives::rg_Split_Possible(RgbTriangleC& t, int EdgeIndex)
130 {
131 if (t.getEdgeIsBorder(EdgeIndex))
132 return false; // edge is on the border
133 assert(triangleCorrectness(t));
134 RgbTriangleC t2 = t.FF(EdgeIndex);
135 assert(triangleCorrectness(t2));
136
137 return
138 (
139 (
140 (
141 (t.getFaceColor() == FaceInfo::FACE_GREEN) &&
142 (
143 (t2.getFaceColor() == FaceInfo::FACE_RED_GGR) ||
144 (t2.getFaceColor() == FaceInfo::FACE_RED_RGG)
145 )
146 )// t is green and t2 is red
147 ||
148 (
149 (
150 (t.getFaceColor() == FaceInfo::FACE_RED_GGR) ||
151 (t.getFaceColor() == FaceInfo::FACE_RED_RGG)
152 )
153 &&
154 (t2.getFaceColor() == FaceInfo::FACE_GREEN)
155 )// t2 is green and t is red
156 )
157 &&
158 (t.getFaceLevel() == t2.getFaceLevel()) // t and t2 are at the same level
159 &&
160 (t.getEdgeColor(EdgeIndex) == FaceInfo::EDGE_GREEN)
161 );
162
163 }
164
rr_Split_Possible(RgbTriangleC & t,int EdgeIndex)165 bool RgbPrimitives::rr_Split_Possible(RgbTriangleC& t, int EdgeIndex)
166 {
167 if (t.getEdgeIsBorder(EdgeIndex))
168 return false; // edge is on the border
169 assert(triangleCorrectness(t));
170 RgbTriangleC t2 = t.FF(EdgeIndex);
171 assert(triangleCorrectness(t2));
172
173 return
174 (
175 (
176 (t.getFaceColor() == FaceInfo::FACE_RED_GGR)
177 ||
178 (t.getFaceColor() == FaceInfo::FACE_RED_RGG)
179 ) // t is red
180 &&
181 (
182
183 (t2.getFaceColor() == FaceInfo::FACE_RED_GGR)
184 ||
185 (t2.getFaceColor() == FaceInfo::FACE_RED_RGG)
186 ) // t2 is red
187 &&
188 (t.getFaceLevel() == t2.getFaceLevel()) // t and t2 are at the same level
189 &&
190 (t.getEdgeColor(EdgeIndex) == FaceInfo::EDGE_GREEN) // edge is green
191 &&
192 (t.getEdgeLevel(EdgeIndex) == t.getFaceLevel()) // edge is at correct level
193 );
194
195 }
196
edgeSplit_Possible(RgbTriangleC & t,int EdgeIndex)197 bool RgbPrimitives::edgeSplit_Possible(RgbTriangleC& t, int EdgeIndex)
198 {
199 if (!t.getEdgeIsBorder(EdgeIndex))
200 return
201 (
202 gg_Split_Possible(t,EdgeIndex) ||
203 rg_Split_Possible(t,EdgeIndex) ||
204 rr_Split_Possible(t,EdgeIndex)
205 );
206 else
207 return
208 (
209 b_g_Bisection_Possible(t,EdgeIndex) ||
210 b_r_Bisection_Possible(t,EdgeIndex)
211 );
212 }
213
doSplit(RgbTriangleC & fp,int EdgeIndex,int level,TopologicalOpC & to,vector<FacePointer> * vfp,RgbVertexC * vNewInserted,vector<RgbVertexC> * vcont,vector<RgbVertexC> * vupd)214 bool RgbPrimitives::doSplit(RgbTriangleC& fp, int EdgeIndex, int level, TopologicalOpC& to, vector<FacePointer> *vfp, RgbVertexC* vNewInserted, vector<RgbVertexC>* vcont, vector<RgbVertexC>* vupd)
215 {
216 switch (stype)
217 {
218 case LOOP:
219 return ControlPoint::doSplit(fp, EdgeIndex, level, to, vfp, vNewInserted, vcont, vupd);
220 case MODBUTFLY:
221 return ModButterfly::doSplit(fp, EdgeIndex, level, to, vfp);
222 default:
223 return false;
224 }
225 }
226
doCollapse(RgbTriangleC & fp,int EdgeIndex,TopologicalOpC & to,Point3<ScalarType> * p,vector<FacePointer> * vfp)227 void RgbPrimitives::doCollapse(RgbTriangleC& fp, int EdgeIndex, TopologicalOpC& to, Point3<ScalarType> *p, vector<FacePointer> *vfp)
228 {
229 switch (stype)
230 {
231 case LOOP:
232 ControlPoint::doCollapse(fp, EdgeIndex, to, p, vfp);
233 break;
234 case MODBUTFLY:
235 ModButterfly::doCollapse(fp, EdgeIndex, to, p, vfp);
236 break;
237 }
238 }
239
distributeContribute(vector<RgbVertexC> & vCont,RgbVertexC & vNew,vector<RgbVertexC> & vUpd)240 void RgbPrimitives::distributeContribute(vector<RgbVertexC>& vCont,RgbVertexC& vNew,vector<RgbVertexC>& vUpd)
241 {
242 for (unsigned int i = 0; i < vCont.size(); ++i)
243 {
244 ControlPoint::addContributeIfPossible(vNew,vCont[i]);
245 }
246 for (unsigned int i = 0; i < vCont.size(); ++i)
247 {
248 ControlPoint::addContributeIfPossible(vCont[i],vNew);
249 }
250 for (unsigned int i = 0; i < vUpd.size(); ++i)
251 {
252 ControlPoint::updateP(vUpd[i]);
253 }
254 }
255
gg_Split(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)256 void RgbPrimitives::gg_Split(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
257 {
258 assert(gg_Split_Possible(t,EdgeIndex));
259 int l = t.getFaceLevel();
260
261 // Store the face obtained with the split
262 vector<FacePointer> vfp;
263 // Execute the split
264 RgbVertexC vNew;
265 vector<RgbVertexC> vCont;
266 vector<RgbVertexC> vUpd;
267
268 bool todo = RgbPrimitives::doSplit(t,EdgeIndex,l+1,to,&vfp,&vNew,&vCont,&vUpd);
269
270 if (!todo)
271 return; // The update on rgb is already done by doSplit
272
273 RgbTriangleC t0 = RgbTriangleC(t.m,t.rgbInfo,vfp[0]->Index());
274 RgbTriangleC t1 = RgbTriangleC(t.m,t.rgbInfo,vfp[1]->Index());
275 RgbTriangleC t2 = RgbTriangleC(t.m,t.rgbInfo,vfp[2]->Index());
276 RgbTriangleC t3 = RgbTriangleC(t.m,t.rgbInfo,vfp[3]->Index());
277
278 g_Bisection(l,t0,t2);
279 g_Bisection(l,t3,t1);
280
281 assert(triangleCorrectness(t0));
282 assert(triangleCorrectness(t1));
283 assert(triangleCorrectness(t2));
284 assert(triangleCorrectness(t3));
285
286 if (vt)
287 {
288 vt->push_back(t0);
289 vt->push_back(t1);
290 vt->push_back(t2);
291 vt->push_back(t3);
292 }
293
294 if (stype == LOOP)
295 distributeContribute(vCont,vNew,vUpd);
296 }
297
rg_Split(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)298 void RgbPrimitives::rg_Split(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
299 {
300 assert(rg_Split_Possible(t,EdgeIndex));
301 int l = t.getFaceLevel();
302
303 // Search the green triangle
304 RgbTriangleC* tp = &t;
305 int ti = EdgeIndex;
306 RgbTriangleC ot = t.FF(EdgeIndex);
307 int oti = t.FFi(EdgeIndex);
308
309 // The color of the red triangle
310 FaceInfo::FaceColor redtype;
311 // contain the 2 indexes of the vertexes of the red edge
312 VertexPair vp;
313 if (tp->getFaceColor() == FaceInfo::FACE_RED_GGR || tp->getFaceColor() == FaceInfo::FACE_RED_RGG)
314 {
315 redtype = tp->getFaceColor();
316 vp = tp->getRedEdge();
317 tp = &ot;
318 ti = oti;
319 }
320 else
321 {
322 redtype = ot.getFaceColor();
323 vp = ot.getRedEdge();
324 }
325
326 // Store the face obtained with the split
327 vector<FacePointer> vfp;
328
329 RgbVertexC vNew;
330 vector<RgbVertexC> vCont;
331 vector<RgbVertexC> vUpd;
332
333 // Execute the split
334 bool todo = RgbPrimitives::doSplit(*tp,ti,l+1,to,&vfp,&vNew,&vCont,&vUpd);
335 if (!todo)
336 return; // The update on rgb is already done by doSplit
337
338 RgbTriangleC t0 = RgbTriangleC(t.m,t.rgbInfo,vfp[0]->Index());
339
340 RgbTriangleC t1 = RgbTriangleC(t.m,t.rgbInfo,vfp[1]->Index());
341 RgbTriangleC t2 = RgbTriangleC(t.m,t.rgbInfo,vfp[2]->Index());
342 RgbTriangleC t3 = RgbTriangleC(t.m,t.rgbInfo,vfp[3]->Index());
343
344 g_Bisection(l,t0,t2);
345 r_Bisection(l,redtype,t1,t3,vp);
346
347 assert(triangleCorrectness(t0));
348 assert(triangleCorrectness(t1));
349 assert(triangleCorrectness(t2));
350 assert(triangleCorrectness(t3));
351
352 if (vt)
353 {
354 vt->push_back(t0);
355 vt->push_back(t1);
356 vt->push_back(t2);
357 vt->push_back(t3);
358 }
359
360
361 if (t1.isBlue())
362 {
363 assert(!t3.isBlue());
364 bb_Swap_If_Needed(t1,vt);
365 }
366 else
367 {
368 assert(!t1.isBlue());
369 bb_Swap_If_Needed(t3,vt);
370 }
371
372 if (stype == LOOP)
373 distributeContribute(vCont,vNew,vUpd);
374 return;
375 }
376
rr_Split(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)377 void RgbPrimitives::rr_Split(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
378 {
379 assert(rr_Split_Possible(t,EdgeIndex));
380 int l = t.getFaceLevel();
381
382 // get the other triangle
383 RgbTriangleC ottemp = t.FF(EdgeIndex);
384 int otitemp = t.FFi(EdgeIndex);
385
386 RgbTriangleC* tp;
387 int ti;
388 RgbTriangleC* otp;
389 int oti;
390
391 tp = &t;
392 ti = EdgeIndex;
393 otp = &ottemp;
394 oti = otitemp;
395
396 VertexPair vp = tp->getRedEdge();
397 VertexPair ovp = otp->getRedEdge();
398
399 FaceInfo::FaceColor redtypeu = tp->getFaceColor();
400 FaceInfo::FaceColor redtypel = otp->getFaceColor();
401
402 // Store the face obtained with the split
403 vector<FacePointer> vfp;
404 // Execute the split
405 RgbVertexC vNew;
406 vector<RgbVertexC> vCont;
407 vector<RgbVertexC> vUpd;
408
409 bool todo = RgbPrimitives::doSplit(*tp,ti,l+1,to,&vfp,&vNew,&vCont,&vUpd);
410 if (!todo)
411 return; // The update on rgb is already done by doSplit
412
413
414 RgbTriangleC t0 = RgbTriangleC(t.m,t.rgbInfo,vfp[0]->Index());
415
416 RgbTriangleC t1 = RgbTriangleC(t.m,t.rgbInfo,vfp[1]->Index());
417 RgbTriangleC t2 = RgbTriangleC(t.m,t.rgbInfo,vfp[2]->Index());
418 RgbTriangleC t3 = RgbTriangleC(t.m,t.rgbInfo,vfp[3]->Index());
419
420 r_Bisection(l,redtypeu,t2,t0,vp);
421 r_Bisection(l,redtypel,t1,t3,ovp);
422
423 assert(triangleCorrectness(t0));
424 assert(triangleCorrectness(t1));
425 assert(triangleCorrectness(t2));
426 assert(triangleCorrectness(t3));
427
428 vector<RgbTriangleC*> vb;
429
430 if (t0.isBlue())
431 vb.push_back(&t0);
432 if (t1.isBlue())
433 vb.push_back(&t1);
434 if (t2.isBlue())
435 vb.push_back(&t2);
436 if (t3.isBlue())
437 vb.push_back(&t3);
438
439 assert(vb.size() == 2);
440
441 if (vt)
442 {
443 vt->push_back(t0);
444 vt->push_back(t1);
445 vt->push_back(t2);
446 vt->push_back(t3);
447 }
448
449
450 bb_Swap_If_Needed(*vb[0],vt);
451 bb_Swap_If_Needed(*vb[1],vt);
452
453 if (stype == LOOP)
454 distributeContribute(vCont,vNew,vUpd);
455 return;
456 }
457
edgeSplit(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)458 bool RgbPrimitives::edgeSplit(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
459 {
460 RgbVertexC v1 = t.V(EdgeIndex);
461 RgbVertexC v2 = t.V((EdgeIndex+1)%3);
462 int l = t.getFaceLevel();
463
464 RgbTriangleC t2;
465 int ti2;
466
467 if ((stype == LOOP) && !t.getEdgeIsBorder(EdgeIndex))
468 ControlPoint::findInitialStencil(t,EdgeIndex,l+1,to);
469
470 if (!IsValidEdge(v1,v2,&t2,&ti2))
471 return true; // The split is already done (by findInitialStencil)
472
473 if (!t.getEdgeIsBorder(EdgeIndex))
474 {
475 if (gg_Split_Possible(t2,ti2))
476 {
477 gg_Split(t2,ti2,to,vt);
478 }
479 else
480 if (rg_Split_Possible(t2,ti2))
481 {
482 rg_Split(t2,ti2,to,vt);
483 }
484 else
485 if (rr_Split_Possible(t2,ti2))
486 {
487 rr_Split(t2,ti2,to,vt);
488 }
489 }
490 else
491 {
492 if (b_g_Bisection_Possible(t2,ti2))
493 {
494 b_g_Bisection(t2,ti2,to,vt);
495 }
496 else
497 if (b_r_Bisection_Possible(t2,ti2))
498 {
499 b_r_Bisection(t2,ti2,to,vt);
500 }
501
502 }
503
504 if (!IsValidEdge(v1,v2,&t2,&ti2))
505 return true; // The split is already done
506 else
507 return false;
508
509 }
510
bb_Swap_Possible(RgbTriangleC & t,int EdgeIndex)511 bool RgbPrimitives::bb_Swap_Possible(RgbTriangleC& t, int EdgeIndex)
512 {
513 if (t.getEdgeIsBorder(EdgeIndex))
514 return false; // edge is on the border
515
516 RgbTriangleC ot = t.FF(EdgeIndex);
517 assert(triangleCorrectness(t));
518 assert(triangleCorrectness(ot));
519 return
520 (
521 (t.getFaceLevel() == ot.getFaceLevel()) &&
522 ((t.getFaceColor() == FaceInfo::FACE_BLUE_GGR) || (t.getFaceColor() == FaceInfo::FACE_BLUE_RGG)) &&
523 ((ot.getFaceColor() == FaceInfo::FACE_BLUE_GGR) || (ot.getFaceColor() == FaceInfo::FACE_BLUE_RGG)) &&
524 (t.getEdgeColor(EdgeIndex) == FaceInfo::EDGE_RED) &&
525 rgbt::CheckFlipEdge(*(t.face()),EdgeIndex)
526 );
527
528 }
529
bb_Swap(RgbTriangleC & t,int EdgeIndex,vector<RgbTriangleC> * vt)530 void RgbPrimitives::bb_Swap(RgbTriangleC& t, int EdgeIndex, vector<RgbTriangleC>* vt)
531 {
532 assert(bb_Swap_Possible(t,EdgeIndex));
533 int l = t.getFaceLevel();
534 RgbTriangleC ot = t.FF(EdgeIndex);
535
536 rgbt::FlipEdge(*(t.face()),EdgeIndex);
537
538 // t and ot are not consistent with the color of edge and level of edge but
539 // at the first setFaceColor all the data is recalculated
540
541 t.setFaceColor(FaceInfo::FACE_GREEN);
542 ot.setFaceColor(FaceInfo::FACE_GREEN);
543 t.setFaceLevel(l+1);
544 ot.setFaceLevel(l+1);
545
546 assert(triangleCorrectness(t));
547 assert(triangleCorrectness(ot));
548
549 if (vt)
550 {
551 vt->push_back(t);
552 vt->push_back(ot);
553 }
554
555 }
556
bb_Swap_If_Needed(RgbTriangleC & t,vector<RgbTriangleC> * vt)557 void RgbPrimitives::bb_Swap_If_Needed(RgbTriangleC& t, vector<RgbTriangleC>* vt)
558 {
559 // Search for the red edge on the blue face
560 for (int i = 0; i < 3; ++i)
561 {
562 if (t.getEdgeColor(i) == FaceInfo::EDGE_RED)
563 {
564 if (bb_Swap_Possible(t,i))
565 bb_Swap(t,i,vt);
566 }
567
568 }
569 }
570
g_Bisection(int level,RgbTriangleC & rgg,RgbTriangleC & ggr)571 void RgbPrimitives::g_Bisection(int level, RgbTriangleC& rgg, RgbTriangleC& ggr)
572 {
573 // Set new colors
574 rgg.setFaceColor(FaceInfo::FACE_RED_RGG);
575 ggr.setFaceColor(FaceInfo::FACE_RED_GGR);
576
577 // Set new levels
578 rgg.setFaceLevel(level);
579 ggr.setFaceLevel(level);
580 }
581
r_Bisection(int level,FaceInfo::FaceColor color,RgbTriangleC & t1,RgbTriangleC & t2,VertexPair vp)582 void RgbPrimitives::r_Bisection(int level,FaceInfo::FaceColor color , RgbTriangleC& t1, RgbTriangleC& t2, VertexPair vp)
583 {
584 assert(color == FaceInfo::FACE_RED_GGR || color == FaceInfo::FACE_RED_RGG);
585 assert(t1.containEdge(vp) || t2.containEdge(vp));
586 RgbTriangleC* green;
587 RgbTriangleC* blue;
588
589 if (t1.containEdge(vp))
590 {
591 green = &t2;
592 blue = &t1;
593 }
594 else
595 {
596 green = &t1;
597 blue = &t2;
598 }
599
600 // Set new colors
601 green->setFaceColor(FaceInfo::FACE_GREEN);
602 if (color == FaceInfo::FACE_RED_RGG)
603 blue->setFaceColor(FaceInfo::FACE_BLUE_GGR);
604 else
605 blue->setFaceColor(FaceInfo::FACE_BLUE_RGG);
606
607 // Set new levels
608 green->setFaceLevel(level+1);
609 blue->setFaceLevel(level);
610
611 }
612
vf(RgbTriangleC & t,int VertexIndex,vectorRgbTriangle & fc)613 void RgbPrimitives::vf(RgbTriangleC& t, int VertexIndex, vectorRgbTriangle& fc)
614 {
615 assert(VertexIndex>= 0 && VertexIndex<=2);
616 assert(!t.face()->IsD());
617 assert(!t.face()->V(VertexIndex)->IsD());
618
619 bool isBorder = t.getVertexIsBorder(VertexIndex);
620 fc.reserve(fc.size()+10);
621 vcg::face::Pos<FaceType> pos(t.face(),t.face()->V(VertexIndex));
622
623 if (t.getNumberOfBoundaryEdge(&(t.V(VertexIndex))) >= 2)
624 {
625 fc.push_back(t);
626 return;
627 }
628
629 if (isBorder) // if is border move cw until the border is found
630 {
631 pos.FlipE();
632 pos.FlipF();
633
634 while (!pos.IsBorder())
635 {
636 pos.FlipE();
637 pos.FlipF();
638 }
639
640 pos.FlipE();
641 }
642
643 CMeshO::FacePointer first = pos.F();
644
645 fc.push_back(RgbTriangleC(t.m,t.rgbInfo,pos.F()->Index()));
646 pos.FlipF();
647 pos.FlipE();
648
649
650
651 while(pos.F() != first)
652 {
653 fc.push_back(RgbTriangleC(t.m,t.rgbInfo,pos.F()->Index()));
654
655 if (pos.IsBorder())
656 break;
657
658 pos.FlipF();
659 pos.FlipE();
660 }
661
662 int indexV = t.getVIndex(VertexIndex);
663 int res;
664 for (unsigned int i = 0; i < fc.size(); ++i)
665 {
666 assert(fc[i].containVertex(indexV,&res));
667 if (!isBorder)
668 {
669 assert(fc[i].FF((res+2)%3).face() == fc[(i+1)%fc.size()].face());
670 }
671 assert(!fc[i].face()->IsD());
672 }
673
674 }
675
676
r4_Merge_Possible(RgbTriangleC & t,int VertexIndex)677 bool RgbPrimitives::r4_Merge_Possible(RgbTriangleC& t, int VertexIndex)
678 {
679 if (t.V(VertexIndex).getIsBorder())
680 return false; // Vertex is on the border
681
682 assert(VertexIndex>=0 && VertexIndex <= 2);
683 if (!r4p)
684 {
685 r4p = new vector<FaceInfo::FaceColor>(4);
686 (*r4p)[0] = FaceInfo::FACE_RED_RGG;
687 (*r4p)[1] = FaceInfo::FACE_RED_GGR;
688 (*r4p)[2] = FaceInfo::FACE_RED_RGG;
689 (*r4p)[3] = FaceInfo::FACE_RED_GGR;
690 }
691 vectorRgbTriangle fc;
692 vf(t,VertexIndex,fc);
693 vectorFaceColor vcolor;
694 extractColor(fc,vcolor);
695 return isMatch(vcolor,*r4p);
696 }
r2gb_Merge_Possible(RgbTriangleC & t,int VertexIndex)697 bool RgbPrimitives::r2gb_Merge_Possible(RgbTriangleC& t, int VertexIndex)
698 {
699 if (t.V(VertexIndex).getIsBorder())
700 return false; // Vertex is on the border
701
702 assert(VertexIndex>=0 && VertexIndex <= 2);
703
704 if (!r2gb1p)
705 {
706 r2gb1p = new vector<FaceInfo::FaceColor>(4);
707 (*r2gb1p)[0] = FaceInfo::FACE_RED_GGR;
708 (*r2gb1p)[1] = FaceInfo::FACE_RED_RGG;
709 (*r2gb1p)[2] = FaceInfo::FACE_GREEN;
710 (*r2gb1p)[3] = FaceInfo::FACE_BLUE_GGR;
711 }
712
713 if (!r2gb2p)
714 {
715 r2gb2p = new vector<FaceInfo::FaceColor>(4);
716 (*r2gb2p)[0] = FaceInfo::FACE_RED_GGR;
717 (*r2gb2p)[1] = FaceInfo::FACE_RED_RGG;
718 (*r2gb2p)[2] = FaceInfo::FACE_BLUE_RGG;
719 (*r2gb2p)[3] = FaceInfo::FACE_GREEN;
720 }
721 vectorRgbTriangle fc;
722 vf(t,VertexIndex,fc);
723 vectorFaceColor vcolor;
724 extractColor(fc,vcolor);
725
726 return (isMatch(vcolor,*r2gb1p) || isMatch(vcolor,*r2gb2p));
727 }
gbgb_Merge_Possible(RgbTriangleC & t,int VertexIndex)728 bool RgbPrimitives::gbgb_Merge_Possible(RgbTriangleC& t, int VertexIndex)
729 {
730 if (t.V(VertexIndex).getIsBorder())
731 return false; // Vertex is on the border
732
733 assert(VertexIndex>=0 && VertexIndex <= 2);
734
735 if (!gbgb1p)
736 {
737 gbgb1p = new vector<FaceInfo::FaceColor>(4);
738 (*gbgb1p)[0] = FaceInfo::FACE_GREEN;
739 (*gbgb1p)[1] = FaceInfo::FACE_BLUE_GGR;
740 (*gbgb1p)[2] = FaceInfo::FACE_GREEN;
741 (*gbgb1p)[3] = FaceInfo::FACE_BLUE_GGR;
742 }
743
744 if (!gbgb2p)
745 {
746 gbgb2p = new vector<FaceInfo::FaceColor>(4);
747 (*gbgb2p)[0] = FaceInfo::FACE_GREEN;
748 (*gbgb2p)[1] = FaceInfo::FACE_BLUE_RGG;
749 (*gbgb2p)[2] = FaceInfo::FACE_GREEN;
750 (*gbgb2p)[3] = FaceInfo::FACE_BLUE_RGG;
751 }
752
753 vectorRgbTriangle fc;
754 vf(t,VertexIndex,fc);
755 vectorFaceColor vcolor;
756 extractColor(fc,vcolor);
757 return (isMatch(vcolor,*gbgb1p) || isMatch(vcolor,*gbgb2p));
758 }
g2b2_Merge_Possible(RgbTriangleC & t,int VertexIndex)759 bool RgbPrimitives::g2b2_Merge_Possible(RgbTriangleC& t, int VertexIndex)
760 {
761 if (t.V(VertexIndex).getIsBorder())
762 return false; // Vertex is on the border
763
764 assert(VertexIndex>=0 && VertexIndex <= 2);
765
766 if (!g2b21p)
767 {
768 g2b21p = new vector<FaceInfo::FaceColor>(4);
769 (*g2b21p)[0] = FaceInfo::FACE_BLUE_GGR;
770 (*g2b21p)[1] = FaceInfo::FACE_GREEN;
771 (*g2b21p)[2] = FaceInfo::FACE_GREEN;
772 (*g2b21p)[3] = FaceInfo::FACE_BLUE_RGG;
773 }
774
775 if (!g2b22p)
776 {
777 g2b22p = new vector<FaceInfo::FaceColor>(4);
778 (*g2b22p)[0] = FaceInfo::FACE_BLUE_RGG;
779 (*g2b22p)[1] = FaceInfo::FACE_GREEN;
780 (*g2b22p)[2] = FaceInfo::FACE_GREEN;
781 (*g2b22p)[3] = FaceInfo::FACE_BLUE_GGR;
782 }
783 vectorRgbTriangle fc;
784 vf(t,VertexIndex,fc);
785 vectorFaceColor vcolor;
786 extractColor(fc,vcolor);
787 return (isMatch(vcolor,*g2b21p) || isMatch(vcolor,*g2b22p));
788 }
gg_Swap_Possible(RgbTriangleC & t,int VertexIndex)789 bool RgbPrimitives::gg_Swap_Possible(RgbTriangleC& t, int VertexIndex)
790 {
791 return
792 (
793 gg_Swap_6g_Possible(t,VertexIndex) ||
794 gg_Swap_4g1b_Possible(t,VertexIndex) ||
795 gg_Swap_3g2r_Possible(t,VertexIndex)
796 );
797 }
798
vertexRemoval_Possible(RgbTriangleC & t,int VertexIndex)799 bool RgbPrimitives::vertexRemoval_Possible(RgbTriangleC& t, int VertexIndex)
800 {
801 if (t.getVl(VertexIndex) <= 0)
802 return false;
803
804 if (!t.V(VertexIndex).getIsBorder())
805 return
806 (
807 r4_Merge_Possible(t,VertexIndex) ||
808 r2gb_Merge_Possible(t,VertexIndex) ||
809 gbgb_Merge_Possible(t,VertexIndex) ||
810 g2b2_Merge_Possible(t,VertexIndex) ||
811 gg_Swap_Possible(t,VertexIndex) ||
812 brb2g_Swap_Possible(t,VertexIndex)
813 );
814 else
815 return
816 (
817 b_r2_Merge_Possible(t,VertexIndex) ||
818 b_gb_Merge_Possible(t,VertexIndex)
819 );
820 }
821
r4_Merge(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)822 void RgbPrimitives::r4_Merge(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
823 {
824 assert(VertexIndex>=0 && VertexIndex <= 2);
825 assert(r4_Merge_Possible(t,VertexIndex));
826
827 vectorRgbTriangle fc;
828 vf(t,VertexIndex,fc);
829 assert(fc.size() == 4);
830 vectorFaceColor vcolor;
831 extractColor(fc,vcolor);
832
833 int k = findColorIndex(vcolor,FaceInfo::FACE_RED_GGR);
834
835 RgbTriangleC* f0 = &fc[(k+0)%4];
836 assert(f0->getFaceColor() == FaceInfo::FACE_RED_GGR);
837 int l = f0->getFaceLevel();
838 RgbTriangleC* f1 = &fc[(k+1)%4];
839 RgbTriangleC* f2 = &fc[(k+2)%4];
840 RgbTriangleC* f3 = &fc[(k+3)%4];
841
842 int mi = f0->maxLevelEdge();
843 RgbTriangleC rgbtemp = f0->FF(mi);
844 int rgbtempi = f0->face()->FFi(mi);
845 RgbPrimitives::doCollapse(rgbtemp,rgbtempi,to);
846
847 f1->setFaceColor(FaceInfo::FACE_GREEN,false);
848 f2->setFaceColor(FaceInfo::FACE_GREEN,false);
849 f1->setFaceLevel(l);
850 f2->setFaceLevel(l);
851
852 assert(triangleCorrectness(*f1));
853 assert(triangleCorrectness(*f2));
854
855 if (vt)
856 {
857 vt->push_back(*f1);
858 vt->push_back(*f2);
859 }
860
861 assert(f0->face()->IsD());
862 assert(!f1->face()->IsD());
863 assert(!f2->face()->IsD());
864 assert(f3->face()->IsD());
865 }
r2gb_Merge(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)866 void RgbPrimitives::r2gb_Merge(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
867 {
868 assert(VertexIndex>=0 && VertexIndex <= 2);
869 assert(r2gb_Merge_Possible(t,VertexIndex));
870
871 vectorRgbTriangle fc;
872 vf(t,VertexIndex,fc);
873 assert(fc.size() == 4);
874 vectorFaceColor vcolor;
875 extractColor(fc,vcolor);
876
877 int k = findColorIndex(vcolor,FaceInfo::FACE_RED_GGR);
878
879 RgbTriangleC* f0 = &fc[(k+0)%4];
880 assert(f0->getFaceColor() == FaceInfo::FACE_RED_GGR);
881 int l = f0->getFaceLevel();
882 RgbTriangleC* f1 = &fc[(k+1)%4];
883 RgbTriangleC* f2 = &fc[(k+2)%4];
884 RgbTriangleC* f3 = &fc[(k+3)%4];
885
886 assert((f2->getFaceColor() == FaceInfo::FACE_GREEN && f3->getFaceColor() == FaceInfo::FACE_BLUE_GGR) || (f3->getFaceColor() == FaceInfo::FACE_GREEN && f2->getFaceColor() == FaceInfo::FACE_BLUE_RGG ) );
887
888 bool isr2gb1 = f2->getFaceColor() == FaceInfo::FACE_GREEN;
889
890 int mi = f0->maxLevelEdge();
891 RgbTriangleC rgbtemp = f0->FF(mi);
892 int rgbtempi = f0->face()->FFi(mi);
893 RgbPrimitives::doCollapse(rgbtemp,rgbtempi,to);
894
895 if (isr2gb1)
896 {
897 f1->setFaceColor(FaceInfo::FACE_GREEN,false);
898 f2->setFaceColor(FaceInfo::FACE_RED_RGG,false);
899 }
900 else
901 {
902 f1->setFaceColor(FaceInfo::FACE_GREEN,false);
903 f2->setFaceColor(FaceInfo::FACE_RED_GGR,false);
904 }
905
906 f1->setFaceLevel(l);
907 f2->setFaceLevel(l);
908
909 assert(triangleCorrectness(*f1));
910 assert(triangleCorrectness(*f2));
911
912 if (vt)
913 {
914 vt->push_back(*f1);
915 vt->push_back(*f2);
916 }
917
918 assert(f0->face()->IsD());
919 assert(!f1->face()->IsD());
920 assert(!f2->face()->IsD());
921 assert(f3->face()->IsD());
922 }
gbgb_Merge(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)923 void RgbPrimitives::gbgb_Merge(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
924 {
925 assert(VertexIndex>=0 && VertexIndex <= 2);
926 assert(gbgb_Merge_Possible(t,VertexIndex));
927
928 vectorRgbTriangle fc;
929 vf(t,VertexIndex,fc);
930 assert(fc.size() == 4);
931 vectorFaceColor vcolor;
932 extractColor(fc,vcolor);
933
934 // level of one of the blue triangles
935 int l;
936
937 RgbTriangleC* f0;
938 RgbTriangleC* f1;
939 RgbTriangleC* f2;
940 RgbTriangleC* f3;
941
942 int k = findColorIndex(vcolor,FaceInfo::FACE_GREEN);
943 FaceInfo::FaceColor bluetype = fc[(k+1)%4].getFaceColor();
944 // If the blue faces are RGG we need to take the faces in ccw order else in cw order
945 if (bluetype == FaceInfo::FACE_BLUE_RGG)
946 {
947 // gbgb-2 merge
948 f0 = &fc[(k+0)%4];
949 assert(f0->getFaceColor() == FaceInfo::FACE_GREEN);
950
951 f1 = &fc[(k+1)%4];
952 l = f1->getFaceLevel();
953 f2 = &fc[(k+2)%4];
954 f3 = &fc[(k+3)%4];
955 }
956 else
957 {
958 // gbgb-1 merge
959 f0 = &fc[(k+4)%4]; // = k-0 % 4
960 assert(f0->getFaceColor() == FaceInfo::FACE_GREEN);
961
962 f1 = &fc[(k+3)%4]; // = k-1 % 4
963 l = f1->getFaceLevel();
964 f2 = &fc[(k+2)%4]; // = k-2 % 4
965 f3 = &fc[(k+1)%4]; // = k-3 % 4
966 }
967
968 assert(f0->isGreen());
969 assert(f1->isBlue());
970 assert(f2->isGreen());
971 assert(f3->isBlue());
972
973 assert(f1->getFaceColor() == f3->getFaceColor());
974
975 int mi = f3->minLevelVertex();
976
977
978 if (bluetype == FaceInfo::FACE_BLUE_RGG)
979 {
980 // gbgb-2 merge
981 mi = (mi+2) % 3;
982 }
983 else
984 {
985 // gbgb-1 merge
986 mi = (mi) % 3;
987 }
988
989
990 // The collapse must be performed on the green triangle if gbgb-2 merge
991 // and on blue if is gbgb-1 merge:
992 // this delete the correct point, if the collapse is performed
993 // on the blue the point deleted is not one at level l+1
994 if (bluetype == FaceInfo::FACE_BLUE_RGG)
995 {
996 // gbgb-2 merge
997 RgbTriangleC rgbtemp = f3->FF(mi);
998 int rgbtempi = f3->face()->FFi(mi);
999 RgbPrimitives::doCollapse(rgbtemp,rgbtempi,to);
1000 }
1001 else
1002 {
1003 // gbgb-1 merge
1004 RgbPrimitives::doCollapse(*f3,mi,to);
1005 }
1006
1007 gb_Merge(l,bluetype,*f0);
1008 gb_Merge(l,bluetype,*f1);
1009
1010 assert(triangleCorrectness(*f0));
1011 assert(triangleCorrectness(*f1));
1012
1013 if (vt)
1014 {
1015 vt->push_back(*f0);
1016 vt->push_back(*f1);
1017 }
1018
1019 assert(!f0->face()->IsD());
1020 assert(!f1->face()->IsD());
1021 assert(f2->face()->IsD());
1022 assert(f3->face()->IsD());
1023
1024 }
g2b2_Merge(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1025 void RgbPrimitives::g2b2_Merge(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1026 {
1027 assert(VertexIndex>=0 && VertexIndex <= 2);
1028 assert(g2b2_Merge_Possible(t,VertexIndex));
1029
1030 vectorRgbTriangle fc;
1031 vf(t,VertexIndex,fc);
1032 assert(fc.size() == 4);
1033 vectorFaceColor vcolor;
1034 extractColor(fc,vcolor);
1035
1036 // level of one of the blue triangles
1037 int l;
1038
1039 RgbTriangleC* f0;
1040 RgbTriangleC* f1;
1041 RgbTriangleC* f2;
1042 RgbTriangleC* f3;
1043
1044 int k = findColorIndex(vcolor,FaceInfo::FACE_GREEN);
1045 if (fc[(k+1)%4].isGreen())
1046 ++k;
1047 ++k;
1048 assert(fc[(k)%4].isBlue()); // Now k is the first blue
1049
1050 f0 = &fc[(k)%4];
1051 FaceInfo::FaceColor bluetypeu = f0->getFaceColor();
1052 l = f0->getFaceLevel();
1053 f1 = &fc[(k+1)%4];
1054 FaceInfo::FaceColor bluetypel = f1->getFaceColor();
1055
1056 f2 = &fc[(k+2)%4];
1057 f3 = &fc[(k+3)%4];
1058
1059 assert(f0->isBlue());
1060 assert(f1->isBlue());
1061 assert(f2->isGreen());
1062 assert(f3->isGreen());
1063
1064 assert(f0->getFaceColor() != f1->getFaceColor());
1065
1066 int mi = f2->minLevelVertex();
1067
1068 RgbPrimitives::doCollapse(*f2,mi,to);
1069
1070 gb_Merge(l,bluetypeu,*f0);
1071 gb_Merge(l,bluetypel,*f1);
1072
1073 assert(triangleCorrectness(*f0));
1074 assert(triangleCorrectness(*f1));
1075
1076 if (vt)
1077 {
1078 vt->push_back(*f0);
1079 vt->push_back(*f1);
1080 }
1081
1082 assert(!f0->face()->IsD());
1083 assert(!f1->face()->IsD());
1084 assert(f2->face()->IsD());
1085 assert(f3->face()->IsD());
1086 }
1087
gg_Swap(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1088 void RgbPrimitives::gg_Swap(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1089 {
1090 assert(VertexIndex>=0 && VertexIndex <= 2);
1091 assert(gg_Swap_Possible(t,VertexIndex));
1092
1093 if (gg_Swap_6g_Possible(t,VertexIndex))
1094 gg_Swap_6g(t,VertexIndex,to,vt);
1095 else if (gg_Swap_4g1b_Possible(t,VertexIndex))
1096 gg_Swap_4g1b(t,VertexIndex,to,vt);
1097 else if (gg_Swap_3g2r_Possible(t,VertexIndex))
1098 gg_Swap_3g2r(t,VertexIndex,to,vt);
1099
1100 }
vertexRemoval(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1101 void RgbPrimitives::vertexRemoval(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1102 {
1103 if (t.getVl(VertexIndex) <= 0)
1104 return;
1105
1106 RgbVertexC v = t.V(VertexIndex);
1107 vector<RgbVertexC> vv;
1108 if (stype == LOOP)
1109 {
1110 vv.reserve(6);
1111 RgbPrimitives::VV(v,vv,false);
1112 ControlPoint::vertexRemovalUpdate(v);
1113 }
1114
1115 bool modified = false;
1116 if (!t.V(VertexIndex).getIsBorder())
1117 {
1118
1119 if (r4_Merge_Possible(t,VertexIndex))
1120 {
1121 r4_Merge(t,VertexIndex,to,vt);
1122 modified = true;
1123 }
1124 else if (r2gb_Merge_Possible(t,VertexIndex))
1125 {
1126 r2gb_Merge(t,VertexIndex,to,vt);
1127 modified = true;
1128 }
1129 else if (gbgb_Merge_Possible(t,VertexIndex))
1130 {
1131 gbgb_Merge(t,VertexIndex,to,vt);
1132 modified = true;
1133 }
1134 else if (g2b2_Merge_Possible(t,VertexIndex))
1135 {
1136 g2b2_Merge(t,VertexIndex,to,vt);
1137 modified = true;
1138 }
1139 else if (gg_Swap_Possible(t,VertexIndex))
1140 {
1141 gg_Swap(t,VertexIndex,to,vt);
1142 modified = true;
1143 }
1144 else if (brb2g_Swap_Possible(t,VertexIndex))
1145 {
1146 brb2g_Swap(t,VertexIndex,to,vt);
1147 modified = true;
1148 }
1149 }
1150 else
1151 {
1152 if (b_r2_Merge_Possible(t,VertexIndex))
1153 {
1154 b_r2_Merge(t,VertexIndex,to,vt);
1155 modified = true;
1156 }
1157 else if (b_gb_Merge_Possible(t,VertexIndex))
1158 {
1159 b_gb_Merge(t,VertexIndex,to,vt);
1160 modified = true;
1161 }
1162 }
1163
1164 if ((stype == LOOP) && modified)
1165 {
1166 for (unsigned int i = 0; i < vv.size(); ++i)
1167 {
1168 ControlPoint::updateP(vv[i]);
1169 }
1170 }
1171 }
1172
extractColor(vectorRgbTriangle & f,vectorFaceColor & c)1173 void RgbPrimitives::extractColor(vectorRgbTriangle& f,vectorFaceColor& c)
1174 {
1175 vector<RgbTriangleC>::iterator it;
1176 c.reserve(c.size() + f.size());
1177 for (it = f.begin(); it < f.end(); ++it)
1178 {
1179 c.push_back(it->getFaceColor());
1180 }
1181 }
1182
findColorIndex(vectorFaceColor & vc,FaceInfo::FaceColor color)1183 int RgbPrimitives::findColorIndex(vectorFaceColor& vc,FaceInfo::FaceColor color)
1184 {
1185 for (unsigned int i = 0; i < vc.size(); ++i)
1186 {
1187 if (vc[i] == color)
1188 return i;
1189 }
1190 assert(0);
1191 return -1;
1192 }
1193
gb_Merge(int level,FaceInfo::FaceColor color,RgbTriangleC & t)1194 void RgbPrimitives::gb_Merge(int level, FaceInfo::FaceColor color , RgbTriangleC& t)
1195 {
1196 assert(color == FaceInfo::FACE_BLUE_RGG || color == FaceInfo::FACE_BLUE_GGR);
1197 t.setFaceLevel(level);
1198 if (color == FaceInfo::FACE_BLUE_RGG)
1199 t.setFaceColor(FaceInfo::FACE_RED_GGR);
1200 else
1201 t.setFaceColor(FaceInfo::FACE_RED_RGG);
1202
1203 }
1204
gg_SwapAuxPossible(RgbTriangleC & t,int EdgeIndex)1205 bool RgbPrimitives::gg_SwapAuxPossible(RgbTriangleC& t, int EdgeIndex)
1206 {
1207 if (t.getEdgeIsBorder(EdgeIndex))
1208 return false; // edge is on the border
1209
1210 RgbTriangleC ot = t.FF(EdgeIndex);
1211 int oti = t.FFi(EdgeIndex);
1212 assert(triangleCorrectness(t));
1213 assert(triangleCorrectness(ot));
1214 int l = t.getFaceLevel();
1215
1216 return
1217 (
1218 (t.getFaceLevel() == ot.getFaceLevel()) &&
1219 ((t.getFaceColor() == FaceInfo::FACE_GREEN) && (ot.getFaceColor() == FaceInfo::FACE_GREEN))
1220 &&
1221 rgbt::CheckFlipEdge(*(t.face()),EdgeIndex)
1222 &&
1223 (
1224 (t.getVl((EdgeIndex+2)%3) <= l-1 && ot.getVl((oti+2)%3) == l)
1225 ||
1226 (t.getVl((EdgeIndex+2)%3) == l && ot.getVl((oti+2)%3) <= l-1)
1227 )
1228 );
1229 }
1230
gg_SwapAux(RgbTriangleC & t,int EdgeIndex,vector<RgbTriangleC> * vt)1231 void RgbPrimitives::gg_SwapAux(RgbTriangleC& t, int EdgeIndex, vector<RgbTriangleC>* vt)
1232 {
1233 assert(gg_SwapAuxPossible(t,EdgeIndex));
1234
1235 int l = t.getFaceLevel();
1236 RgbTriangleC ot = t.FF(EdgeIndex);
1237
1238 bool upperIsAtLevelL = (t.getVl((EdgeIndex+2)%3) == l);
1239
1240 // t and ot are not consistent with the color of edge and level of edge but
1241 // at the first setFaceColor all the data is recalculated
1242 rgbt::FlipEdge(*(t.face()),EdgeIndex);
1243
1244 if (!upperIsAtLevelL)
1245 {
1246 t.setFaceColor(FaceInfo::FACE_BLUE_GGR);
1247 ot.setFaceColor(FaceInfo::FACE_BLUE_RGG);
1248 }
1249 else
1250 {
1251 t.setFaceColor(FaceInfo::FACE_BLUE_RGG);
1252 ot.setFaceColor(FaceInfo::FACE_BLUE_GGR);
1253 }
1254 t.setFaceLevel(l-1);
1255 ot.setFaceLevel(l-1);
1256
1257 assert(triangleCorrectness(t));
1258 assert(triangleCorrectness(ot));
1259
1260 if (vt)
1261 {
1262 vt->push_back(t);
1263 vt->push_back(ot);
1264 }
1265 }
1266
gg_Swap_4g1b(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1267 void RgbPrimitives::gg_Swap_4g1b(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1268 {
1269 assert(VertexIndex>=0 && VertexIndex <= 2);
1270 assert(gg_Swap_4g1b_Possible(t,VertexIndex));
1271
1272 int vertexAbsoluteIndex = t.getVIndex(VertexIndex);
1273 int l = t.getFaceLevel();
1274 if (t.isBlue())
1275 ++l;
1276
1277 vectorRgbTriangle fc;
1278 vf(t,VertexIndex,fc);
1279 assert(fc.size() == 5);
1280 int k = -1;
1281 for (unsigned int i = 0; i < fc.size(); ++i)
1282 {
1283 if (fc[i].isBlue())
1284 k = i;
1285 }
1286 assert(k >= 0 && k <= 4);
1287 vector<int> extVertex(fc.size());
1288 vector<int> sharedVertex(fc.size());
1289
1290 int res = 0;
1291 int nVertexLowLevel = 0;
1292 for (unsigned int i = 0; i < fc.size(); ++i)
1293 {
1294 assert(fc[i].containVertex(vertexAbsoluteIndex));
1295 fc[i].containVertex(vertexAbsoluteIndex,&res);
1296 sharedVertex[i] = res;
1297 extVertex[i] = (res+1)%3;
1298 if (fc[i].getVl(extVertex[i]) <= l-1)
1299 {
1300 nVertexLowLevel++;
1301 }
1302 }
1303 assert(nVertexLowLevel == 2);
1304
1305 bool isGGR = (fc[k].getFaceColor() == FaceInfo::FACE_BLUE_GGR);
1306 if (isGGR)
1307 {
1308 assert(fc[k].getVl(extVertex[k]) == l);
1309 assert(fc[(k+1)%5].getVl(extVertex[(k+1)%5]) <= l-1);
1310 assert(fc[(k+4)%5].getVl(extVertex[(k+4)%5]) <= l-1);
1311
1312 assert(gg_SwapAuxPossible(fc[(k+3)%5],sharedVertex[(k+3)%5]));
1313 gg_SwapAux(fc[(k+3)%5],sharedVertex[(k+3)%5],vt);
1314
1315 assert(vertexRemoval_Possible(fc[(k+4)%5],sharedVertex[(k+4)%5]));
1316 vertexRemoval(fc[(k+4)%5],sharedVertex[(k+4)%5],to,vt);
1317 }
1318 else
1319 {
1320 assert(fc[k].getVl(extVertex[k]) <= l-1);
1321 assert(fc[(k+1)%5].getVl(extVertex[(k+1)%5]) == l);
1322 assert(fc[(k+2)%5].getVl(extVertex[(k+2)%5]) <= l-1);
1323
1324
1325 assert(gg_SwapAuxPossible(fc[(k+3)%5],sharedVertex[(k+3)%5]));
1326 gg_SwapAux(fc[(k+3)%5],sharedVertex[(k+3)%5],vt);
1327
1328 assert(vertexRemoval_Possible(fc[(k+1)%5],sharedVertex[(k+1)%5]));
1329 vertexRemoval(fc[(k+1)%5],sharedVertex[(k+1)%5],to,vt);
1330 }
1331
1332 }
1333
1334
gg_Swap_3g2r(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1335 void RgbPrimitives::gg_Swap_3g2r(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1336 {
1337 assert(VertexIndex>=0 && VertexIndex <= 2);
1338 assert(gg_Swap_3g2r_Possible(t,VertexIndex));
1339
1340 int vertexAbsoluteIndex = t.getVIndex(VertexIndex);
1341 int l = t.getFaceLevel();
1342 if (t.isRed())
1343 ++l;
1344
1345 vectorRgbTriangle fc;
1346 vf(t,VertexIndex,fc);
1347 assert(fc.size() == 5);
1348 int k = -1;
1349 for (unsigned int i = 0; i < fc.size(); ++i)
1350 {
1351 if (fc[i].getFaceColor() == FaceInfo::FACE_RED_GGR)
1352 k = i;
1353 }
1354 assert(k >= 0 && k <= 4);
1355 assert(fc[k].getFaceColor() == FaceInfo::FACE_RED_GGR);
1356 assert(fc[(k+1)%5].getFaceColor() == FaceInfo::FACE_RED_RGG);
1357
1358
1359 vector<int> extVertex(fc.size());
1360 vector<int> sharedVertex(fc.size());
1361
1362 int res = 0;
1363 int nVertexLowLevel = 0;
1364 for (unsigned int i = 0; i < fc.size(); ++i)
1365 {
1366 fc[i].containVertex(vertexAbsoluteIndex,&res);
1367 sharedVertex[i] = res;
1368 extVertex[i] = (res+1)%3;
1369 if (fc[i].getVl(extVertex[i]) <= l-1)
1370 {
1371 nVertexLowLevel++;
1372 }
1373 }
1374
1375 assert(nVertexLowLevel == 3);
1376
1377 assert(fc[k].getVl(extVertex[k]) <= l-1);
1378 assert(fc[(k+1)%5].getVl(extVertex[(k+1)%5]) <= l-1);
1379 assert(fc[(k+2)%5].getVl(extVertex[(k+2)%5]) <= l-1);
1380
1381 assert(gg_SwapAuxPossible(fc[(k+4)%5],sharedVertex[(k+4)%5]));
1382 gg_SwapAux(fc[(k+4)%5],sharedVertex[(k+4)%5],vt);
1383
1384 assert(vertexRemoval_Possible(fc[k],sharedVertex[k]));
1385 vertexRemoval(fc[k],sharedVertex[k],to,vt);
1386 }
1387
gg_Swap_6g(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1388 void RgbPrimitives::gg_Swap_6g(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1389 {
1390 assert(VertexIndex>=0 && VertexIndex <= 2);
1391 assert(gg_Swap_6g_Possible(t,VertexIndex));
1392
1393 int vertexAbsoluteIndex = t.getVIndex(VertexIndex);
1394 int l = t.getFaceLevel();
1395
1396 vectorRgbTriangle fc;
1397 vf(t,VertexIndex,fc);
1398 assert(fc.size() == 6);
1399 vector<int> extVertex(fc.size());
1400 vector<int> sharedVertex(fc.size());
1401
1402 int k = 0;
1403
1404 int res = 0;
1405 int nVertexLowLevel = 0;
1406 for (unsigned int i = 0; i < fc.size(); ++i)
1407 {
1408 fc[i].containVertex(vertexAbsoluteIndex,&res);
1409 sharedVertex[i] = res;
1410 extVertex[i] = (res+1)%3;
1411 if (fc[i].getVl(extVertex[i]) <= l-1)
1412 {
1413 nVertexLowLevel++;
1414 k = i;
1415 }
1416 }
1417
1418 assert(nVertexLowLevel == 2);
1419
1420 RgbTriangleC* f0 = &fc[(k+0)%6];
1421 RgbTriangleC* f2 = &fc[(k+2)%6];
1422 RgbTriangleC* f3 = &fc[(k+3)%6];
1423
1424 assert(gg_SwapAuxPossible(*f0,(sharedVertex[(k+0)%6]+2)%3));
1425 gg_SwapAux(*f0,(sharedVertex[(k+0)%6]+2)%3,vt);
1426
1427 assert(gg_SwapAuxPossible(*f3,(sharedVertex[(k+3)%6]+2)%3));
1428 gg_SwapAux(*f3,(sharedVertex[(k+3)%6]+2)%3,vt);
1429
1430 assert(vertexRemoval_Possible(*f2,sharedVertex[(k+2)%6]));
1431 vertexRemoval(*f2,sharedVertex[(k+2)%6],to,vt);
1432 }
1433
check_4g1b_LevelCorrectness(vectorRgbTriangle & fc,int l)1434 bool RgbPrimitives::check_4g1b_LevelCorrectness(vectorRgbTriangle& fc, int l)
1435 {
1436 // Check Levels
1437 for (unsigned int i = 0; i < fc.size(); ++i)
1438 {
1439 if (fc[i].getFaceColor() == FaceInfo::FACE_GREEN)
1440 {
1441 if (fc[i].getFaceLevel() != l)
1442 return false;
1443 }
1444 else
1445 {
1446 if (
1447 !(fc[i].getFaceColor() == FaceInfo::FACE_BLUE_GGR || fc[i].getFaceColor() == FaceInfo::FACE_BLUE_RGG )
1448 ||
1449 (fc[i].getFaceLevel() != l-1)
1450 )
1451 return false;
1452 }
1453 }
1454 return true;
1455 }
1456
gg_Swap_4g1b_Possible(RgbTriangleC & t,int VertexIndex)1457 bool RgbPrimitives::gg_Swap_4g1b_Possible(RgbTriangleC& t, int VertexIndex)
1458 {
1459 assert(VertexIndex>=0 && VertexIndex <= 2);
1460
1461 if (t.V(VertexIndex).getIsBorder())
1462 return false; // Vertex is on the border
1463
1464 if (!s4g1bggr)
1465 {
1466 s4g1bggr = new vector<FaceInfo::FaceColor>(5);
1467 (*s4g1bggr)[0] = FaceInfo::FACE_GREEN;
1468 (*s4g1bggr)[1] = FaceInfo::FACE_GREEN;
1469 (*s4g1bggr)[2] = FaceInfo::FACE_GREEN;
1470 (*s4g1bggr)[3] = FaceInfo::FACE_GREEN;
1471 (*s4g1bggr)[4] = FaceInfo::FACE_BLUE_GGR;
1472 }
1473
1474 if (!s4g1brgg)
1475 {
1476 s4g1brgg = new vector<FaceInfo::FaceColor>(5);
1477 (*s4g1brgg)[0] = FaceInfo::FACE_GREEN;
1478 (*s4g1brgg)[1] = FaceInfo::FACE_GREEN;
1479 (*s4g1brgg)[2] = FaceInfo::FACE_GREEN;
1480 (*s4g1brgg)[3] = FaceInfo::FACE_GREEN;
1481 (*s4g1brgg)[4] = FaceInfo::FACE_BLUE_RGG;
1482 }
1483
1484 vectorRgbTriangle fc;
1485 vf(t,VertexIndex,fc);
1486 vectorFaceColor vcolor;
1487 extractColor(fc,vcolor);
1488
1489
1490 if (!(isMatch(vcolor,*s4g1bggr) || isMatch(vcolor,*s4g1brgg)))
1491 return false;
1492
1493 return true;
1494
1495 int l = 0;
1496
1497 if (fc[0].getFaceColor() == FaceInfo::FACE_GREEN)
1498 l = fc[0].getFaceLevel();
1499 else
1500 l = fc[1].getFaceLevel();
1501
1502 if (t.getVl(VertexIndex) != l)
1503 return false;
1504
1505 return check_4g1b_LevelCorrectness(fc,l);
1506 }
1507
check_3g2r_LevelCorrectness(vectorRgbTriangle & fc,int l)1508 bool RgbPrimitives::check_3g2r_LevelCorrectness(vectorRgbTriangle& fc, int l)
1509 {
1510 // Check Levels
1511 for (unsigned int i = 0; i < fc.size(); ++i)
1512 {
1513 if (fc[i].getFaceColor() == FaceInfo::FACE_GREEN)
1514 {
1515 if (fc[i].getFaceLevel() != l)
1516 return false;
1517 }
1518 else
1519 {
1520 if (
1521 !(fc[i].isRed())
1522 ||
1523 (fc[i].getFaceLevel() != l-1)
1524 )
1525 return false;
1526 }
1527 }
1528 return true;
1529 }
1530
gg_Swap_3g2r_Possible(RgbTriangleC & t,int VertexIndex)1531 bool RgbPrimitives::gg_Swap_3g2r_Possible(RgbTriangleC& t, int VertexIndex)
1532 {
1533 assert(VertexIndex>=0 && VertexIndex <= 2);
1534
1535 if (t.V(VertexIndex).getIsBorder())
1536 return false; // Vertex is on the border
1537
1538 if (!s3g2rp)
1539 {
1540 s3g2rp = new vector<FaceInfo::FaceColor>(5);
1541 (*s3g2rp)[0] = FaceInfo::FACE_GREEN;
1542 (*s3g2rp)[1] = FaceInfo::FACE_GREEN;
1543 (*s3g2rp)[2] = FaceInfo::FACE_GREEN;
1544 (*s3g2rp)[3] = FaceInfo::FACE_RED_GGR;
1545 (*s3g2rp)[4] = FaceInfo::FACE_RED_RGG;
1546 }
1547 vectorRgbTriangle fc;
1548 vf(t,VertexIndex,fc);
1549 vectorFaceColor vcolor;
1550 extractColor(fc,vcolor);
1551 if (!isMatch(vcolor,*s3g2rp))
1552 return false;
1553
1554 return true;
1555
1556 int l;
1557
1558 if (fc[0].isRed())
1559 l = fc[0].getFaceLevel() + 1;
1560 else
1561 l = fc[0].getFaceLevel();
1562
1563 if (t.getVl(VertexIndex) != l)
1564 return false;
1565
1566 return check_3g2r_LevelCorrectness(fc,l);
1567
1568 }
1569
gg_Swap_6g_Possible(RgbTriangleC & t,int VertexIndex)1570 bool RgbPrimitives::gg_Swap_6g_Possible(RgbTriangleC& t, int VertexIndex)
1571 {
1572 assert(VertexIndex>=0 && VertexIndex <= 2);
1573
1574 if (t.V(VertexIndex).getIsBorder())
1575 return false; // Vertex is on the border
1576
1577 if (!s6gp)
1578 {
1579 s6gp = new vector<FaceInfo::FaceColor>(6);
1580 (*s6gp)[0] = FaceInfo::FACE_GREEN;
1581 (*s6gp)[1] = FaceInfo::FACE_GREEN;
1582 (*s6gp)[2] = FaceInfo::FACE_GREEN;
1583 (*s6gp)[3] = FaceInfo::FACE_GREEN;
1584 (*s6gp)[4] = FaceInfo::FACE_GREEN;
1585 (*s6gp)[5] = FaceInfo::FACE_GREEN;
1586 }
1587 vectorRgbTriangle fc;
1588 vf(t,VertexIndex,fc);
1589 vectorFaceColor vcolor;
1590 extractColor(fc,vcolor);
1591
1592 int level = fc[0].getFaceLevel();
1593
1594 if (!(
1595 isMatch(vcolor,*s6gp) &&
1596 (fc[0].getFaceLevel() == level) &&
1597 (fc[1].getFaceLevel() == level) &&
1598 (fc[2].getFaceLevel() == level) &&
1599 (fc[3].getFaceLevel() == level) &&
1600 (fc[4].getFaceLevel() == level) &&
1601 (fc[5].getFaceLevel() == level)
1602 ))
1603 return false;
1604
1605 int nVertexLowLevel = 0;
1606 int vertexAbsoluteIndex = t.V(VertexIndex).index;
1607 for (unsigned int i = 0; i < fc.size(); ++i)
1608 {
1609 int res = 0;
1610 fc[i].containVertex(vertexAbsoluteIndex,&res);
1611 if (fc[i].getVl((res+1)%3) <= level-1)
1612 {
1613 nVertexLowLevel++;
1614 }
1615 }
1616
1617 if (nVertexLowLevel != 2)
1618 return false;
1619
1620 return true;
1621
1622 }
1623
1624
IsValidEdge(RgbVertexC & rgbv1,RgbVertexC & rgbv2,RgbTriangleC * t,int * ti)1625 bool RgbPrimitives::IsValidEdge(RgbVertexC& rgbv1,RgbVertexC& rgbv2, RgbTriangleC* t, int* ti)
1626 {
1627 CMeshO* m = rgbv1.m;
1628 RgbInfo* info = rgbv1.rgbInfo;
1629 int v1 = rgbv1.index;
1630 int v2 = rgbv2.index;
1631
1632
1633 assert((unsigned int)v1 < m->vert.size());
1634 assert((unsigned int)v2 < m->vert.size());
1635
1636 if (m->vert[v1].IsD() || m->vert[v2].IsD())
1637 {
1638 //std::cerr << "DELETED" << std::endl;
1639 return false;
1640 }
1641
1642 VertexType& v = m->vert[v1];
1643 RgbTriangleC tf = RgbTriangleC(m,info,v.VFp()->Index());
1644 int tfi = v.VFi();
1645 assert(tf.V(tfi).index == v1);
1646
1647 VertexType& va = m->vert[v2];
1648 RgbTriangleC tfa = RgbTriangleC(m,info,va.VFp()->Index());
1649 int tfia = va.VFi();
1650 assert(tfa.V(tfia).index == v2);
1651
1652 vector<RgbTriangleC> vf;
1653 vf.reserve(6);
1654 RgbPrimitives::vf(tf,tfi,vf);
1655
1656 for (unsigned int i = 0; i < vf.size(); ++i)
1657 {
1658 RgbTriangleC& tt = vf[i];
1659 int k = 0;
1660 while(tt.V(k).index != v1)
1661 {
1662 assert(k <= 2);
1663 k++;
1664 }
1665
1666 if (tt.V((k+1)%3).index == v2)
1667 {
1668 if (t)
1669 *t = tt;
1670 if (ti)
1671 *ti = k;
1672 return true;
1673 }
1674
1675 }
1676 return false;
1677 }
1678
recursiveEdgeSplitAux(RgbVertexC & v1,RgbVertexC & v2,TopologicalOpC & to,vector<RgbTriangleC> * vt)1679 void RgbPrimitives::recursiveEdgeSplitAux(RgbVertexC& v1, RgbVertexC& v2, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1680 {
1681 RgbTriangleC t;
1682 int EdgeIndex;
1683
1684 if (!IsValidEdge(v1,v2,&t,&EdgeIndex))
1685 return;
1686
1687 RgbTriangleC* tp = &t;
1688
1689 if (tp->isRed())
1690 {
1691 int index = -1;
1692 int l = tp->getFaceLevel();
1693 for (int i = 0; i < 3; ++i)
1694 {
1695 if (tp->getEdgeLevel(i) == l && tp->getEdgeColor(i) == FaceInfo::EDGE_GREEN)
1696 index = i;
1697 }
1698 assert(index >= 0 && index <= 2);
1699 RgbVertexC v1t = tp->V(index);
1700 RgbVertexC v2t = tp->V((index+1)%3);
1701 recursiveEdgeSplitVV(v1t,v2t,to,vt);
1702 }
1703 else
1704 {
1705
1706 assert(tp->isBlue());
1707 int l = tp->getFaceLevel();
1708 int redEdge = tp->minLevelEdge();
1709 assert(tp->getEdgeColor(redEdge) == FaceInfo::EDGE_RED);
1710 RgbTriangleC redTriangle = tp->FF(redEdge);
1711 assert(redTriangle.getFaceLevel() == l);
1712 assert(redTriangle.isRed());
1713
1714 int index = -1;
1715 for (int i = 0; i < 3; ++i)
1716 {
1717 if (redTriangle.getEdgeLevel(i) == l && redTriangle.getEdgeColor(i) == FaceInfo::EDGE_GREEN)
1718 index = i;
1719 }
1720 assert(index >= 0 && index <= 2);
1721
1722 RgbVertexC v1t = redTriangle.V(index);
1723 RgbVertexC v2t = redTriangle.V((index+1)%3);
1724
1725 recursiveEdgeSplitVV(v1t,v2t,to,vt);
1726 }
1727 }
1728
1729
recursiveEdgeSplit(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vtr)1730 bool RgbPrimitives::recursiveEdgeSplit(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vtr)
1731 {
1732 RgbVertexC v1 = t.V(EdgeIndex);
1733 RgbVertexC v2 = t.V((EdgeIndex+1)%3);
1734 return recursiveEdgeSplitVV(v1,v2,to,vtr);
1735 }
1736
recursiveEdgeSplitVV(RgbVertexC & v1,RgbVertexC & v2,TopologicalOpC & to,vector<RgbTriangleC> * vt)1737 bool RgbPrimitives::recursiveEdgeSplitVV(RgbVertexC& v1,RgbVertexC& v2, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1738 {
1739 RgbTriangleC t;
1740 int EdgeIndex;
1741
1742 if (!IsValidEdge(v1,v2,&t,&EdgeIndex))
1743 {
1744 return false;
1745 }
1746
1747
1748 if (t.getEdgeColor(EdgeIndex) == FaceInfo::EDGE_RED)
1749 {
1750 return false;
1751 }
1752
1753 if (edgeSplit_Possible(t,EdgeIndex))
1754 {
1755 return edgeSplit(t,EdgeIndex,to,vt);
1756 }
1757
1758 int l = t.getEdgeLevel(EdgeIndex);
1759
1760 RgbTriangleC ot = t.FF(EdgeIndex);
1761
1762 assert(t.getFaceLevel() == l || t.getFaceLevel() == l-1);
1763 assert(ot.getFaceLevel() == l || ot.getFaceLevel() == l-1);
1764
1765 if (t.getFaceLevel() < l)
1766 {
1767 recursiveEdgeSplitAux(v1,v2,to,vt);
1768 }
1769 if (ot.getFaceLevel() < l)
1770 {
1771 recursiveEdgeSplitAux(v2,v1,to,vt);
1772 }
1773
1774 if (!IsValidEdge(v1,v2,&t,&EdgeIndex)) // the edge can be already splitted
1775 return true;
1776
1777 if (edgeSplit_Possible(t,EdgeIndex))
1778 {
1779 // std::cerr << "POSSIBLE2" << std::endl;
1780 return edgeSplit(t,EdgeIndex,to,vt);
1781 }
1782
1783 return false;
1784 }
1785
isVertexInternal(RgbVertexC & v)1786 bool RgbPrimitives::isVertexInternal(RgbVertexC& v)
1787 {
1788 vectorRgbTriangle fc;
1789 assert(!v.vert().IsD());
1790 FacePointer fp = v.vert().VFp();
1791 int fi = v.vert().VFi();
1792 if (!fp)
1793 return false;
1794 vcg::face::Pos<FaceType> pos(fp,fp->V(fi));
1795 CMeshO::FacePointer first = pos.F();
1796 if (pos.IsBorder())
1797 return false;
1798 pos.FlipF();
1799 pos.FlipE();
1800
1801 while(pos.F() != first)
1802 {
1803 if (pos.IsBorder())
1804 {
1805 return false;
1806 }
1807
1808 pos.FlipF();
1809 pos.FlipE();
1810 }
1811
1812 return true;
1813 }
1814
1815
isVertexInternal(RgbTriangleC & t,int VertexIndex)1816 bool RgbPrimitives::isVertexInternal(RgbTriangleC& t, int VertexIndex)
1817 {
1818 assert(VertexIndex>= 0 && VertexIndex<=2);
1819 vectorRgbTriangle fc;
1820 assert(!t.face()->IsD());
1821 assert(!t.face()->V(VertexIndex)->IsD());
1822
1823 vcg::face::Pos<FaceType> pos(t.face(),t.face()->V(VertexIndex));
1824 CMeshO::FacePointer first = pos.F();
1825 pos.FlipF();
1826 pos.FlipE();
1827
1828 while(pos.F() && (pos.F() != first))
1829 {
1830 if (vcg::face::BorderCount(*pos.F()))
1831 {
1832 return false;
1833 }
1834
1835 pos.FlipF();
1836 pos.FlipE();
1837 }
1838
1839 return true;
1840 }
1841
brb2g_Swap_Possible(RgbTriangleC & t,int VertexIndex)1842 bool RgbPrimitives::brb2g_Swap_Possible(RgbTriangleC& t, int VertexIndex)
1843 {
1844 assert(VertexIndex>=0 && VertexIndex <= 2);
1845
1846 if (t.V(VertexIndex).getIsBorder())
1847 return false; // Vertex is on the border
1848
1849 vectorRgbTriangle fc;
1850 fc.reserve(5);
1851 vf(t,VertexIndex,fc);
1852
1853 if (fc.size() != 5)
1854 return false;
1855
1856 int ri = -1;
1857 for (unsigned int i = 0; i < fc.size(); ++i)
1858 {
1859 if (fc[i].isRed())
1860 {
1861 ri = i;
1862 break;
1863 }
1864 }
1865
1866 assert(ri <= 5);
1867 if (ri < 0)
1868 return false;
1869
1870 int l = fc[ri].getFaceLevel();
1871 return
1872 (
1873 fc[(ri+0)%5].isRed() && (fc[(ri+0)%5].getFaceLevel()) == l &&
1874 fc[(ri+1)%5].isBlue() && (fc[(ri+1)%5].getFaceLevel()) == l &&
1875 fc[(ri+2)%5].isGreen() && (fc[(ri+2)%5].getFaceLevel()) == l+1 &&
1876 fc[(ri+3)%5].isGreen() && (fc[(ri+3)%5].getFaceLevel()) == l+1 &&
1877 fc[(ri+4)%5].isBlue() && (fc[(ri+4)%5].getFaceLevel()) == l
1878
1879 );
1880
1881 }
1882
brb2g_Swap(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1883 void RgbPrimitives::brb2g_Swap(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1884 {
1885 RgbVertexC v = t.V(VertexIndex);
1886
1887 assert(VertexIndex>=0 && VertexIndex <= 2);
1888
1889 vectorRgbTriangle fc;
1890 fc.reserve(5);
1891 vf(t,VertexIndex,fc);
1892
1893 assert(fc.size() == 5);
1894
1895 int ri = -1;
1896 for (unsigned int i = 0; i < fc.size(); ++i)
1897 {
1898 if (fc[i].isRed())
1899 {
1900 ri = i;
1901 break;
1902 }
1903 }
1904
1905 assert(ri >= 0 && ri <= 4);
1906
1907 int rei = -1;
1908 for (int i = 0; i < 3; ++i)
1909 {
1910 if (fc[ri].getEdgeColor(i) == FaceInfo::EDGE_RED)
1911 {
1912 rei = i;
1913 break;
1914 }
1915
1916 }
1917
1918 assert(rei >= 0 && rei <= 2);
1919
1920 RgbTriangleC& t1 = fc[ri];
1921 RgbTriangleC t2 = fc[ri].FF(rei);
1922
1923 int l = t1.getFaceLevel();
1924
1925 assert(t1.isRed());
1926 assert(t2.isBlue());
1927 assert(t2.index == fc[(ri+1)%5].index || t2.index == fc[(ri+4)%5].index);
1928
1929 FaceInfo::FaceColor redt = t1.getFaceColor();
1930 FaceInfo::FaceColor bluet = t2.getFaceColor();
1931
1932 rgbt::FlipEdge(*(t1.face()),rei);
1933
1934 t1.updateInfo();
1935 t2.updateInfo();
1936
1937 RgbTriangleC* pred;
1938 RgbTriangleC* pblue;
1939
1940 if (t1.countVertexAtLevel(l+1) == 2)
1941 {
1942 // t1 is the blue triangle
1943 pblue = &t1;
1944 pred = &t2;
1945 }
1946 else
1947 {
1948 // t2 is the blue triangle
1949 pblue = &t2;
1950 pred = &t1;
1951 }
1952
1953 assert(pred->countVertexAtLevel(l+1) == 1);
1954 assert(pblue->countVertexAtLevel(l+1) == 2);
1955
1956 if (bluet == FaceInfo::FACE_BLUE_GGR)
1957 pblue->setFaceColor(FaceInfo::FACE_BLUE_RGG);
1958 else
1959 pblue->setFaceColor(FaceInfo::FACE_BLUE_GGR);
1960
1961 if (redt == FaceInfo::FACE_RED_GGR)
1962 pred->setFaceColor(FaceInfo::FACE_RED_RGG);
1963 else
1964 pred->setFaceColor(FaceInfo::FACE_RED_GGR);
1965
1966 assert(triangleCorrectness(*pred));
1967 assert(triangleCorrectness(*pblue));
1968
1969 RgbTriangleC& green = fc[(ri+2)%5];
1970 assert(green.isGreen());
1971
1972 int greeni = 0;
1973 assert(green.containVertex(v.index));
1974 green.containVertex(v.index,&greeni);
1975
1976 assert(g2b2_Merge_Possible(green,greeni));
1977 g2b2_Merge(green,greeni, to, vt);
1978
1979 }
1980
1981
b_g_Bisection_Possible(RgbTriangleC & t,int EdgeIndex)1982 bool RgbPrimitives::b_g_Bisection_Possible(RgbTriangleC& t, int EdgeIndex)
1983 {
1984 assert(triangleCorrectness(t));
1985
1986 return
1987 (
1988 (t.getEdgeIsBorder(EdgeIndex)) && // edge is on boundary
1989 (t.getFaceColor() == FaceInfo::FACE_GREEN) // t is green
1990 );
1991 }
1992
b_g_Bisection(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)1993 void RgbPrimitives::b_g_Bisection(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
1994 {
1995 assert(b_g_Bisection_Possible(t,EdgeIndex));
1996 int l = t.getFaceLevel();
1997
1998 // Store the face obtained with the split
1999 vector<FacePointer> vfp;
2000 // Execute the split
2001 RgbVertexC vNew;
2002 vector<RgbVertexC> vCont;
2003 vector<RgbVertexC> vUpd;
2004
2005
2006 bool todo = RgbPrimitives::doSplit(t,EdgeIndex,l+1,to,&vfp,&vNew,&vCont,&vUpd);
2007
2008 if (!todo)
2009 return; // The update on rgb is already done by doSplit
2010
2011 RgbTriangleC t0 = RgbTriangleC(t.m,t.rgbInfo,vfp[0]->Index());
2012 RgbTriangleC t2 = RgbTriangleC(t.m,t.rgbInfo,vfp[1]->Index());
2013
2014 g_Bisection(l,t0,t2);
2015
2016 assert(triangleCorrectness(t0));
2017 assert(triangleCorrectness(t2));
2018
2019 if (vt)
2020 {
2021 vt->push_back(t0);
2022 vt->push_back(t2);
2023 }
2024
2025 if (stype == LOOP)
2026 distributeContribute(vCont,vNew,vUpd);
2027 }
2028
b_r_Bisection_Possible(RgbTriangleC & t,int EdgeIndex)2029 bool RgbPrimitives::b_r_Bisection_Possible(RgbTriangleC& t, int EdgeIndex)
2030 {
2031 assert(triangleCorrectness(t));
2032
2033 return
2034 (
2035 (t.getEdgeIsBorder(EdgeIndex)) && // edge is on boundary
2036 (t.isRed()) && // t is red
2037 (t.getEdgeLevel(EdgeIndex) == t.getFaceLevel()) &&
2038 (t.getEdgeColor(EdgeIndex) == FaceInfo::EDGE_GREEN)
2039 );
2040 }
2041
b_r_Bisection(RgbTriangleC & t,int EdgeIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)2042 void RgbPrimitives::b_r_Bisection(RgbTriangleC& t, int EdgeIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
2043 {
2044 assert(b_r_Bisection_Possible(t,EdgeIndex));
2045 int l = t.getFaceLevel();
2046
2047 RgbTriangleC* tp;
2048 int ti;
2049
2050 tp = &t;
2051 ti = EdgeIndex;
2052
2053 VertexPair vp = tp->getRedEdge();
2054 FaceInfo::FaceColor redtypeu = tp->getFaceColor();
2055 // Store the face obtained with the split
2056 vector<FacePointer> vfp;
2057 // Execute the split
2058 //to.doSplit(e,p,&vfp);
2059 RgbVertexC vNew;
2060 vector<RgbVertexC> vCont;
2061 vector<RgbVertexC> vUpd;
2062
2063 bool todo = RgbPrimitives::doSplit(*tp,ti,l+1,to,&vfp,&vNew,&vCont,&vUpd);
2064 if (!todo)
2065 return; // The update on rgb is already done by doSplit
2066
2067
2068 RgbTriangleC t0 = RgbTriangleC(t.m,t.rgbInfo,vfp[0]->Index());
2069 RgbTriangleC t2 = RgbTriangleC(t.m,t.rgbInfo,vfp[1]->Index());
2070
2071
2072 r_Bisection(l,redtypeu,t2,t0,vp);
2073
2074 assert(triangleCorrectness(t0));
2075 assert(triangleCorrectness(t2));
2076
2077 vector<RgbTriangleC*> vb;
2078 if (t0.isBlue())
2079 vb.push_back(&t0);
2080 if (t2.isBlue())
2081 vb.push_back(&t2);
2082
2083 assert(vb.size() == 1);
2084
2085 if (vt)
2086 {
2087 vt->push_back(t0);
2088 vt->push_back(t2);
2089 }
2090 bb_Swap_If_Needed(*vb[0],vt);
2091
2092 if (stype == LOOP)
2093 distributeContribute(vCont,vNew,vUpd);
2094 return;
2095
2096 }
2097
2098
b_r2_Merge_Possible(RgbTriangleC & t,int VertexIndex)2099 bool RgbPrimitives::b_r2_Merge_Possible(RgbTriangleC& t, int VertexIndex)
2100 {
2101 if (!t.V(VertexIndex).getIsBorder())
2102 return false; // Vertex is NOT on the border
2103
2104 assert(VertexIndex>=0 && VertexIndex <= 2);
2105
2106 vectorRgbTriangle fc;
2107 vf(t,VertexIndex,fc);
2108 vectorFaceColor vcolor;
2109 return
2110 (
2111 (fc.size() == 2) &&
2112 (fc[0].getFaceColor() == FaceInfo::FACE_RED_GGR) &&
2113 (fc[1].getFaceColor() == FaceInfo::FACE_RED_RGG) &&
2114 (fc[0].getFaceLevel() == fc[1].getFaceLevel())
2115 );
2116 }
2117
b_r2_Merge(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)2118 void RgbPrimitives::b_r2_Merge(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
2119 {
2120 assert(VertexIndex>=0 && VertexIndex <= 2);
2121 assert(b_r2_Merge_Possible(t,VertexIndex));
2122
2123 vectorRgbTriangle fc;
2124 vf(t,VertexIndex,fc);
2125 assert(fc.size() == 2);
2126
2127
2128 RgbTriangleC* f0 = &fc[1];
2129 RgbTriangleC* f1 = &fc[0];
2130
2131 // level of one of the red triangles
2132 int l = f0->getFaceLevel();
2133
2134 assert(f0->getFaceColor() == FaceInfo::FACE_RED_RGG);
2135 assert(f1->getFaceColor() == FaceInfo::FACE_RED_GGR);
2136
2137 int fi = (f0->maxLevelVertex()+2)%3;
2138 RgbPrimitives::doCollapse(*f0,fi,to);
2139
2140 f1->setFaceColor(FaceInfo::FACE_GREEN,false);
2141 f1->setFaceLevel(l);
2142
2143 assert(triangleCorrectness(*f1));
2144
2145 if (vt)
2146 {
2147 vt->push_back(*f0);
2148 // Also the adjacent faces may contain vertexes that have to be removed
2149 vt->push_back(fc[0].FF(0));
2150 vt->push_back(fc[0].FF(1));
2151 vt->push_back(fc[0].FF(2));
2152 }
2153
2154 assert(f0->face()->IsD());
2155 assert(!f1->face()->IsD());
2156 }
2157
b_gb_Merge_Possible(RgbTriangleC & t,int VertexIndex)2158 bool RgbPrimitives::b_gb_Merge_Possible(RgbTriangleC& t, int VertexIndex)
2159 {
2160 if (!t.V(VertexIndex).getIsBorder())
2161 return false; // Vertex is NOT on the border
2162
2163 assert(VertexIndex>=0 && VertexIndex <= 2);
2164
2165 vectorRgbTriangle fc;
2166 vf(t,VertexIndex,fc);
2167 vectorFaceColor vcolor;
2168
2169 RgbTriangleC* g;
2170 RgbTriangleC* b;
2171
2172 if (fc.size() != 2)
2173 return false;
2174
2175 if (fc[0].isGreen())
2176 {
2177 g = &fc[0];
2178 b = &fc[1];
2179 if (b->getFaceColor() != FaceInfo::FACE_BLUE_GGR)
2180 return false;
2181 }
2182 else
2183 {
2184 g = &fc[1];
2185 b = &fc[0];
2186 if (b->getFaceColor() != FaceInfo::FACE_BLUE_RGG)
2187 return false;
2188 }
2189
2190 if (!g->isGreen())
2191 return false;
2192
2193 return
2194 (
2195 (b->getFaceLevel()+1 == g->getFaceLevel())
2196 );
2197 }
2198
b_gb_Merge(RgbTriangleC & t,int VertexIndex,TopologicalOpC & to,vector<RgbTriangleC> * vt)2199 void RgbPrimitives::b_gb_Merge(RgbTriangleC& t, int VertexIndex, TopologicalOpC& to, vector<RgbTriangleC>* vt)
2200 {
2201 assert(VertexIndex>=0 && VertexIndex <= 2);
2202 assert(b_gb_Merge_Possible(t,VertexIndex));
2203
2204 vectorRgbTriangle fc;
2205 vf(t,VertexIndex,fc);
2206 assert(fc.size() == 2);
2207 RgbTriangleC* g;
2208 RgbTriangleC* b;
2209
2210 if (fc[0].isGreen())
2211 {
2212 g = &fc[0];
2213 b = &fc[1];
2214 }
2215 else
2216 {
2217 g = &fc[1];
2218 b = &fc[0];
2219 }
2220
2221 // level of the blue triangle
2222 int l = b->getFaceLevel();
2223
2224 assert(g->isGreen());
2225 assert(b->isBlue());
2226
2227 bool isBlueRGG = (b->getFaceColor() == FaceInfo::FACE_BLUE_RGG);
2228 int fi = -1;
2229
2230 for (int i = 0; i < 3; i++)
2231 if (fc[1].getEdgeIsBorder(i))
2232 fi = i;
2233
2234 // Special case if two edge are on the border
2235 if (fc[1].getEdgeIsBorder((fi+1)%3))
2236 fi = (fi+1)%3;
2237
2238 assert(fi != -1);
2239
2240 assert(!fc[1].face()->IsD());
2241 RgbPrimitives::doCollapse(fc[1],fi,to);
2242
2243 if (isBlueRGG)
2244 fc[0].setFaceColor(FaceInfo::FACE_RED_GGR,false);
2245 else
2246 fc[0].setFaceColor(FaceInfo::FACE_RED_RGG,false);
2247
2248 fc[0].setFaceLevel(l);
2249
2250 assert(!fc[0].face()->IsD());
2251 assert(fc[1].face()->IsD());
2252 if (!triangleCorrectness(fc[0]))
2253 {
2254 bool r = triangleCorrectness(fc[0]);
2255 assert(r);
2256 }
2257
2258 if (vt)
2259 {
2260 vt->push_back(fc[0]);
2261 // Also the adjacent faces may contain vertex that has to be removed
2262 vt->push_back(fc[0].FF(0));
2263 vt->push_back(fc[0].FF(1));
2264 vt->push_back(fc[0].FF(2));
2265 }
2266
2267 }
2268
findOppositeVertex(RgbTriangleC & tin,int EdgeIndex,vector<RgbVertexC> * firstVertexes)2269 RgbPrimitives::RgbVertexC RgbPrimitives::findOppositeVertex(RgbTriangleC& tin, int EdgeIndex, vector<RgbVertexC>* firstVertexes)
2270 {
2271 int count = 0;
2272 RgbTriangleC t = tin;
2273 int ti = EdgeIndex;
2274 while (true)
2275 {
2276 if (t.isGreen())
2277 {
2278 return t.V((ti+2)%3);
2279 }
2280 assert(t.isRed());
2281 {
2282 if ((count == 0) && firstVertexes)
2283 {
2284 firstVertexes->push_back(t.V((ti+2)%3));
2285 }
2286 int rei = -1;
2287 for (int i = 0; i < 3; ++i)
2288 {
2289 if (t.getEdgeColor(i) == FaceInfo::EDGE_RED)
2290 rei = i;
2291 }
2292 assert(rei >= 0 && rei <= 2);
2293
2294 RgbTriangleC t1 = t.FF(rei);
2295 int t1i = t.FFi(rei);
2296
2297 assert(t1.isRed() || t1.isBlue());
2298
2299 if (t1.isRed())
2300 {
2301 return t1.V((t1i+2)%3);
2302 }
2303 else
2304 {
2305 assert(t1.isBlue());
2306 RgbTriangleC t2;
2307 int t2i;
2308 // isBlue
2309 if (t1.containVertex(t.V((ti+1)%3).index))
2310 {
2311 t2 = t1.FF((t1i+2)%3);
2312 t2i = t1.FFi((t1i+2)%3);
2313 if ((count == 0) && firstVertexes)
2314 {
2315 firstVertexes->push_back(t1.V((t1i+2)%3));
2316 }
2317
2318 }
2319 else
2320 {
2321 assert(t1.containVertex(t.V(ti).index));
2322 t2 = t1.FF((t1i+1)%3);
2323 t2i = t1.FFi((t1i+1)%3);
2324 if ((count == 0) && firstVertexes)
2325 {
2326 firstVertexes->push_back(t1.V((t1i+2)%3));
2327 }
2328 }
2329
2330 t = t2;
2331 ti = t2i;
2332 t.updateInfo();
2333 assert(t.isGreen() || t.isRed());
2334
2335 }
2336
2337 }
2338 ++count;
2339 }
2340 }
2341
splitGreenEdgeIfNeeded(RgbVertexC & v,int minLevel,TopologicalOpC & to)2342 void RgbPrimitives::splitGreenEdgeIfNeeded(RgbVertexC& v, int minLevel, TopologicalOpC& to)
2343 {
2344 if (stype == LOOP)
2345 {
2346 if ((v.getLevel() == minLevel -1) || (v.getIsPinfReady()) || v.getIsMarked())
2347 return;
2348 }
2349 else
2350 {
2351 if (v.getIsMarked())
2352 return;
2353 }
2354
2355 v.setIsMarked(true);
2356
2357 bool split = true;
2358 while(split)
2359 {
2360 split = false;
2361 int level;
2362 int i = 0;
2363
2364 FacePointer fp = v.vert().VFp();
2365 int fi = v.vert().VFi();
2366 vcg::face::Pos<FaceType> pos(fp,fi);
2367
2368 if (v.getIsBorder()) // if is border move cw until the border is found
2369 {
2370 pos.FlipE();
2371 pos.FlipF();
2372
2373 while (!pos.IsBorder())
2374 {
2375 pos.FlipE();
2376 pos.FlipF();
2377 }
2378
2379 pos.FlipE();
2380 }
2381
2382 CMeshO::FacePointer first = pos.F();
2383
2384 RgbTriangleC tmp = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2385 assert(tmp.containVertex(v.index));
2386 tmp.containVertex(v.index,&i);
2387 assert(i>=0 && i<= 2);
2388 level = tmp.getEdgeLevel(i);
2389
2390 if (level < (minLevel - 1) && tmp.getEdgeColor(i) == FaceInfo::EDGE_GREEN)
2391 {
2392 split = RgbPrimitives::recursiveEdgeSplit(tmp,i,to);
2393 if (split)
2394 continue;
2395 }
2396
2397 pos.FlipF();
2398 pos.FlipE();
2399
2400 while(pos.F() && (pos.F() != first))
2401 {
2402 RgbTriangleC tmp = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2403 assert(tmp.containVertex(v.index));
2404 tmp.containVertex(v.index,&i);
2405 assert(i>=0 && i<= 2);
2406
2407 level = tmp.getEdgeLevel(i);
2408 if (level < (minLevel -1 ) && tmp.getEdgeColor(i) == FaceInfo::EDGE_GREEN)
2409 {
2410 split = RgbPrimitives::recursiveEdgeSplit(tmp,i,to);
2411 if (split)
2412 break;
2413 }
2414
2415 pos.FlipF();
2416 pos.FlipE();
2417 assert(pos.F()->V(0) == fp->V(fi) || pos.F()->V(1) == fp->V(fi) || pos.F()->V(2) == fp->V(fi));
2418 assert(!fp->IsD());
2419 }
2420
2421
2422 }
2423
2424 v.setIsMarked(false);
2425 if (RgbPrimitives::stype == LOOP)
2426 {
2427 assert(v.getIsPinfReady());
2428 }
2429 }
2430
splitRedEdgeIfNeeded(RgbVertexC & v,int minLevel,TopologicalOpC & to)2431 void RgbPrimitives::splitRedEdgeIfNeeded(RgbVertexC& v, int minLevel, TopologicalOpC& to)
2432 {
2433 bool split = true;
2434
2435 while(split)
2436 {
2437 split = false;
2438 int level;
2439 int i = 0;
2440
2441 FacePointer fp = v.vert().VFp();
2442 int fi = v.vert().VFi();
2443 vcg::face::Pos<FaceType> pos(fp,fi);
2444
2445 if (v.getIsBorder()) // if is border move cw until the border is found
2446 {
2447 pos.FlipE();
2448 pos.FlipF();
2449
2450 while (!pos.IsBorder())
2451 {
2452 pos.FlipE();
2453 pos.FlipF();
2454 }
2455
2456 pos.FlipE();
2457 }
2458
2459 CMeshO::FacePointer first = pos.F();
2460
2461 RgbTriangleC tmp = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2462 assert(tmp.containVertex(v.index));
2463 tmp.containVertex(v.index,&i);
2464 assert(i>=0 && i<= 2);
2465 // ----------
2466 level = tmp.getEdgeLevel(i);
2467 if (level < (minLevel - 1) && tmp.getEdgeColor(i) == FaceInfo::EDGE_RED)
2468 {
2469 if (tmp.isRed())
2470 {
2471 assert(tmp.getEdgeColor((i+1)%3) == FaceInfo::EDGE_GREEN);
2472 assert(tmp.getEdgeColor((i+2)%3) == FaceInfo::EDGE_GREEN);
2473 assert(tmp.getEdgeColor((i)%3) == FaceInfo::EDGE_RED);
2474
2475 if (tmp.getEdgeLevel((i+1)%3) <= tmp.getEdgeLevel((i+2)%3))
2476 {
2477 split = RgbPrimitives::recursiveEdgeSplit(tmp,(i+1)%3,to);
2478 }
2479 else
2480 {
2481 split = RgbPrimitives::recursiveEdgeSplit(tmp,(i+2)%3,to);
2482 }
2483
2484 }
2485 if (split)
2486 continue;
2487
2488 RgbTriangleC tmp2 = tmp.FF(i);
2489 int i2 = tmp.FFi(i);
2490 if (tmp2.isRed())
2491 {
2492 assert(tmp2.getEdgeColor((i2+1)%3) == FaceInfo::EDGE_GREEN);
2493 assert(tmp2.getEdgeColor((i2+2)%3) == FaceInfo::EDGE_GREEN);
2494 assert(tmp2.getEdgeColor((i2)%3) == FaceInfo::EDGE_RED);
2495
2496 if (tmp2.getEdgeLevel((i2+1)%3) <= tmp2.getEdgeLevel((i2+2)%3))
2497 {
2498 split = RgbPrimitives::recursiveEdgeSplit(tmp2,(i2+1)%3,to);
2499 }
2500 else
2501 {
2502 split = RgbPrimitives::recursiveEdgeSplit(tmp2,(i2+2)%3,to);
2503 }
2504
2505 }
2506 assert(split);
2507 if (split)
2508 continue;
2509
2510 }
2511 // ----------
2512
2513 pos.FlipF();
2514 pos.FlipE();
2515
2516 while(pos.F() && (pos.F() != first))
2517 {
2518 RgbTriangleC tmp = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2519 assert(tmp.containVertex(v.index));
2520 tmp.containVertex(v.index,&i);
2521 assert(i>=0 && i<= 2);
2522 // ----------
2523 level = tmp.getEdgeLevel(i);
2524 if (level < (minLevel - 1) && tmp.getEdgeColor(i) == FaceInfo::EDGE_RED)
2525 {
2526 if (tmp.isRed())
2527 {
2528 if (tmp.getEdgeLevel((i+1)%3) < tmp.getEdgeLevel((i+2)%3))
2529 {
2530 split = RgbPrimitives::recursiveEdgeSplit(tmp,(i+1)%3,to);
2531 }
2532 else
2533 {
2534 split = RgbPrimitives::recursiveEdgeSplit(tmp,(i+2)%3,to);
2535 }
2536
2537 }
2538 if (split)
2539 break;
2540
2541 RgbTriangleC tmp2 = tmp.FF(i);
2542 int i2 = tmp.FFi(i);
2543 if (tmp2.isRed())
2544 {
2545 if (tmp2.getEdgeLevel((i2+1)%3) < tmp2.getEdgeLevel((i2+2)%3))
2546 split = RgbPrimitives::recursiveEdgeSplit(tmp2,(i2+1)%3,to);
2547 else
2548 split = RgbPrimitives::recursiveEdgeSplit(tmp2,(i2+2)%3,to);
2549
2550 }
2551 if (split)
2552 break;
2553
2554 }
2555 if (split)
2556 continue;
2557 // ----------
2558 pos.FlipF();
2559 pos.FlipE();
2560 assert(pos.F()->V(0) == fp->V(fi) || pos.F()->V(1) == fp->V(fi) || pos.F()->V(2) == fp->V(fi));
2561 assert(!fp->IsD());
2562 }
2563
2564
2565 }
2566 }
2567
VF(RgbVertexC & v,vector<FacePointer> & vfp)2568 void RgbPrimitives::VF(RgbVertexC& v,vector<FacePointer>& vfp)
2569 {
2570 assert(!v.vert().IsD());
2571 bool isBorder = v.getIsBorder();
2572
2573 vcg::face::Pos<FaceType> pos(v.vert().VFp(),v.vert().VFi());
2574
2575 RgbTriangleC t = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2576
2577 if (t.getNumberOfBoundaryEdge(&v) >= 2)
2578 {
2579 vfp.push_back(pos.F());
2580 return;
2581 }
2582
2583 if (isBorder) // if is border move cw until the border is found
2584 {
2585 pos.FlipE();
2586 pos.FlipF();
2587
2588 while (!pos.IsBorder())
2589 {
2590 pos.FlipE();
2591 pos.FlipF();
2592 }
2593
2594 pos.FlipE();
2595 }
2596
2597
2598 CMeshO::FacePointer first = pos.F();
2599 vfp.push_back(pos.F());
2600 pos.FlipF();
2601 pos.FlipE();
2602
2603 while(pos.F() && (pos.F() != first))
2604 {
2605 vfp.push_back(pos.F());
2606
2607 pos.FlipF();
2608 pos.FlipE();
2609 }
2610
2611 }
2612
updateNormal(RgbVertexC & v)2613 void RgbPrimitives::updateNormal(RgbVertexC& v)
2614 {
2615 vector<FacePointer> vfp;
2616 vfp.reserve(6);
2617 RgbPrimitives::VF(v,vfp);
2618 Point3f vnorm(0,0,0);
2619 int count = 0;
2620 for (unsigned int i = 0; i < vfp.size(); ++i)
2621 {
2622 vcg::face::ComputeNormal(*(vfp[i]));
2623 vnorm += vfp[i]->cN();
2624 ++count;
2625 }
2626 vnorm /= count;
2627 v.vert().N() = vnorm;
2628 }
2629
VV(RgbVertexC & v,vector<RgbVertexC> & vv,bool onlyGreenEdge)2630 void RgbPrimitives::VV(RgbVertexC& v, vector<RgbVertexC>& vv, bool onlyGreenEdge)
2631 {
2632 // This VV is cw
2633
2634 int i = 0;
2635 FacePointer fp = v.vert().VFp();
2636 int fi = v.vert().VFi();
2637 assert(fp->V(fi) == &(v.vert()));
2638 bool isBorder = v.getIsBorder();
2639
2640 vcg::face::Pos<FaceType> pos(fp,fi);
2641
2642 RgbTriangleC t = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2643
2644 if (t.getNumberOfBoundaryEdge(&v) >= 2)
2645 {
2646 int index;
2647 bool res = t.containVertex(v.index, &index);
2648 assert(res);
2649
2650 if (!onlyGreenEdge)
2651 {
2652 vv.push_back(t.V((index+1)%3));
2653 vv.push_back(t.V((index+2)%3));
2654 }
2655 else
2656 {
2657 if ((t.getEdgeColor(index) == FaceInfo::EDGE_GREEN) && (t.getEdgeLevel(index) > t.getVl(index)))
2658 {
2659 vv.push_back(t.V((index+1)%3));
2660 }
2661 if ((t.getEdgeColor((index+2)%3) == FaceInfo::EDGE_GREEN) && (t.getEdgeLevel((index+2)%3) > t.getVl((index))))
2662 {
2663 vv.push_back(t.V((index+2)%3));
2664 }
2665 }
2666
2667 return;
2668 }
2669
2670 if (isBorder) // if is border move ccw until the border is found
2671 {
2672 pos.FlipE();
2673 pos.FlipF();
2674
2675 while (!pos.IsBorder())
2676 {
2677 pos.FlipE();
2678 pos.FlipF();
2679 }
2680
2681 pos.FlipE();
2682 }
2683
2684 CMeshO::FacePointer first = pos.F();
2685
2686 RgbTriangleC tmp = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2687
2688 assert(tmp.containVertex(v.index));
2689 tmp.containVertex(v.index,&i);
2690 assert(i>=0 && i<= 2);
2691 assert(tmp.V(i).index == v.index);
2692
2693 if (!onlyGreenEdge)
2694 {
2695 if (isBorder)
2696 vv.push_back(tmp.V((i+2)%3)); // we cannot scan all the triangle around the vertex,
2697 // we have to save the last vertex
2698 vv.push_back(tmp.V((i+1)%3));
2699 }
2700 else
2701 {
2702 if (isBorder && (tmp.getEdgeColor((i+2)%3) == FaceInfo::EDGE_GREEN) && (tmp.getEdgeLevel((i+2)%3) > tmp.getVl(i)))
2703 vv.push_back(tmp.V((i+2)%3));
2704
2705 if ((tmp.getEdgeColor(i) == FaceInfo::EDGE_GREEN) && (tmp.getEdgeLevel(i) > tmp.getVl(i)))
2706 vv.push_back(tmp.V((i+1)%3));
2707 }
2708
2709
2710 pos.FlipF();
2711 pos.FlipE();
2712
2713 while(pos.F() != first)
2714 {
2715 RgbTriangleC tmp = RgbTriangleC(v.m,v.rgbInfo,pos.F()->Index());
2716 assert(tmp.containVertex(v.index));
2717 tmp.containVertex(v.index,&i);
2718 assert(i>=0 && i<= 2);
2719
2720 if (!onlyGreenEdge)
2721 {
2722 vv.push_back(tmp.V((i+1)%3));
2723 }
2724 else
2725 {
2726 if ((tmp.getEdgeColor(i) == FaceInfo::EDGE_GREEN) && (tmp.getEdgeLevel(i) > tmp.getVl(i)))
2727 vv.push_back(tmp.V((i+1)%3));
2728 }
2729
2730 if (pos.IsBorder())
2731 {
2732 break;
2733 }
2734
2735 pos.FlipF();
2736 pos.FlipE();
2737 assert(pos.F()->V(0) == fp->V(fi) || pos.F()->V(1) == fp->V(fi) || pos.F()->V(2) == fp->V(fi));
2738 assert(!fp->IsD());
2739 }
2740 }
2741
baseIncidentEdges(RgbVertexC & v)2742 unsigned int RgbPrimitives::baseIncidentEdges(RgbVertexC& v)
2743 {
2744 int rank;
2745 if (v.getLevel() > 0)
2746 {
2747 rank = 6;
2748 }
2749 else
2750 {
2751 rank = v.getBaseArity();
2752 }
2753 return rank;
2754 }
2755
2756 }
2757