Merged changes in the trunk up to revision 53146.
[blender.git] / source / blender / freestyle / intern / view_map / ViewEdgeXBuilder.cpp
1 //
2 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
3 //   with this source distribution. 
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 2
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 //
19 ///////////////////////////////////////////////////////////////////////////////
20
21 #include "ViewMap.h"
22 #include "ViewEdgeXBuilder.h"
23 #include "../winged_edge/WXEdge.h"
24 #include "SilhouetteGeomEngine.h"
25 #include <list>
26
27 using namespace std;
28
29 void ViewEdgeXBuilder::Init(ViewShape *oVShape){
30   if(0 == oVShape)
31     return;
32
33   // for design conveniance, we store the current SShape.
34   _pCurrentSShape = oVShape->sshape();
35   if(0 == _pCurrentSShape)
36     return;
37
38   _pCurrentVShape = oVShape;
39   
40   // Reset previous data
41   //--------------------
42   if(!_SVertexMap.empty())
43     _SVertexMap.clear();
44 }
45
46 void ViewEdgeXBuilder::BuildViewEdges( WXShape *iWShape, ViewShape *oVShape, 
47                                       vector<ViewEdge*>& ioVEdges, 
48                                       vector<ViewVertex*>& ioVVertices,
49                                       vector<FEdge*>& ioFEdges,
50                                       vector<SVertex*>& ioSVertices){
51   // Reinit structures
52   Init(oVShape);
53
54   ViewEdge *vedge ;
55   // Let us build the smooth stuff 
56   //----------------------------------------  
57   // We parse all faces to find the ones 
58   // that contain smooth edges
59   vector<WFace*>& wfaces = iWShape->GetFaceList();
60   vector<WFace*>::iterator wf, wfend;
61   WXFace *wxf;
62   for(wf=wfaces.begin(), wfend=wfaces.end();
63   wf!=wfend;
64   wf++){
65     wxf = dynamic_cast<WXFace*>(*wf);
66     if(false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ?
67       continue;
68     // parse all smooth layers:
69     vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers();
70     for(vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend=smoothLayers.end();
71     sl!=slend;
72     ++sl){
73       if(!(*sl)->hasSmoothEdge())
74         continue;
75       if(stopSmoothViewEdge((*sl))) // has it been parsed already ?
76         continue;
77       // here we know that we're dealing with a face layer that has not been 
78       // processed yet and that contains a smooth edge.
79       vedge = BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
80     }
81   }
82   
83   // Now let's build sharp view edges:
84   //----------------------------------
85   // Reset all userdata for WXEdge structure
86   //----------------------------------------
87   //iWShape->ResetUserData();
88   
89   WXEdge * wxe;
90   vector<WEdge*>& wedges = iWShape->getEdgeList();
91   // 
92   //------------------------------
93   for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end();
94   we!=weend;
95   we++){
96     wxe = dynamic_cast<WXEdge*>(*we);
97     if(Nature::NO_FEATURE == wxe->nature())
98       continue;
99     
100     if(!stopSharpViewEdge(wxe)){
101       bool b=true;
102       if(wxe->order() == -1)
103         b = false;
104       BuildSharpViewEdge(OWXEdge(wxe,b));
105     }
106   }
107
108   // Reset all userdata for WXEdge structure
109   //----------------------------------------
110   iWShape->ResetUserData();
111  
112   // Add all these new edges to the scene's feature edges list:
113   //-----------------------------------------------------------
114   vector<FEdge*>& newedges = _pCurrentSShape->getEdgeList();
115   vector<SVertex*>& newVertices = _pCurrentSShape->getVertexList();
116   vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices();
117   vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges();
118
119   // inserts in ioFEdges, at its end, all the edges of newedges
120   ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
121   ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
122   ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
123   ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
124
125 }
126
127 ViewEdge * ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer){
128   // Find first edge:
129   OWXFaceLayer first = iFaceLayer;
130   OWXFaceLayer currentFace = first;
131   
132   // bidirectional chaining.
133   // first direction
134   list<OWXFaceLayer> facesChain;
135   unsigned size  = 0;
136   while(!stopSmoothViewEdge(currentFace.fl)){
137     facesChain.push_back(currentFace);
138     ++size;
139     currentFace.fl->userdata = (void*)1; // processed
140     // Find the next edge!
141     currentFace =  FindNextFaceLayer(currentFace);
142   }
143   OWXFaceLayer end = facesChain.back();
144   // second direction
145   currentFace = FindPreviousFaceLayer(first);
146   while(!stopSmoothViewEdge(currentFace.fl)){
147     facesChain.push_front(currentFace);
148     ++size;
149     currentFace.fl->userdata = (void*)1; // processed
150     // Find the previous edge!
151     currentFace =  FindPreviousFaceLayer(currentFace);
152   }
153   first = facesChain.front();
154   
155   if(iFaceLayer.fl->nature() & Nature::RIDGE){
156     if(size<4){
157       return 0;
158     }
159   }
160   
161   // Start a new chain edges
162   ViewEdge * newVEdge = new ViewEdge;
163   newVEdge->setId(_currentViewId);
164   ++_currentViewId;
165   
166   _pCurrentVShape->AddEdge(newVEdge);
167   
168
169   // build FEdges
170   FEdge * feprevious = 0;
171   FEdge * fefirst = 0;
172   FEdge * fe = 0;
173   for(list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend=facesChain.end();
174   fl!=flend;
175   ++fl){
176     fe = BuildSmoothFEdge(feprevious, (*fl));
177     if (feprevious && fe == feprevious)
178       continue;
179     fe->setViewEdge(newVEdge);
180     if(!fefirst)
181       fefirst = fe;
182     feprevious = fe;
183   }
184   // Store the chain starting edge:
185   _pCurrentSShape->AddChain(fefirst);
186   newVEdge->setNature(iFaceLayer.fl->nature());
187   newVEdge->setFEdgeA(fefirst);
188   newVEdge->setFEdgeB(fe);
189
190   // is it a closed loop ?
191   if((first == end) && (size != 1)){
192     fefirst->setPreviousEdge(fe);
193     fe->setNextEdge(fefirst);
194     newVEdge->setA(0);
195     newVEdge->setB(0);
196   }else{
197     ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
198     ViewVertex *vvb = MakeViewVertex(fe->vertexB());
199         
200     ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge);
201     ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge);
202
203     newVEdge->setA(vva);
204     newVEdge->setB(vvb);
205   } 
206   
207   return newVEdge;
208 }
209
210 ViewEdge * ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge) {
211   // Start a new sharp chain edges
212   ViewEdge * newVEdge = new ViewEdge;
213   newVEdge->setId(_currentViewId);
214   ++_currentViewId;
215   unsigned size=0;
216   
217   _pCurrentVShape->AddEdge(newVEdge);
218   
219   // Find first edge:
220   OWXEdge firstWEdge = iWEdge;
221   OWXEdge previousWEdge = firstWEdge;
222   OWXEdge currentWEdge = firstWEdge;
223   list<OWXEdge> edgesChain;
224 #if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */
225   // bidirectional chaining
226   // first direction:
227   while(!stopSharpViewEdge(currentWEdge.e)){
228     edgesChain.push_back(currentWEdge);
229     ++size;
230     currentWEdge.e->userdata = (void*)1; // processed
231     // Find the next edge!
232     currentWEdge =  FindNextWEdge(currentWEdge);
233   }
234   OWXEdge endWEdge = edgesChain.back();
235   // second direction
236   currentWEdge = FindPreviousWEdge(firstWEdge);
237   while(!stopSharpViewEdge(currentWEdge.e)){
238     edgesChain.push_front(currentWEdge);
239     ++size;
240     currentWEdge.e->userdata = (void*)1; // processed
241     // Find the previous edge!
242     currentWEdge =  FindPreviousWEdge(currentWEdge);
243   }
244 #else
245   edgesChain.push_back(currentWEdge);
246   ++size;
247   currentWEdge.e->userdata = (void*)1; // processed
248   OWXEdge endWEdge = edgesChain.back();
249 #endif
250   firstWEdge = edgesChain.front();
251
252   // build FEdges
253   FEdge * feprevious = 0;
254   FEdge * fefirst = 0;
255   FEdge * fe = 0;
256   for(list<OWXEdge>::iterator we = edgesChain.begin(), weend=edgesChain.end();
257   we!=weend;
258   ++we){
259     fe = BuildSharpFEdge(feprevious, (*we));
260     fe->setViewEdge(newVEdge);
261     if(!fefirst)
262       fefirst = fe;
263     feprevious = fe;
264   }
265   // Store the chain starting edge:
266   _pCurrentSShape->AddChain(fefirst);
267   newVEdge->setNature(iWEdge.e->nature());
268   newVEdge->setFEdgeA(fefirst);
269   newVEdge->setFEdgeB(fe);
270
271   // is it a closed loop ?
272   if((firstWEdge == endWEdge) && (size!=1)){
273     fefirst->setPreviousEdge(fe);
274     fe->setNextEdge(fefirst);
275     newVEdge->setA(0);
276     newVEdge->setB(0);
277   }else{
278     ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
279     ViewVertex *vvb = MakeViewVertex(fe->vertexB());
280         
281     ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge);
282     ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge);
283
284     newVEdge->setA(vva);
285     newVEdge->setB(vvb);
286   }
287
288   return newVEdge;
289 }
290
291 OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer& iFaceLayer){
292   WXFace *nextFace = 0;
293   WOEdge * woeend;
294   real tend;
295   if(iFaceLayer.order){
296     woeend = iFaceLayer.fl->getSmoothEdge()->woeb();
297     tend = iFaceLayer.fl->getSmoothEdge()->tb();
298   }else{
299     woeend = iFaceLayer.fl->getSmoothEdge()->woea();
300     tend = iFaceLayer.fl->getSmoothEdge()->ta();
301   }
302   // special case of EDGE_VERTEX config:
303   if((tend == 0.0) || (tend == 1.0)){
304     WVertex *nextVertex;
305     if(tend == 0.0)
306       nextVertex = woeend->GetaVertex();
307     else
308       nextVertex = woeend->GetbVertex();
309     if(nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
310       return OWXFaceLayer(0,true);
311     bool found = false;
312     WVertex::face_iterator f=nextVertex->faces_begin();
313     WVertex::face_iterator fend=nextVertex->faces_end();
314     while((!found) && (f!=fend)){
315       nextFace = dynamic_cast<WXFace*>(*f);
316       if((0 != nextFace) && (nextFace!=iFaceLayer.fl->getFace())){
317         vector<WXFaceLayer*> sameNatureLayers;
318         nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
319         if(sameNatureLayers.size() == 1) {// don't know 
320           // maybe should test whether this face has 
321           // also a vertex_edge configuration
322           WXFaceLayer * winner = sameNatureLayers[0];
323                   // check face mark continuity
324                   if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
325                         return OWXFaceLayer(0,true);
326           if(woeend == winner->getSmoothEdge()->woea()->twin())
327             return OWXFaceLayer(winner,true);
328           else
329             return OWXFaceLayer(winner,false);
330         }
331       }
332       ++f;
333     }
334   }else{
335     nextFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woeend));
336     if(0 == nextFace)
337       return OWXFaceLayer(0,true);
338     // if the next face layer has either no smooth edge or 
339     // no smooth edge of same nature, no next face
340     if(!nextFace->hasSmoothEdges())
341       return OWXFaceLayer(0,true);
342     vector<WXFaceLayer*> sameNatureLayers;
343     nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
344     if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face
345       return OWXFaceLayer(0,true);
346     else{
347       WXFaceLayer * winner = sameNatureLayers[0];
348           // check face mark continuity
349           if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
350                 return OWXFaceLayer(0,true);
351       if(woeend == winner->getSmoothEdge()->woea()->twin())
352         return OWXFaceLayer(winner,true);
353       else
354         return OWXFaceLayer(winner,false);
355     } 
356   }
357   return OWXFaceLayer(0,true);
358 }
359
360 OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer) {
361   WXFace *previousFace = 0;
362   WOEdge * woebegin;
363   real tend;
364   if(iFaceLayer.order){
365     woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
366     tend = iFaceLayer.fl->getSmoothEdge()->ta();
367   }else{
368     woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
369     tend = iFaceLayer.fl->getSmoothEdge()->tb();
370   }
371
372   // special case of EDGE_VERTEX config:
373   if((tend == 0.0) || (tend == 1.0)){
374     WVertex *previousVertex;
375     if(tend == 0.0)
376       previousVertex = woebegin->GetaVertex();
377     else
378       previousVertex = woebegin->GetbVertex();
379     if(previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
380       return OWXFaceLayer(0,true);
381     bool found = false;
382     WVertex::face_iterator f=previousVertex->faces_begin();
383     WVertex::face_iterator fend=previousVertex->faces_end();
384     while((!found) && (f!=fend)){
385       previousFace = dynamic_cast<WXFace*>(*f);
386       if((0 != previousFace) && (previousFace!=iFaceLayer.fl->getFace())){
387         vector<WXFaceLayer*> sameNatureLayers;
388         previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
389         if(sameNatureLayers.size() == 1) {// don't know 
390           // maybe should test whether this face has 
391           // also a vertex_edge configuration
392           WXFaceLayer * winner = sameNatureLayers[0];
393                   // check face mark continuity
394                   if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
395                         return OWXFaceLayer(0,true);
396           if(woebegin == winner->getSmoothEdge()->woeb()->twin())
397             return OWXFaceLayer(winner,true);
398           else
399             return OWXFaceLayer(winner,false);
400         }
401       }
402       ++f;
403     }
404   }else{
405     previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
406     if(0 == previousFace)
407       return OWXFaceLayer(0,true);
408     
409     // if the next face layer has either no smooth edge or 
410     // no smooth edge of same nature, no next face
411     if(!previousFace->hasSmoothEdges())
412       return OWXFaceLayer(0,true);
413     vector<WXFaceLayer*> sameNatureLayers;
414     previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
415     if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face
416       return OWXFaceLayer(0,true);
417     else{
418       WXFaceLayer * winner = sameNatureLayers[0];
419           // check face mark continuity
420           if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
421             return OWXFaceLayer(0,true);
422       if(woebegin == winner->getSmoothEdge()->woeb()->twin())
423         return OWXFaceLayer(winner,true);
424       else
425         return OWXFaceLayer(winner,false);
426     }
427   }
428   return OWXFaceLayer(0,true);
429 }
430
431 FEdge * ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl){
432   WOEdge *woea, *woeb;
433   real ta, tb;
434   SVertex *va, *vb;
435   FEdgeSmooth *fe;
436   // retrieve exact silhouette data
437   WXSmoothEdge *se = ifl.fl->getSmoothEdge();
438
439   if (ifl.order) {
440     woea = se->woea();
441     woeb = se->woeb();
442         ta = se->ta();
443         tb = se->tb();
444   } else {
445     woea = se->woeb();
446     woeb = se->woea();
447         ta = se->tb();
448         tb = se->ta();
449   }
450
451   Vec3r normal;
452   // Make the 2 Svertices
453   if(feprevious == 0){ // that means that we don't have any vertex already built for that face
454     Vec3r A1(woea->GetaVertex()->GetVertex());
455     Vec3r A2(woea->GetbVertex()->GetVertex());
456     Vec3r A(A1+ta*(A2-A1));
457     
458     va = MakeSVertex(A, false);
459     // Set normal:
460     Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex()));
461     Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex()));
462     Vec3r na((1 - ta) * NA1 + ta * NA2);
463     na.normalize();
464     va->AddNormal(na);
465     normal = na;
466
467     // Set CurvatureInfo
468     CurvatureInfo* curvature_info_a = new CurvatureInfo(
469                 *(dynamic_cast<WXVertex*>(woea->GetaVertex())->curvatures()),
470                 *(dynamic_cast<WXVertex*>(woea->GetbVertex())->curvatures()),
471                 ta);
472     va->setCurvatureInfo(curvature_info_a);
473   }
474   else
475     va = feprevious->vertexB();
476
477   Vec3r B1(woeb->GetaVertex()->GetVertex());
478   Vec3r B2(woeb->GetbVertex()->GetVertex());
479   Vec3r B(B1+tb*(B2-B1));
480
481   if (feprevious && (B - va->point3D()).norm() < 1e-6)
482         return feprevious;
483
484   vb = MakeSVertex(B, false);
485   // Set normal:
486   Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex()));
487   Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex()));
488   Vec3r nb((1 - tb) * NB1 + tb * NB2);
489   nb.normalize();
490   normal += nb;
491   vb->AddNormal(nb);
492
493   // Set CurvatureInfo
494   CurvatureInfo* curvature_info_b = new CurvatureInfo(
495           *(dynamic_cast<WXVertex*>(woeb->GetaVertex())->curvatures()),
496           *(dynamic_cast<WXVertex*>(woeb->GetbVertex())->curvatures()),
497           tb);
498   vb->setCurvatureInfo(curvature_info_b);
499
500   // Creates the corresponding feature edge
501   fe = new FEdgeSmooth(va, vb);
502   fe->setNature(ifl.fl->nature());
503   fe->setId(_currentFId);
504   fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex());
505   fe->setFace(ifl.fl->getFace());
506   fe->setFaceMark(ifl.fl->getFace()->GetMark());
507   if(feprevious == 0)
508           normal.normalize();
509   fe->setNormal(normal);
510   fe->setPreviousEdge(feprevious);
511   if(feprevious)
512     feprevious->setNextEdge(fe);
513   _pCurrentSShape->AddEdge(fe);
514   va->AddFEdge(fe);
515   vb->AddFEdge(fe);
516   
517   ++_currentFId;
518   ifl.fl->userdata = fe;
519   return fe;
520 }
521
522 bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer){
523   if(0 == iFaceLayer)
524     return true;
525   if(iFaceLayer->userdata == 0)
526     return false;
527   return true;
528 }
529
530 int ViewEdgeXBuilder::retrieveFaceMarks(WXEdge *iEdge)
531 {
532   WFace *aFace = iEdge->GetaFace();
533   WFace *bFace = iEdge->GetbFace();
534   int result = 0;
535   if (aFace && aFace->GetMark())
536     result += 1;
537   if (bFace && bFace->GetMark())
538     result += 2;
539   return result;
540 }
541
542 OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge& iEdge){
543   if(Nature::NO_FEATURE == iEdge.e->nature())
544     return OWXEdge(0, true);
545
546   WVertex *v;
547   if(true == iEdge.order)
548     v = iEdge.e->GetbVertex();
549   else
550     v = iEdge.e->GetaVertex();
551
552   if(((WXVertex*)v)->isFeature())
553     return 0;
554
555   
556   int faceMarks = retrieveFaceMarks(iEdge.e);
557   vector<WEdge*>& vEdges = (v)->GetEdges();
558   for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end();
559   ve!=veend;
560   ve++){ 
561     WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
562     if(wxe == iEdge.e)
563       continue; // same edge as the one processed
564
565     if(wxe->nature() != iEdge.e->nature())
566       continue;
567       
568         // check face mark continuity
569         if(retrieveFaceMarks(wxe) != faceMarks)
570           continue;
571
572     if(wxe->GetaVertex() == v){
573      // That means that the face necesarily lies on the edge left.
574      // So the vertex order is OK.
575       return OWXEdge(wxe, true);
576     }else{
577       // That means that the face necesarily lies on the edge left.
578       // So the vertex order is OK.
579       return OWXEdge(wxe, false);
580     }  
581   }   
582   // we did not find:
583   return OWXEdge(0, true);
584 }
585
586 OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge& iEdge){
587   if(Nature::NO_FEATURE == iEdge.e->nature())
588     return OWXEdge(0, true);
589
590   WVertex *v;
591   if(true == iEdge.order)
592     v = iEdge.e->GetaVertex();
593   else
594     v = iEdge.e->GetbVertex();
595
596   if(((WXVertex*)v)->isFeature())
597     return 0;
598
599   
600   int faceMarks = retrieveFaceMarks(iEdge.e);
601   vector<WEdge*>& vEdges = (v)->GetEdges();
602   for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end();
603   ve!=veend;
604   ve++){ 
605     WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
606     if(wxe == iEdge.e)
607       continue; // same edge as the one processed
608
609     if(wxe->nature() != iEdge.e->nature())
610       continue;
611       
612         // check face mark continuity
613         if(retrieveFaceMarks(wxe) != faceMarks)
614           continue;
615
616     if(wxe->GetbVertex() == v){
617       return OWXEdge(wxe, true);
618     }else{
619       return OWXEdge(wxe, false);
620     }  
621   }   
622   // we did not find:
623   return OWXEdge(0, true);
624 }
625
626 FEdge * ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe){
627   SVertex *va, *vb;
628   FEdgeSharp *fe;
629   WXVertex *wxVA, *wxVB;
630   if(iwe.order){
631     wxVA = (WXVertex*)iwe.e->GetaVertex();
632     wxVB = (WXVertex*)iwe.e->GetbVertex();
633   }else{
634     wxVA = (WXVertex*)iwe.e->GetbVertex();
635     wxVB = (WXVertex*)iwe.e->GetaVertex();
636   }
637   // Make the 2 SVertex
638   va = MakeSVertex(wxVA->GetVertex(), true);
639   vb = MakeSVertex(wxVB->GetVertex(), true);
640
641   // get the faces normals and the material indices
642   Vec3r normalA, normalB;
643   unsigned matA(0), matB(0);
644   bool faceMarkA = false, faceMarkB = false;
645   if(iwe.order){
646     normalB = (iwe.e->GetbFace()->GetNormal());
647     matB    = (iwe.e->GetbFace()->frs_materialIndex());
648     faceMarkB = (iwe.e->GetbFace()->GetMark());
649     if(!(iwe.e->nature() & Nature::BORDER)) {  
650       normalA = (iwe.e->GetaFace()->GetNormal());
651       matA    = (iwe.e->GetaFace()->frs_materialIndex());
652       faceMarkA = (iwe.e->GetaFace()->GetMark());
653     }
654   }else{
655     normalA = (iwe.e->GetbFace()->GetNormal());
656     matA    = (iwe.e->GetbFace()->frs_materialIndex());
657     faceMarkA = (iwe.e->GetbFace()->GetMark());
658     if(!(iwe.e->nature() & Nature::BORDER)) { 
659       normalB = (iwe.e->GetaFace()->GetNormal());
660       matB    = (iwe.e->GetaFace()->frs_materialIndex());
661       faceMarkB = (iwe.e->GetaFace()->GetMark());
662     }
663   }
664   // Creates the corresponding feature edge
665   // Creates the corresponding feature edge
666   fe = new FEdgeSharp(va, vb);
667   fe->setNature(iwe.e->nature());
668   fe->setId(_currentFId);
669   fe->setaFrsMaterialIndex(matA);
670   fe->setbFrsMaterialIndex(matB);
671   fe->setaFaceMark(faceMarkA);
672   fe->setbFaceMark(faceMarkB);
673   fe->setNormalA(normalA);
674   fe->setNormalB(normalB);
675   fe->setPreviousEdge(feprevious);
676   if(feprevious)
677     feprevious->setNextEdge(fe);
678   _pCurrentSShape->AddEdge(fe);
679   va->AddFEdge(fe);
680   vb->AddFEdge(fe);
681   //Add normals:
682   va->AddNormal(normalA);
683   va->AddNormal(normalB);
684   vb->AddNormal(normalA);
685   vb->AddNormal(normalB);
686   
687   ++_currentFId;
688   iwe.e->userdata = fe;
689   return fe;
690 }
691
692 bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge){
693   if(0 == iEdge)
694     return true;
695   if(iEdge->userdata == 0)
696     return false;
697   return true;
698 }
699
700 SVertex * ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint){
701   SVertex *va = new SVertex(iPoint, _currentSVertexId);
702   SilhouetteGeomEngine::ProjectSilhouette(va);
703   ++_currentSVertexId;
704   // Add the svertex to the SShape svertex list:
705   _pCurrentSShape->AddNewVertex(va);
706   return va;
707 }
708
709 SVertex * ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint, bool shared){
710   SVertex *va;
711   if (!shared) {
712         va = MakeSVertex(iPoint);
713   } else {
714         // Check whether the iPoint is already in the table
715         SVertexMap::const_iterator found = _SVertexMap.find(iPoint);
716         if (shared && found != _SVertexMap.end()) {
717           va = (*found).second;
718         }else{
719           va = MakeSVertex(iPoint);
720           // Add the svertex into the table using iPoint as the key
721           _SVertexMap[iPoint] = va; 
722         }
723   }
724   return va;
725 }
726
727 ViewVertex * ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex){
728   ViewVertex *vva = iSVertex->viewvertex();  
729   if(vva != 0)
730     return vva;
731   vva = new NonTVertex(iSVertex);
732   // Add the view vertex to the ViewShape svertex list:
733   _pCurrentVShape->AddVertex(vva);    
734   return vva;
735 }
736