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