Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Curioni <maxime.curioni@gmail.com>2008-05-08 23:16:40 +0400
committerMaxime Curioni <maxime.curioni@gmail.com>2008-05-08 23:16:40 +0400
commit64e4a3ec9aed6c8abe095e2cd1fe1552f7cde51c (patch)
tree6c77358bd447b6c2d215324ef48fc12d1f5ae5ca /source/blender/freestyle/intern/view_map
parentcf2e1e2857cfc5b3c2848c7fc6c9d919ac72fabb (diff)
parent106974a9d2d5caa5188322507980e3d57d2e3517 (diff)
soc-2008-mxcurioni: merged changes to revision 14747, cosmetic changes for source/blender/freestyle
Diffstat (limited to 'source/blender/freestyle/intern/view_map')
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.cpp677
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.h150
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions0D.cpp356
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions0D.h487
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions1D.cpp209
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions1D.h537
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Interface0D.h351
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Interface1D.h202
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.cpp370
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.h1417
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp185
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h122
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SteerableViewMap.cpp243
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SteerableViewMap.h153
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp666
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h214
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMap.cpp703
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMap.h1487
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h691
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapBuilder.cpp1027
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapBuilder.h224
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapIO.cpp1245
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapIO.h116
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapIterators.h542
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapTesselator.cpp36
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapTesselator.h196
-rwxr-xr-xsource/blender/freestyle/intern/view_map/src.pri34
-rwxr-xr-xsource/blender/freestyle/intern/view_map/view_map.pro89
28 files changed, 12729 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
new file mode 100755
index 00000000000..628b3ad77aa
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -0,0 +1,677 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "FEdgeXDetector.h"
+#include "float.h"
+#include "../geometry/GeomUtils.h"
+#include <math.h>
+#include "../geometry/normal_cycle.h"
+
+void FEdgeXDetector::processShapes(WingedEdge& we) {
+ bool progressBarDisplay = false;
+ Vec3r Min, Max;
+ vector<WShape*> wshapes = we.getWShapes();
+ WXShape * wxs;
+
+ if(_pProgressBar != NULL) {
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Detecting feature lines");
+ _pProgressBar->setTotalSteps(wshapes.size() * 3);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ for(vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++){
+ wxs = dynamic_cast<WXShape*>(*it);
+ wxs->bbox(Min, Max);
+ _bbox_diagonal = (Max-Min).norm();
+ if(_changes){
+ vector<WFace*>& wfaces = wxs->GetFaceList();
+ for(vector<WFace*>::iterator wf=wfaces.begin(), wfend=wfaces.end();
+ wf!=wfend;
+ ++wf){
+ WXFace* wxf = dynamic_cast<WXFace*>(*wf);
+ wxf->Clear();
+ }
+ _computeViewIndependant = true;
+ } else if (!(wxs)->getComputeViewIndependantFlag()) {
+ wxs->Reset();
+ _computeViewIndependant = false;
+ } else {
+ _computeViewIndependant = true;
+ }
+ preProcessShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ processBorderShape(wxs);
+ processCreaseShape(wxs);
+ if(_computeRidgesAndValleys)
+ processRidgesAndValleysShape(wxs);
+ if(_computeSuggestiveContours)
+ processSuggestiveContourShape(wxs);
+ processSilhouetteShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+
+ // build smooth edges:
+ buildSmoothEdges(wxs);
+
+ // Post processing for suggestive contours
+ if(_computeSuggestiveContours)
+ postProcessSuggestiveContourShape(wxs);
+ if (progressBarDisplay)
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+
+ wxs->setComputeViewIndependantFlag(false);
+ _computeViewIndependant = false;
+ _changes = false;
+
+ // reset user data
+ (*it)->ResetUserData();
+ }
+}
+
+// GENERAL STUFF
+////////////////
+void FEdgeXDetector::preProcessShape(WXShape* iWShape) {
+ _meanK1 = 0;
+ _meanKr = 0;
+ _minK1 = FLT_MAX;
+ _maxK1 = -FLT_MAX;
+ _minKr = FLT_MAX;
+ _maxKr = -FLT_MAX;
+ _nPoints = 0;
+ _meanEdgeSize = iWShape->getMeanEdgeSize();
+
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f,fend;
+ // view dependant stuff
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f){
+ preProcessFace((WXFace*)(*f));
+ }
+
+ vector<WVertex*>& wvertices = iWShape->GetVertexList();
+ for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end();
+ wv!=wvend;
+ ++wv){
+ // Compute curvatures
+ WXVertex * wxv = dynamic_cast<WXVertex*>(*wv);
+ computeCurvatures(wxv);
+ }
+ _meanK1 /= (real)(_nPoints);
+ _meanKr /= (real)(_nPoints);
+}
+
+void FEdgeXDetector::preProcessFace(WXFace *iFace){
+ Vec3r firstPoint = iFace->GetVertex(0)->GetVertex();
+ Vec3r N = iFace->GetNormal();
+
+ // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
+ Vec3r V(_Viewpoint - firstPoint);
+ N.normalize();
+ V.normalize();
+ iFace->SetDotP(N * V);
+
+ // compute the distance between the face center and the viewpoint:
+ Vec3r dist_vec(iFace->center() - _Viewpoint);
+ iFace->SetZ(dist_vec.norm());
+}
+
+void FEdgeXDetector::computeCurvatures(WXVertex *vertex){
+ // CURVATURE LAYER
+ // store all the curvature datas for each vertex
+
+ real K1, K2, cos2theta, sin2theta;
+ Vec3r e1, n, v;
+ // one vertex curvature info :
+ CurvatureInfo *C;
+ float radius = _sphereRadius*_meanEdgeSize;
+
+ // view independant stuff
+ if(_computeViewIndependant){
+ C = new CurvatureInfo();
+ vertex->setCurvatures(C);
+ OGF::NormalCycle ncycle ;
+ ncycle.begin() ;
+ if(radius > 0) {
+ OGF::compute_curvature_tensor(vertex, radius, ncycle) ;
+ } else {
+ OGF::compute_curvature_tensor_one_ring(vertex, ncycle) ;
+ }
+ ncycle.end() ;
+ C->K1 = ncycle.kmin();
+ C->K2 = ncycle.kmax();
+ C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax();
+ C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin() ;
+
+ real absK1 = fabs(C->K1);
+ _meanK1 += absK1;
+ if(absK1 > _maxK1)
+ _maxK1 = absK1;
+ if(absK1 < _minK1)
+ _minK1 = absK1;
+ }
+ // view dependant
+ C = vertex->curvatures();
+ if(C == 0)
+ return;
+
+ // compute radial curvature :
+ n = C->e1 ^ C->e2;
+ v = _Viewpoint - vertex->GetVertex();
+ C->er = v - (v * n) * n;
+ C->er.normalize();
+ e1 = C->e1;
+ e1.normalize();
+ cos2theta = C->er * e1;
+ cos2theta *= cos2theta;
+ sin2theta = 1 - cos2theta;
+ C->Kr = C->K1 * cos2theta + C->K2 * sin2theta;
+ real absKr = fabs(C->Kr);
+ _meanKr += absKr;
+ if(absKr > _maxKr)
+ _maxKr = absKr;
+ if(absKr < _minKr)
+ _minKr = absKr;
+
+ ++_nPoints;
+}
+
+// SILHOUETTE
+/////////////
+void FEdgeXDetector::processSilhouetteShape(WXShape* iWShape) {
+ // Make a first pass on every polygons in order
+ // to compute all their silhouette relative values:
+ //------------------------------------------------
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f,fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ ProcessSilhouetteFace((WXFace*)(*f));
+ }
+
+ // Make a pass on the edges to detect
+ // the silhouette edges that are not smooth
+ // --------------------
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->GetEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we)
+ {
+ ProcessSilhouetteEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace)
+{
+
+ // SILHOUETTE LAYER
+ Vec3r normal;
+ // Compute the dot products between View direction and N at each vertex
+ // of the face:
+ Vec3r point;
+ int closestPointId = 0;
+ real dist, minDist = FLT_MAX;
+ int numVertices = iFace->numberOfVertices();
+ WXFaceLayer * faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
+ for(int i=0; i<numVertices; i++){
+ point = iFace->GetVertex(i)->GetVertex();
+ normal = iFace->GetVertexNormal(i);
+ Vec3r V(_Viewpoint - point);
+ normal.normalize();
+ V.normalize();
+ real d = normal * V;
+ faceLayer->PushDotP(d);
+ // Find the point the closest to the viewpoint
+ Vec3r dist_vec(point - _Viewpoint);
+ dist = dist_vec.norm();
+ if(dist < minDist) {
+ minDist = dist;
+ closestPointId = i;
+ }
+ }
+ // Set the closest point id:
+ faceLayer->SetClosestPointIndex(closestPointId);
+ // Add this layer to the face:
+ iFace->AddSmoothLayer(faceLayer);
+}
+
+void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge)
+{
+ if(iEdge->nature() & Nature::BORDER)
+ return;
+ // SILHOUETTE ?
+ //-------------
+ WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
+ WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
+
+ if((fA->front())^(fB->front())){ // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
+ // The only edges we want to set as silhouette edges in this
+ // way are the ones with 2 different normals for 1 vertex
+ // for these two faces
+ //--------------------
+ // In reality we only test the normals for 1 of the 2 vertices.
+ if(fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()))
+ return;
+ iEdge->AddNature(Nature::SILHOUETTE);
+ if(fB->front())
+ iEdge->SetOrder(1);
+ else
+ iEdge->SetOrder(-1);
+ }
+}
+
+
+// BORDER
+/////////
+void FEdgeXDetector::processBorderShape(WXShape* iWShape) {
+
+ if(!_computeViewIndependant)
+ return;
+ // Make a pass on the edges to detect
+ // the BORDER
+ // --------------------
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->GetEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we){
+ ProcessBorderEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge)
+{
+ // first check whether it is a border edge:
+ // BORDER ?
+ //---------
+ if(iEdge->GetaFace() == 0){
+ // it is a border edge
+ iEdge->AddNature(Nature::BORDER);
+ }
+}
+
+
+// CREASE
+/////////
+void FEdgeXDetector::processCreaseShape(WXShape* iWShape) {
+ if(!_computeViewIndependant)
+ return;
+
+ // Make a pass on the edges to detect
+ // the CREASE
+ // --------------------
+ vector<WEdge*>::iterator we, weend;
+ vector<WEdge*> &wedges = iWShape->GetEdgeList();
+ for(we=wedges.begin(), weend=wedges.end();
+ we!=weend;
+ ++we){
+ ProcessCreaseEdge((WXEdge*)(*we));
+ }
+}
+
+void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge)
+{
+ // CREASE ?
+ //---------
+ if(iEdge->nature() & Nature::BORDER)
+ return;
+ WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
+ WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
+
+ WVertex * aVertex = iEdge->GetaVertex();
+ if((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= 0.7) // angle of 140 degrees
+ iEdge->AddNature(Nature::CREASE);
+}
+
+// RIDGES AND VALLEYS
+/////////////////////
+
+void FEdgeXDetector::processRidgesAndValleysShape(WXShape* iWShape) {
+ // Don't forget to add the built layer to the face at the end
+ // of the ProcessFace:
+ //iFace->AddSmoothLayer(faceLayer);
+
+ if((!_computeViewIndependant))
+ return;
+
+ // Here the curvatures must already have been computed
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ ProcessRidgeFace((WXFace*)(*f));
+ }
+}
+
+
+// RIDGES
+/////////
+
+void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
+{
+ WXFaceLayer * flayer = new WXFaceLayer(iFace, Nature::RIDGE|Nature::VALLEY, false);
+ iFace->AddSmoothLayer(flayer);
+
+ unsigned int numVertices = iFace->numberOfVertices();
+ for(unsigned int i=0; i<numVertices; ++i){
+ WVertex *wv = iFace->GetVertex(i);
+ WXVertex * wxv = dynamic_cast<WXVertex*>(wv);
+ flayer->PushDotP(wxv->curvatures()->K1);
+ }
+
+ real threshold = 0;
+ //real threshold = _maxK1 - (_maxK1-_meanK1)/20.0;
+
+ if(flayer->nPosDotP()!=numVertices){
+ if((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) && (fabs(flayer->dotP(2)) < threshold)){
+ flayer->ReplaceDotP(0, 0);
+ flayer->ReplaceDotP(1, 0);
+ flayer->ReplaceDotP(2, 0);
+ }
+ }
+}
+
+// void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
+// {
+
+// // RIDGE LAYER
+// // compute the RidgeFunction, that is the derivative of the ppal curvature
+// // along e1 at each vertex of the face
+
+// WVertex *v;
+// Vec3r v1v2;
+// real t;
+// vector<WXFaceLayer*> SmoothLayers;
+// WXFaceLayer *faceLayer;
+// Face_Curvature_Info *layer_info;
+// real K1_a(0), K1_b(0);
+// Vec3r Inter_a, Inter_b;
+
+// // find the ridge layer of the face
+// iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
+// if(SmoothLayers.size()!=1)
+// return;
+// faceLayer = SmoothLayers[0];
+// // retrieve the curvature info of this layer
+// layer_info = (Face_Curvature_Info *)faceLayer->userdata;
+
+// int numVertices = iFace->numberOfVertices();
+// for(int i=0; i<numVertices; i++){
+// v = iFace->GetVertex(i);
+// // vec_curvature_info[i] contains the curvature info of this vertex
+// Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2;
+// Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1;
+// e2.normalize();
+
+// WVertex::face_iterator fit = v->faces_begin();
+// WVertex::face_iterator fitend = v->faces_end();
+// for(; fit!=fitend; ++fit){
+// WXFace * wxf = dynamic_cast<WXFace*>(*fit);
+// WOEdge * oppositeEdge;
+// if(!(wxf->getOppositeEdge(v, oppositeEdge)))
+// continue;
+// v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
+// GeomUtils::intersection_test res;
+// res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2,
+// e2, -(v->GetVertex()*e2),
+// t,1.e-06);
+// if((res == GeomUtils::DO_INTERSECT) && (t>=0.0) && (t<=1.0)){
+// vector<WXFaceLayer*> second_ridge_layer;
+// wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
+// if(second_ridge_layer.size()!=1)
+// continue;
+// Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata;
+
+// unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
+// unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
+// real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
+// real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
+// real K1 = (1.0-t)*K1_1 + t*K1_2;
+// Vec3r inter((1.0-t)*oppositeEdge->GetaVertex()->GetVertex() + t*oppositeEdge->GetbVertex()->GetVertex());
+// Vec3r vtmp(inter - v->GetVertex());
+// // is it K1_a or K1_b ?
+// if(vtmp*e1 > 0){
+// K1_b = K1;
+// Inter_b = inter;
+// }else{
+// K1_a = K1;
+// Inter_a = inter;
+// }
+// }
+// }
+// // Once we have K1 along the the ppal direction
+// // compute the derivative : K1b - K1a
+// // put it in DotP
+// //real d = fabs(K1_b)-fabs(K1_a);
+// real d = 0;
+// real threshold = _meanK1 + (_maxK1-_meanK1)/7.0;
+// //real threshold = _meanK1;
+// //if((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
+// d = (K1_b)-(K1_a)/(Inter_b-Inter_a).norm();
+// faceLayer->PushDotP(d);
+// //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
+// }
+
+// // Make the values relevant by checking whether all principal
+// // directions have the "same" direction:
+// Vec3r e0((layer_info->vec_curvature_info[0]->K1*layer_info->vec_curvature_info[0]->e1));
+// e0.normalize();
+// Vec3r e1((layer_info->vec_curvature_info[1]->K1*layer_info->vec_curvature_info[1]->e1));
+// e1.normalize();
+// Vec3r e2((layer_info->vec_curvature_info[2]->K1*layer_info->vec_curvature_info[2]->e1));
+// e2.normalize();
+// if (e0 * e1 < 0)
+// // invert dotP[1]
+// faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
+// if (e0 * e2 < 0)
+// // invert dotP[2]
+// faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));
+
+// // remove the weakest values;
+// //real minDiff = (_maxK1 - _minK1)/10.0;
+// // real minDiff = _meanK1;
+// // if((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)){
+// // faceLayer->ReplaceDotP(0, 0);
+// // faceLayer->ReplaceDotP(1, 0);
+// // faceLayer->ReplaceDotP(2, 0);
+// // }
+// }
+
+// SUGGESTIVE CONTOURS
+//////////////////////
+
+void FEdgeXDetector::processSuggestiveContourShape(WXShape* iWShape) {
+
+ // Here the curvatures must already have been computed
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ ProcessSuggestiveContourFace((WXFace*)(*f));
+ }
+}
+
+void FEdgeXDetector::ProcessSuggestiveContourFace(WXFace *iFace)
+{
+ WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
+ iFace->AddSmoothLayer(faceLayer);
+
+ unsigned int numVertices = iFace->numberOfVertices();
+ for(unsigned int i=0; i<numVertices; ++i){
+ WVertex *wv = iFace->GetVertex(i);
+ WXVertex * wxv = dynamic_cast<WXVertex*>(wv);
+ faceLayer->PushDotP(wxv->curvatures()->Kr);
+ }
+
+ // FIXME: find a more clever way to compute the threshold
+// real threshold = _meanKr;
+// if(faceLayer->nPosDotP()!=numVertices){
+// if((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) && (fabs(faceLayer->dotP(2)) < threshold)){
+// faceLayer->ReplaceDotP(0, 0);
+// faceLayer->ReplaceDotP(1, 0);
+// faceLayer->ReplaceDotP(2, 0);
+// }
+// }
+}
+
+void FEdgeXDetector::postProcessSuggestiveContourShape(WXShape* iShape) {
+ vector<WFace*>& wfaces = iShape->GetFaceList();
+ vector<WFace*>::iterator f, fend;
+ for(f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ postProcessSuggestiveContourFace((WXFace*)(*f));
+ }
+}
+
+void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) {
+
+ // Compute the derivative of the radial curvature in the radial direction,
+ // at the two extremities of the smooth edge.
+ // If the derivative is smaller than a given threshold _kr_derivative_epsilon,
+ // discard the edge.
+
+ // Find the suggestive contour layer of the face (zero or one edge).
+ vector<WXFaceLayer*> sc_layers;
+ iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers);
+ if(sc_layers.empty())
+ return;
+
+ WXFaceLayer *sc_layer;
+ sc_layer = sc_layers[0];
+
+ // Compute the derivative value at each vertex of the face, and add it in a vector.
+ vector<real> kr_derivatives;
+
+ unsigned vertices_nb = iFace->numberOfVertices();
+ WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
+ WXFace *wxf;
+ WOEdge *opposite_edge;
+ Vec3r opposite_edge_vec, normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
+ GeomUtils::intersection_test res;
+ real kr(0), kr1(0), kr2(0), t;
+
+ for (unsigned i = 0; i < vertices_nb; ++i) {
+ v = (WXVertex*)(iFace->GetVertex(i));
+
+ // v is a singular vertex, skip it.
+ if (v->isBoundary()) {
+ kr_derivatives.push_back(0);
+ continue;
+ }
+
+ v_vec = v->GetVertex();
+ er_vec = v->curvatures()->er;
+
+ // For each vertex, iterate on its adjacent faces.
+ for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end();
+ fit != fitend;
+ ++fit) {
+ wxf = dynamic_cast<WXFace*>(*fit);
+ if(!(wxf->getOppositeEdge(v, opposite_edge)))
+ continue;
+
+ opposite_vertex_a = (WXVertex*)opposite_edge->GetaVertex();
+ opposite_vertex_b = (WXVertex*)opposite_edge->GetbVertex();
+ opposite_edge_vec = opposite_vertex_b->GetVertex() - opposite_vertex_a->GetVertex();
+ normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
+ radial_normal_vec = er_vec ^ normal_vec;
+
+ // Test wether the radial plan intersects with the edge at the opposite of v.
+ res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge_vec,
+ radial_normal_vec, -(v_vec * radial_normal_vec),
+ t,
+ 1.e-06);
+
+ // If there is an intersection, compute the value of the derivative ath that point.
+ if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
+ kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr;
+ inter = opposite_vertex_a->GetVertex() + t * opposite_edge_vec;
+ tmp_vec = inter - v->GetVertex();
+ // Is it kr1 or kr2?
+ if (tmp_vec * er_vec > 0) {
+ kr2 = kr;
+ inter2 = inter;
+ } else {
+ kr1 = kr;
+ inter1 = inter;
+ }
+ }
+ }
+
+ // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
+ // We have to compute the derivative of kr for that vertex, equal to:
+ // (kr2 - kr1) / dist(inter1, inter2).
+ // Then we add it to the vector of derivatives.
+ v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
+ kr_derivatives.push_back(v->curvatures()->dKr);
+ }
+
+ // At that point, we have the derivatives for each vertex of iFace.
+ // All we have to do now is to use linear interpolation to compute the values at
+ // the extremities of the smooth edge.
+ WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
+ WOEdge *sc_oedge = sc_edge->woea();
+ t = sc_edge->ta();
+ if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
+ (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) {
+ sc_layer->removeSmoothEdge();
+ return;
+ }
+ sc_oedge = sc_edge->woeb();
+ t = sc_edge->tb();
+ if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
+ (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon)
+ sc_layer->removeSmoothEdge();
+}
+
+
+// Build Smooth edges
+/////////////////////
+void FEdgeXDetector::buildSmoothEdges(WXShape* iShape){
+ // Make a last pass to build smooth edges from the previous stored values:
+ //--------------------------------------------------------------------------
+ vector<WFace*>& wfaces = iShape->GetFaceList();
+ for(vector<WFace*>::iterator f=wfaces.begin(), fend=wfaces.end();
+ f!=fend;
+ ++f)
+ {
+ vector<WXFaceLayer*>& faceLayers = ((WXFace*)(*f))->getSmoothLayers();
+ for(vector<WXFaceLayer*>::iterator wxfl = faceLayers.begin(), wxflend=faceLayers.end();
+ wxfl!=wxflend;
+ ++wxfl){
+ (*wxfl)->BuildSmoothEdge();
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
new file mode 100755
index 00000000000..38d0f34e21f
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
@@ -0,0 +1,150 @@
+//
+// Filename : FEdgeXDetector.h
+// Author(s) : Stephane Grabli
+// Purpose : Detects/flags/builds extended features edges on the
+// WXEdge structure
+// Date of creation : 26/10/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef FEDGEXDETECTOR_H
+# define FEDGEXDETECTOR_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../winged_edge/WXEdge.h"
+# include "../winged_edge/Curvature.h"
+# include "../system/ProgressBar.h"
+
+using namespace Geometry;
+
+/*! This class takes as input a WXEdge structure and fills it
+ */
+
+class LIB_VIEW_MAP_EXPORT FEdgeXDetector
+{
+public:
+
+ FEdgeXDetector() {
+ _pProgressBar = 0;
+ _computeViewIndependant = true;
+ _bbox_diagonal = 1.0;
+ _meanEdgeSize = 0;
+ _computeRidgesAndValleys = true;
+ _computeSuggestiveContours = true;
+ _sphereRadius = 1.0;
+ _changes = false;
+ _kr_derivative_epsilon = 0.0;
+ }
+ virtual ~FEdgeXDetector() {}
+
+ /*! Process shapes from a WingedEdge containing a list of WShapes */
+ virtual void processShapes(WingedEdge&);
+
+ // GENERAL STUFF
+ virtual void preProcessShape(WXShape* iShape);
+ virtual void preProcessFace(WXFace* iFace);
+ virtual void computeCurvatures(WXVertex *iVertex);
+
+ // SILHOUETTE
+ virtual void processSilhouetteShape(WXShape* iShape);
+ virtual void ProcessSilhouetteFace(WXFace *iFace);
+ virtual void ProcessSilhouetteEdge(WXEdge *iEdge);
+
+ // CREASE
+ virtual void processCreaseShape(WXShape* iShape);
+ virtual void ProcessCreaseEdge(WXEdge *iEdge);
+
+ // BORDER
+ virtual void processBorderShape(WXShape* iShape);
+ virtual void ProcessBorderEdge(WXEdge *iEdge);
+
+ // RIDGES AND VALLEYS
+ virtual void processRidgesAndValleysShape(WXShape* iShape);
+ virtual void ProcessRidgeFace(WXFace *iFace);
+
+ // SUGGESTIVE CONTOURS
+ virtual void processSuggestiveContourShape(WXShape* iShape);
+ virtual void ProcessSuggestiveContourFace(WXFace *iFace);
+ virtual void postProcessSuggestiveContourShape(WXShape* iShape);
+ virtual void postProcessSuggestiveContourFace(WXFace *iFace);
+ /*! Sets the minimal derivative of the radial curvature for suggestive contours
+ * \param dkr
+ * The minimal derivative of the radial curvature
+ */
+ inline void setSuggestiveContourKrDerivativeEpsilon(real dkr) {
+ if (dkr != _kr_derivative_epsilon){
+ _kr_derivative_epsilon = dkr;
+ _changes = true;
+ }
+ }
+
+ // EVERYBODY
+ virtual void buildSmoothEdges(WXShape* iShape);
+
+ /*! Sets the current viewpoint */
+ inline void SetViewpoint(const Vec3r& ivp) {_Viewpoint = ivp;}
+ inline void enableRidgesAndValleysFlag(bool b) {_computeRidgesAndValleys = b;}
+ inline void enableSuggestiveContours(bool b) {_computeSuggestiveContours = b;}
+ /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation)
+ * \param r
+ * The radius of the sphere expressed as a ratio of the mean edge size
+ */
+ inline void setSphereRadius(real r) {
+ if(r!=_sphereRadius){
+ _sphereRadius = r;
+ _changes=true;
+ }
+ }
+
+ inline void SetProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;}
+
+protected:
+
+ Vec3r _Viewpoint;
+ real _bbox_diagonal; // diagonal of the current processed shape bbox
+ //tmp values
+ bool _computeViewIndependant;
+ real _meanK1;
+ real _meanKr;
+ real _minK1;
+ real _minKr;
+ real _maxK1;
+ real _maxKr;
+ unsigned _nPoints;
+ real _meanEdgeSize;
+
+ bool _computeRidgesAndValleys;
+ bool _computeSuggestiveContours;
+ real _sphereRadius; // expressed as a ratio of the mean edge size
+ bool _changes;
+
+ real _kr_derivative_epsilon;
+
+ ProgressBar *_pProgressBar;
+};
+
+#endif // FEDGEDXETECTOR_H
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp
new file mode 100755
index 00000000000..c868510624c
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp
@@ -0,0 +1,356 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "Functions0D.h"
+# include "ViewMap.h"
+
+using namespace std;
+
+namespace Functions0D {
+
+ // Internal function
+ FEdge* getFEdge(Interface0D& it1, Interface0D& it2){
+ return it1.getFEdge(it2);
+ }
+
+ void getFEdges(Interface0DIterator& it,
+ FEdge*& fe1,
+ FEdge*& fe2) {
+ // count number of vertices
+ Interface0DIterator prev = it, next = it;
+ ++next;
+ int count = 1;
+ while((!prev.isBegin()) && (count < 3))
+ {
+ --prev;
+ ++count;
+ }
+ while((!next.isEnd()) && (count < 3))
+ {
+ ++next;
+ ++count;
+ }
+ if(count < 3)
+ {
+ // if we only have 2 vertices
+ FEdge * fe = 0;
+ Interface0DIterator tmp = it;
+ if(it.isBegin())
+ {
+ ++tmp;
+ fe = it->getFEdge(*tmp);
+ }
+ else
+ {
+ --tmp;
+ fe = it->getFEdge(*tmp);
+ }
+ fe1 = fe;
+ fe2 = 0;
+ }
+ else
+ {
+ // we have more than 2 vertices
+ bool begin=false,last=false;
+ Interface0DIterator previous = it;
+ if(!previous.isBegin())
+ --previous;
+ else
+ begin=true;
+ Interface0DIterator next = it;
+ ++next;
+ if(next.isEnd())
+ last = true;
+ if(begin)
+ {
+ fe1 = it->getFEdge(*next);
+ fe2 = 0;
+ }
+ else if(last)
+ {
+ fe1 = previous->getFEdge(*it);
+ fe2 = 0;
+ }
+ else
+ {
+ fe1 = previous->getFEdge(*it);
+ fe2 = it->getFEdge(*next);
+ }
+ }
+ }
+
+ void getViewEdges(Interface0DIterator &it,
+ ViewEdge *&ve1,
+ ViewEdge *&ve2)
+ {
+ FEdge * fe1, *fe2;
+ getFEdges(it, fe1, fe2);
+ ve1 = fe1->viewedge();
+ if(fe2 != 0)
+ {
+ ve2 = fe2->viewedge();
+ if(ve2 == ve1)
+ ve2 = 0;
+ }
+ else
+ ve2 = 0;
+ }
+
+ ViewShape* getShapeF0D(Interface0DIterator& it)
+ {
+ ViewEdge *ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ return ve1->viewShape();
+ }
+
+ void getOccludersF0D(Interface0DIterator& it, set<ViewShape*>& oOccluders){
+ ViewEdge * ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ occluder_container::const_iterator oit = ve1->occluders_begin();
+ occluder_container::const_iterator oitend = ve1->occluders_end();
+
+ for(;oit!=oitend; ++oit)
+ oOccluders.insert((*oit));
+
+ if(ve2!=0){
+ oit = ve2->occluders_begin();
+ oitend = ve2->occluders_end();
+ for(;oit!=oitend; ++oit)
+ oOccluders.insert((*oit));
+ }
+ }
+
+ ViewShape * getOccludeeF0D(Interface0DIterator& it){
+ ViewEdge * ve1, *ve2;
+ getViewEdges(it, ve1, ve2);
+ ViewShape *aShape = ve1->aShape();
+ return aShape;
+ }
+
+ //
+ Vec2f VertexOrientation2DF0D::operator()(Interface0DIterator& iter) {
+ Vec2f A,C;
+ Vec2f B(iter->getProjectedX(), iter->getProjectedY());
+ if(iter.isBegin())
+ A = Vec2f(iter->getProjectedX(), iter->getProjectedY());
+ else
+ {
+ Interface0DIterator previous = iter;
+ --previous ;
+ A = Vec2f(previous->getProjectedX(), previous->getProjectedY());
+ }
+ Interface0DIterator next = iter;
+ ++next ;
+ if(next.isEnd())
+ C = Vec2f(iter->getProjectedX(), iter->getProjectedY());
+ else
+ C = Vec2f(next->getProjectedX(), next->getProjectedY());
+
+ Vec2f AB(B-A);
+ if(AB.norm() != 0)
+ AB.normalize();
+ Vec2f BC(C-B);
+ if(BC.norm() != 0)
+ BC.normalize();
+ Vec2f res (AB + BC);
+ if(res.norm() != 0)
+ res.normalize();
+ return res;
+ }
+
+ Vec3f VertexOrientation3DF0D::operator()(Interface0DIterator& iter) {
+ Vec3r A,C;
+ Vec3r B(iter->getX(), iter->getY(), iter->getZ());
+ if(iter.isBegin())
+ A = Vec3r(iter->getX(), iter->getY(), iter->getZ());
+ else
+ {
+ Interface0DIterator previous = iter;
+ --previous ;
+ A = Vec3r(previous->getX(), previous->getY(), previous->getZ());
+ }
+ Interface0DIterator next = iter;
+ ++next ;
+ if(next.isEnd())
+ C = Vec3r(iter->getX(), iter->getY(), iter->getZ());
+ else
+ C = Vec3r(next->getX(), next->getY(), next->getZ());
+
+ Vec3r AB(B-A);
+ if(AB.norm() != 0)
+ AB.normalize();
+ Vec3r BC(C-B);
+ if(BC.norm() != 0)
+ BC.normalize();
+ Vec3f res (AB + BC);
+ if(res.norm() != 0)
+ res.normalize();
+ return res;
+ }
+
+ real Curvature2DAngleF0D::operator()(Interface0DIterator& iter) {
+ Interface0DIterator tmp1 = iter, tmp2 = iter;
+ ++tmp2;
+ unsigned count = 1;
+ while((!tmp1.isBegin()) && (count < 3))
+ {
+ --tmp1;
+ ++count;
+ }
+ while((!tmp2.isEnd()) && (count < 3))
+ {
+ ++tmp2;
+ ++count;
+ }
+ if(count < 3)
+ return 0; // if we only have 2 vertices
+
+ Interface0DIterator v = iter;
+ if(iter.isBegin())
+ ++v;
+ Interface0DIterator next=v;
+ ++next;
+ if(next.isEnd())
+ {
+ next = v;
+ --v;
+ }
+ Interface0DIterator prev=v;
+ --prev;
+
+ Vec2r A(prev->getProjectedX(), prev->getProjectedY());
+ Vec2r B(v->getProjectedX(), v->getProjectedY());
+ Vec2r C(next->getProjectedX(), next->getProjectedY());
+ Vec2r AB(B-A);
+ Vec2r BC(C-B);
+ Vec2r N1(-AB[1], AB[0]);
+ if(N1.norm() != 0)
+ N1.normalize();
+ Vec2r N2(-BC[1], BC[0]);
+ if(N2.norm() != 0)
+ N2.normalize();
+ if((N1.norm() == 0) && (N2.norm() == 0))
+ {
+ Exception::raiseException();
+ return 0;
+ }
+ double cosin = N1*N2;
+ if(cosin > 1)
+ cosin = 1;
+ if(cosin < -1)
+ cosin = -1;
+ return acos(cosin);
+ }
+
+ real ZDiscontinuityF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter, fe1, fe2);
+ real result ;
+ result = fe1->z_discontinuity();
+ if(fe2!=0){
+ result += fe2->z_discontinuity();
+ result /= 2.f;
+ }
+ return result;
+ }
+
+ Vec2f Normal2DF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter,fe1,fe2);
+ Vec3f e1(fe1->orientation2d());
+ Vec2f n1(e1[1], -e1[0]);
+ Vec2f n(n1);
+ if(fe2 != 0)
+ {
+ Vec3f e2(fe2->orientation2d());
+ Vec2f n2(e2[1], -e2[0]);
+ n += n2;
+ }
+ n.normalize();
+ return n;
+ }
+
+ Material MaterialF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter,fe1,fe2);
+
+ if(fe1 == 0)
+ getFEdges(iter, fe1, fe2);
+ Material mat;
+ if(fe1->isSmooth())
+ mat = ((FEdgeSmooth*)fe1)->material();
+ else
+ mat = ((FEdgeSharp*)fe1)->bMaterial();
+ // const SShape * sshape = getShapeF0D(iter);
+ // return sshape->material();
+ return mat;
+ }
+
+ Id ShapeIdF0D::operator()(Interface0DIterator& iter) {
+ ViewShape * vshape = getShapeF0D(iter);
+ return vshape->getId();
+ }
+
+ unsigned int QuantitativeInvisibilityF0D::operator()(Interface0DIterator& iter) {
+ ViewEdge * ve1, *ve2;
+ getViewEdges(iter,ve1,ve2);
+ unsigned int qi1, qi2;
+ qi1 = ve1->qi();
+ if(ve2 != 0){
+ qi2 = ve2->qi();
+ if(qi2!=qi1)
+ cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl;
+ }
+ return qi1;
+ }
+
+ Nature::EdgeNature CurveNatureF0D::operator()(Interface0DIterator& iter) {
+ Nature::EdgeNature nat = 0;
+ ViewEdge * ve1, *ve2;
+ getViewEdges(iter, ve1, ve2);
+ nat |= ve1->getNature();
+ if(ve2!=0)
+ nat |= ve2->getNature();
+ return nat;
+ }
+
+ vector<ViewShape*> GetOccludersF0D::operator()(Interface0DIterator& iter) {
+ set<ViewShape*> occluders;
+ getOccludersF0D(iter,occluders);
+ vector<ViewShape*> vsOccluders;
+ // vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end());
+ for(set<ViewShape*>::iterator it=occluders.begin(), itend=occluders.end();
+ it!=itend;
+ ++it){
+ vsOccluders.push_back((*it));
+ }
+ return vsOccluders;
+ }
+
+ ViewShape* GetShapeF0D::operator()(Interface0DIterator& iter) {
+ return getShapeF0D(iter);
+ }
+
+ ViewShape* GetOccludeeF0D::operator()(Interface0DIterator& iter) {
+ return getOccludeeF0D(iter);
+ }
+
+} // end of namespace Functions0D
diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h
new file mode 100755
index 00000000000..3160546da2f
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.h
@@ -0,0 +1,487 @@
+//
+// Filename : Functions0D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Functions taking 0D input
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FUNCTIONS0D_H
+# define FUNCTIONS0D_H
+
+# include "../system/Precision.h"
+# include "Interface0D.h"
+# include "../geometry/Geom.h"
+# include "../system/Exception.h"
+# include "../scene_graph/Material.h"
+# include <set>
+# include <vector>
+class FEdge;
+class ViewEdge;
+class SShape;
+
+using namespace Geometry;
+
+//
+// UnaryFunction0D (base class for functions in 0D)
+//
+///////////////////////////////////////////////////////////
+
+template <class T>
+/*! Base class for Unary Functions (functors) working
+ * on Interface0DIterator.
+ * A unary function will be used by calling
+ * its operator() on an Interface0DIterator.
+ * \attention In the scripting language, there exists
+ * several prototypes depending on the returned value type.
+ * For example, you would inherit from a UnaryFunction0DDouble
+ * if you wish to define a function that returns a double.
+ * The different existing prototypes are:
+ * - UnaryFunction0DVoid
+ * - UnaryFunction0DUnsigned
+ * - UnaryFunction0DReal
+ * - UnaryFunction0DFloat
+ * - UnaryFunction0DDouble
+ * - UnaryFunction0DVec2f
+ * - UnaryFunction0DVec3f
+ */
+class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction0D
+{
+public:
+
+ /*! The type of the value
+ * returned by the functor.
+ */
+ typedef T ReturnedValueType;
+ /*! Default constructor. */
+ UnaryFunction0D() {}
+ /*! Destructor; */
+ virtual ~UnaryFunction0D() {}
+ /*! Returns the string "UnaryFunction0D" */
+ virtual string getName() const {
+ return "UnaryFunction0D";
+ }
+ /*! The operator ().
+ * \param iter
+ * An Interface0DIterator pointing onto
+ * the point at which we wish to evaluate
+ * the function.
+ * \return the result of the function of type T.
+ */
+ virtual T operator()(Interface0DIterator& iter) {
+ cerr << "Warning: operator() not implemented" << endl;
+ return T();
+ }
+};
+
+# ifdef SWIG
+%feature("director") UnaryFunction0D<void>;
+%feature("director") UnaryFunction0D<unsigned>;
+%feature("director") UnaryFunction0D<float>;
+%feature("director") UnaryFunction0D<double>;
+%feature("director") UnaryFunction0D<Vec2f>;
+%feature("director") UnaryFunction0D<Vec3f>;
+%feature("director") UnaryFunction0D<Id>;
+
+%template(UnaryFunction0DVoid) UnaryFunction0D<void>;
+%template(UnaryFunction0DUnsigned) UnaryFunction0D<unsigned>;
+%template(UnaryFunction0DFloat) UnaryFunction0D<float>;
+%template(UnaryFunction0DDouble) UnaryFunction0D<double>;
+%template(UnaryFunction0DVec2f) UnaryFunction0D<Vec2f>;
+%template(UnaryFunction0DVec3f) UnaryFunction0D<Vec3f>;
+%template(UnaryFunction0DId) UnaryFunction0D<Id>;
+%template(UnaryFunction0DViewShape) UnaryFunction0D<ViewShape*>;
+%template(UnaryFunction0DVectorViewShape) UnaryFunction0D<std::vector<ViewShape*> >;
+# endif // SWIG
+
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+class ViewShape;
+namespace Functions0D {
+
+ // GetXF0D
+ /*! Returns the X 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetXF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetXF0D"*/
+ string getName() const {
+ return "GetXF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter) {
+ return iter->getX();
+ }
+ };
+
+ // GetYF0D
+ /*! Returns the Y 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetYF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetYF0D"*/
+ string getName() const {
+ return "GetYF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter) {
+ return iter->getY();
+ }
+ };
+
+ // GetZF0D
+ /*! Returns the Z 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetZF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetZF0D"*/
+ string getName() const {
+ return "GetZF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter) {
+ return iter->getZ();
+ }
+ };
+
+ // GetProjectedXF0D
+ /*! Returns the X 3D projected coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedXF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetProjectedXF0D"*/
+ string getName() const {
+ return "GetProjectedXF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter) {
+ return iter->getProjectedX();
+ }
+ };
+
+ // GetProjectedYF0D
+ /*! Returns the Y projected 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedYF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetProjectedYF0D"*/
+ string getName() const {
+ return "GetProjectedYF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter) {
+ return iter->getProjectedY();
+ }
+ };
+
+ // GetProjectedZF0D
+ /*! Returns the Z projected 3D coordinate of an Interface0D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedZF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "GetProjectedZF0D"*/
+ string getName() const {
+ return "GetProjectedZF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter) {
+ return iter->getProjectedZ();
+ }
+ };
+
+ // GetCurvilinearAbscissaF0D
+ /*! Returns the curvilinear abscissa of an Interface0D in the context of its 1D element. */
+ class LIB_VIEW_MAP_EXPORT GetCurvilinearAbscissaF0D : public UnaryFunction0D<float>
+ {
+ public:
+ /*! Returns the string "GetCurvilinearAbscissaF0D"*/
+ string getName() const {
+ return "GetCurvilinearAbscissaF0D";
+ }
+ /*! the () operator.*/
+ float operator()(Interface0DIterator& iter) {
+ return iter.t();
+ }
+ };
+
+ // GetParameterF0D
+ /*! Returns the parameter of an Interface0D in the context of its 1D element. */
+ class LIB_VIEW_MAP_EXPORT GetParameterF0D : public UnaryFunction0D<float>
+ {
+ public:
+ /*! Returns the string "GetCurvilinearAbscissaF0D"*/
+ string getName() const {
+ return "GetParameterF0D";
+ }
+ /*! the () operator.*/
+ float operator()(Interface0DIterator& iter) {
+ return iter.u();
+ }
+ };
+
+ // VertexOrientation2DF0D
+ /*! Returns a Vec2r giving the 2D oriented tangent to the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT VertexOrientation2DF0D : public UnaryFunction0D<Vec2f>
+ {
+ public:
+ /*! Returns the string "VertexOrientation2DF0D"*/
+ string getName() const {
+ return "VertexOrientation2DF0D";
+ }
+ /*! the () operator.*/
+ Vec2f operator()(Interface0DIterator& iter);
+ };
+
+ // VertexOrientation3DF0D
+ /*! Returns a Vec3r giving the 3D oriented tangent to the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT VertexOrientation3DF0D : public UnaryFunction0D<Vec3f>
+ {
+ public:
+ /*! Returns the string "VertexOrientation3DF0D"*/
+ string getName() const {
+ return "VertexOrientation3DF0D";
+ }
+ /*! the () operator.*/
+ Vec3f operator()(Interface0DIterator& iter);
+ };
+
+ // Curvature2DAngleF0D
+ /*! Returns a real giving the 2D curvature (as an angle) of the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT Curvature2DAngleF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "Curvature2DAngleF0D"*/
+ string getName() const {
+ return "Curvature2DAngleF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter);
+ };
+
+ // ZDiscontinuity
+ /*! Returns a real giving the distance between
+ * and Interface0D and the shape that lies behind (occludee).
+ * This distance is evaluated in the camera space and normalized
+ * between 0 and 1. Therefore, if no oject is occluded by the
+ * shape to which the Interface0D belongs to, 1 is returned.
+ */
+ class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D<real>
+ {
+ public:
+ /*! Returns the string "ZDiscontinuityF0D"*/
+ string getName() const {
+ return "ZDiscontinuityF0D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface0DIterator& iter);
+ };
+
+ // Normal2DF0D
+ /*! Returns a Vec2f giving the normalized 2D normal to the 1D element
+ * to which the Interface0DIterator& belongs to and
+ * evaluated at the Interface0D pointed by this Interface0DIterator&.
+ */
+ class LIB_VIEW_MAP_EXPORT Normal2DF0D : public UnaryFunction0D<Vec2f>
+ {
+ public:
+ /*! Returns the string "Normal2DF0D"*/
+ string getName() const {
+ return "Normal2DF0D";
+ }
+ /*! the () operator.*/
+ Vec2f operator()(Interface0DIterator& iter);
+ };
+
+ // MaterialF0D
+ /*! Returns the material of the object evaluated at the Interface0D.
+ * This evaluation can be ambiguous (in the case of a TVertex for example.
+ * This functor tries to remove this ambiguity using the context
+ * offered by the 1D element to which the Interface0DIterator& belongs
+ * to and by arbitrary chosing the material of the face
+ * that lies on its left when following the 1D element if there
+ * are two different materials on each side of the point.
+ * However, there still can be problematic cases, and the user willing
+ * to deal with this cases in a specific way should implement
+ * its own getMaterial functor.
+ */
+ class LIB_VIEW_MAP_EXPORT MaterialF0D : public UnaryFunction0D<Material>
+ {
+ public:
+ /*! Returns the string "MaterialF0D"*/
+ string getName() const {
+ return "MaterialF0D";
+ }
+ /*! the () operator.*/
+ Material operator()(Interface0DIterator& iter);
+ };
+
+ // ShapeIdF0D
+ /*! Returns the Id of the Shape the Interface0D belongs to.
+ * This evaluation can be ambiguous (in the case of a TVertex for example).
+ * This functor tries to remove this ambiguity using the context
+ * offered by the 1D element to which the Interface0DIterator& belongs
+ * to.
+ * However, there still can be problematic cases, and the user willing
+ * to deal with this cases in a specific way should implement
+ * its own getShapeIdF0D functor.
+ */
+ class LIB_VIEW_MAP_EXPORT ShapeIdF0D : public UnaryFunction0D<Id>
+ {
+ public:
+ /*! Returns the string "ShapeIdF0D"*/
+ string getName() const {
+ return "ShapeIdF0D";
+ }
+ /*! the () operator.*/
+ Id operator()(Interface0DIterator& iter);
+ };
+
+ // QiF0D
+ /*! Returns the quantitative invisibility of this Interface0D.
+ * This evaluation can be ambiguous (in the case of a TVertex for example).
+ * This functor tries to remove this ambiguity using the context
+ * offered by the 1D element to which the Interface0DIterator& belongs
+ * to.
+ * However, there still can be problematic cases, and the user willing
+ * to deal with this cases in a specific way should implement
+ * its own getQIF0D functor.
+ */
+ class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF0D : public UnaryFunction0D<unsigned int>
+ {
+ public:
+ /*! Returns the string "QuantitativeInvisibilityF0D"*/
+ string getName() const {
+ return "QuantitativeInvisibilityF0D";
+ }
+ /*! the () operator.*/
+ unsigned int operator()(Interface0DIterator& iter);
+ };
+
+ // CurveNatureF0D
+ /*! Returns the Nature::EdgeNature of the 1D element the
+ * Interface0DIterator& belongs to.
+ */
+ class LIB_VIEW_MAP_EXPORT CurveNatureF0D : public UnaryFunction0D<Nature::EdgeNature>
+ {
+ public:
+ /*! Returns the string "QuantitativeInvisibilityF0D"*/
+ string getName() const {
+ return "CurveNatureF0D";
+ }
+ /*! the () operator.*/
+ Nature::EdgeNature operator()(Interface0DIterator& iter);
+ };
+
+ // GetShapeF0D
+ /*! Returns the ViewShape*
+ * containing the Interface0D
+ */
+ class LIB_VIEW_MAP_EXPORT GetShapeF0D : public UnaryFunction0D< ViewShape*>
+ {
+ public:
+ /*! Returns the string "GetShapeF0D"*/
+ string getName() const {
+ return "GetShapeF0D";
+ }
+ /*! the () operator.*/
+ ViewShape* operator()(Interface0DIterator& iter);
+ };
+
+ // GetOccludersF0D
+ /*! Returns a vector containing the ViewShape*
+ * occluding the Interface0D
+ */
+ class LIB_VIEW_MAP_EXPORT GetOccludersF0D : public UnaryFunction0D< std::vector<ViewShape*> >
+ {
+ public:
+ /*! Returns the string "GetOccludersF0D"*/
+ string getName() const {
+ return "GetOccludersF0D";
+ }
+ /*! the () operator.*/
+ std::vector<ViewShape*> operator()(Interface0DIterator& iter);
+ };
+
+ // GetOccludeeF0D
+ /*! Returns the ViewShape*
+ * "occluded" by the Interface0D
+ */
+ class LIB_VIEW_MAP_EXPORT GetOccludeeF0D: public UnaryFunction0D< ViewShape*>
+ {
+ public:
+ /*! Returns the string "GetOccludeeF0D"*/
+ string getName() const {
+ return "GetOccludeeF0D";
+ }
+ /*! the () operator.*/
+ ViewShape* operator()(Interface0DIterator& iter);
+ };
+
+
+
+ /////////////////////////// Internal ////////////////////////////
+
+ // getFEdge
+ LIB_VIEW_MAP_EXPORT
+ FEdge* getFEdge(Interface0D& it1, Interface0D& it2);
+
+ // getFEdges
+ LIB_VIEW_MAP_EXPORT
+ void getFEdges(Interface0DIterator& it,
+ FEdge*& fe1,
+ FEdge*& fe2);
+
+ // getViewEdges
+ LIB_VIEW_MAP_EXPORT
+ void getViewEdges(Interface0DIterator& it,
+ ViewEdge *&ve1,
+ ViewEdge *&ve2);
+
+ // getShapeF0D
+ LIB_VIEW_MAP_EXPORT
+ ViewShape* getShapeF0D(Interface0DIterator& it);
+
+ // getOccludersF0D
+ LIB_VIEW_MAP_EXPORT
+ void getOccludersF0D(Interface0DIterator& it, std::set<ViewShape*>& oOccluders);
+
+ // getOccludeeF0D
+ LIB_VIEW_MAP_EXPORT
+ ViewShape* getOccludeeF0D(Interface0DIterator& it);
+
+} // end of namespace Functions0D
+
+#endif // FUNCTIONS0D_H
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.cpp b/source/blender/freestyle/intern/view_map/Functions1D.cpp
new file mode 100755
index 00000000000..a34124ded31
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp
@@ -0,0 +1,209 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+# include "Functions1D.h"
+using namespace std;
+
+namespace Functions1D {
+
+ real GetXF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ real GetYF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ real GetZF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ real GetProjectedXF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ real GetProjectedYF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ real GetProjectedZF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ Vec2f Orientation2DF1D::operator()(Interface1D& inter) {
+ FEdge * fe = dynamic_cast<FEdge*>(&inter);
+ if(fe){
+ Vec3r res = fe->orientation2d();
+ return Vec2f(res[0], res[1]);
+ }
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ Vec3f Orientation3DF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ real ZDiscontinuityF1D::operator()(Interface1D& inter) {
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ unsigned QuantitativeInvisibilityF1D::operator()(Interface1D& inter) {
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve)
+ return ve->qi();
+ FEdge *fe = dynamic_cast<FEdge*>(&inter);
+ if(fe)
+ return ve->qi();
+ return integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+
+ Nature::EdgeNature CurveNatureF1D::operator()(Interface1D& inter) {
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve)
+ return ve->getNature();
+ else{
+ // we return a nature that contains every
+ // natures of the viewedges spanned by the chain.
+ Nature::EdgeNature nat = Nature::NO_FEATURE;
+ Interface0DIterator it = inter.verticesBegin();
+ while(!it.isEnd()){
+ nat |= _func(it);
+ ++it;
+ }
+ return nat;
+ }
+ }
+
+ void TimeStampF1D::operator()(Interface1D& inter) {
+ TimeStamp *timestamp = TimeStamp::instance();
+ inter.setTimeStamp(timestamp->getTimeStamp());
+ }
+
+ void ChainingTimeStampF1D::operator()(Interface1D& inter) {
+ TimeStamp *timestamp = TimeStamp::instance();
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if(ve)
+ ve->setChainingTimeStamp(timestamp->getTimeStamp());
+ }
+
+ void IncrementChainingTimeStampF1D::operator()(Interface1D& inter) {
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if(ve)
+ ve->setChainingTimeStamp(ve->getChainingTimeStamp()+1);
+ }
+
+ vector<ViewShape*> GetShapeF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ shapesVector.push_back(ve->viewShape());
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it)
+ shapesSet.insert(Functions0D::getShapeF0D(it));
+ shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ return shapesVector;
+ }
+
+ vector<ViewShape*> GetOccludersF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ return ve->occluders();
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it){
+ Functions0D::getOccludersF0D(it, shapesSet);
+ }
+ shapesVector.insert(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ return shapesVector;
+ }
+
+ vector<ViewShape*> GetOccludeeF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ ViewShape * aShape = ve->aShape();
+ shapesVector.push_back(aShape);
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it){
+ shapesSet.insert(Functions0D::getOccludeeF0D(it));
+ }
+ shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end());
+ }
+ return shapesVector;
+ }
+ // Internal
+ ////////////
+
+ void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes){
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ ViewShape * aShape = ve->aShape();
+ if(aShape == 0){
+ oShapes.insert(0);
+ return;
+ }
+ oShapes.insert(aShape);
+ }
+ else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it)
+ oShapes.insert(Functions0D::getOccludeeF0D(it));
+ }
+ }
+
+ void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes){
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ vector<ViewShape*>& occluders = ve->occluders();
+ oShapes.insert<vector<ViewShape*>::iterator>(occluders.begin(), occluders.end());
+ }
+ else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it){
+ set<ViewShape*> shapes;
+ Functions0D::getOccludersF0D(it, shapes);
+ for(set<ViewShape*>::iterator s=shapes.begin(), send=shapes.end();
+ s!=send;
+ ++s)
+ oShapes.insert(*s);
+ }
+ }
+ }
+
+ void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes){
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ oShapes.insert(ve->viewShape());
+ }else{
+ Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd();
+ for(;it!=itend;++it)
+ oShapes.insert(Functions0D::getShapeF0D(it));
+ }
+ }
+} // end of namespace Functions1D
diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h
new file mode 100755
index 00000000000..c92d12ff330
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.h
@@ -0,0 +1,537 @@
+//
+// Filename : Functions1D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Functions taking 1D input
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef FUNCTIONS1D_HPP
+# define FUNCTIONS1D_HPP
+
+# include "../system/Precision.h"
+# include "../system/TimeStamp.h"
+# include "ViewMap.h"
+# include "Functions0D.h"
+# include "Interface1D.h"
+# include "../system/FreestyleConfig.h"
+//
+// UnaryFunction1D (base class for functions in 1D)
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for Unary Functions (functors) working
+ * on Interface1D.
+ * A unary function will be used by calling
+ * its operator() on an Interface1D.
+ * \attention In the scripting language, there exists
+ * several prototypes depending on the returned value type.
+ * For example, you would inherit from a UnaryFunction1DDouble
+ * if you wish to define a function that returns a double.
+ * The different existing prototypes are:
+ * - UnaryFunction1DVoid
+ * - UnaryFunction1DUnsigned
+ * - UnaryFunction1DReal
+ * - UnaryFunction1DFloat
+ * - UnaryFunction1DDouble
+ * - UnaryFunction1DVec2f
+ * - UnaryFunction1DVec3f
+ */
+template <class T>
+class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction1D
+{
+public:
+ /*! The type of the value
+ * returned by the functor.
+ */
+ typedef T ReturnedValueType;
+
+ /*! Default constructor */
+ UnaryFunction1D(){_integration = MEAN;}
+ /*! Builds a UnaryFunction1D from an integration type.
+ * \param iType
+ * In case the result for the Interface1D would be
+ * obtained by evaluating a 0D function over the different
+ * Interface0D of the Interface1D, \a iType tells which
+ * integration method to use.
+ * The default integration method is the MEAN.
+ */
+ UnaryFunction1D(IntegrationType iType){_integration = iType;}
+ /*! destructor. */
+ virtual ~UnaryFunction1D() {}
+
+ /*! returns the string "UnaryFunction1D". */
+ virtual string getName() const {
+ return "UnaryFunction1D";
+ }
+ /*! The operator ().
+ * \param inter
+ * The Interface1D on which we wish to evaluate
+ * the function.
+ * \return the result of the function of type T.
+ */
+ virtual T operator()(Interface1D& inter) {
+ cerr << "Warning: operator() not implemented" << endl;
+ return T(0);
+ }
+ /*! Sets the integration method */
+ void setIntegrationType(IntegrationType integration) {
+ _integration = integration;
+ }
+ /*! Returns the integration method. */
+ IntegrationType getIntegrationType() const {
+ return _integration;
+ }
+
+protected:
+
+ IntegrationType _integration;
+};
+
+# ifdef SWIG
+%feature("director") UnaryFunction1D<void>;
+%feature("director") UnaryFunction1D<unsigned>;
+%feature("director") UnaryFunction1D<float>;
+%feature("director") UnaryFunction1D<double>;
+%feature("director") UnaryFunction1D<Vec2f>;
+%feature("director") UnaryFunction1D<Vec3f>;
+
+%template(UnaryFunction1DVoid) UnaryFunction1D<void>;
+%template(UnaryFunction1DUnsigned) UnaryFunction1D<unsigned>;
+%template(UnaryFunction1DFloat) UnaryFunction1D<float>;
+%template(UnaryFunction1DDouble) UnaryFunction1D<double>;
+%template(UnaryFunction1DVec2f) UnaryFunction1D<Vec2f>;
+%template(UnaryFunction1DVec3f) UnaryFunction1D<Vec3f>;
+%template(UnaryFunction1DVectorViewShape) UnaryFunction1D<std::vector<ViewShape*> >;
+# endif // SWIG
+
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions1D {
+
+ // GetXF1D
+ /*! Returns the X 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetXF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetXF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetXF1D(IntegrationType iType) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "GetXF1D"*/
+ string getName() const {
+ return "GetXF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter) ;
+ };
+
+ // GetYF1D
+ /*! Returns the Y 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetYF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetYF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "GetYF1D"*/
+ string getName() const {
+ return "GetYF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter) ;
+ };
+
+ // GetZF1D
+ /*! Returns the Z 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetZF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetZF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "GetZF1D"*/
+ string getName() const {
+ return "GetZF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter) ;
+ };
+
+ // GetProjectedXF1D
+ /*! Returns the projected X 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedXF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetProjectedXF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetProjectedXF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ public:
+ /*! Returns the string "GetProjectedXF1D"*/
+ string getName() const {
+ return "GetProjectedXF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter);
+ };
+
+ // GetProjectedYF1D
+ /*! Returns the projected Y 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedYF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetProjectedYF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetProjectedYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ public:
+ /*! Returns the string "GetProjectedYF1D"*/
+ string getName() const {
+ return "GetProjectedYF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter);
+ };
+
+ // GetProjectedZF1D
+ /*! Returns the projected Z 3D coordinate of an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetProjectedZF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::GetProjectedZF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ GetProjectedZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ public:
+ /*! Returns the string "GetProjectedZF1D"*/
+ string getName() const {
+ return "GetProjectedZF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter);
+ };
+
+ // Orientation2DF1D
+ /*! Returns the 2D orientation as a Vec2f*/
+ class LIB_VIEW_MAP_EXPORT Orientation2DF1D : public UnaryFunction1D<Vec2f>
+ {
+ private:
+ Functions0D::VertexOrientation2DF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Orientation2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType){}
+ /*! Returns the string "Orientation2DF1D"*/
+ string getName() const {
+ return "Orientation2DF1D";
+ }
+ /*! the () operator.*/
+ Vec2f operator()(Interface1D& inter);
+ };
+
+ // Orientation3DF1D
+ /*! Returns the 3D orientation as a Vec3f. */
+ class LIB_VIEW_MAP_EXPORT Orientation3DF1D : public UnaryFunction1D<Vec3f>
+ {
+ private:
+ Functions0D::VertexOrientation3DF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Orientation3DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec3f>(iType){}
+ /*! Returns the string "Orientation3DF1D"*/
+ string getName() const {
+ return "Orientation3DF1D";
+ }
+ /*! the () operator.*/
+ Vec3f operator()(Interface1D& inter);
+ };
+
+ // ZDiscontinuityF1D
+ /*! Returns a real giving the distance between
+ * and Interface1D and the shape that lies behind (occludee).
+ * This distance is evaluated in the camera space and normalized
+ * between 0 and 1. Therefore, if no oject is occluded by the
+ * shape to which the Interface1D belongs to, 1 is returned.
+ */
+ class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D<real>
+ {
+ private:
+ Functions0D::ZDiscontinuityF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ ZDiscontinuityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType){}
+ /*! Returns the string "ZDiscontinuityF1D"*/
+ string getName() const {
+ return "ZDiscontinuityF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter);
+ };
+
+ // QuantitativeInvisibilityF1D
+ /*! Returns the Quantitative Invisibility of an Interface1D element.
+ * If the Interface1D is a ViewEdge, then there is no ambiguity
+ * concerning the result. But, if the Interface1D results of a chaining
+ * (chain, stroke), then it might be made of several 1D elements
+ * of different Quantitative Invisibilities.
+ */
+ class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF1D : public UnaryFunction1D<unsigned>
+ {
+ private:
+ Functions0D::QuantitativeInvisibilityF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ QuantitativeInvisibilityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<unsigned int>(iType) {}
+ /*! Returns the string "QuantitativeInvisibilityF1D"*/
+ string getName() const {
+ return "QuantitativeInvisibilityF1D";
+ }
+ /*! the () operator.*/
+ unsigned operator()(Interface1D& inter);
+ };
+
+ // CurveNatureF1D
+/*! Returns the nature of the Interface1D (silhouette, ridge, crease...).
+ * Except if the Interface1D is a ViewEdge, this result might be ambiguous.
+ * Indeed, the Interface1D might result from the gathering of several 1D elements,
+ * each one being of a different nature. An integration method, such as
+ * the MEAN, might give, in this case, irrelevant results.
+ */
+ class LIB_VIEW_MAP_EXPORT CurveNatureF1D : public UnaryFunction1D<Nature::EdgeNature>
+ {
+ private:
+ Functions0D::CurveNatureF0D _func;
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ CurveNatureF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Nature::EdgeNature>(iType) {}
+ /*! Returns the string "CurveNatureF1D"*/
+ string getName() const {
+ return "CurveNatureF1D";
+ }
+ /*! the () operator.*/
+ Nature::EdgeNature operator()(Interface1D& inter);
+ };
+
+ // TimeStampF1D
+/*! Returns the time stamp of the Interface1D. */
+ class LIB_VIEW_MAP_EXPORT TimeStampF1D : public UnaryFunction1D<void>
+ {
+ public:
+ /*! Returns the string "TimeStampF1D"*/
+ string getName() const {
+ return "TimeStampF1D";
+ }
+ /*! the () operator.*/
+ void operator()(Interface1D& inter);
+ };
+
+ // IncrementChainingTimeStampF1D
+/*! Increments the chaining time stamp of the Interface1D. */
+ class LIB_VIEW_MAP_EXPORT IncrementChainingTimeStampF1D : public UnaryFunction1D<void>
+ {
+ public:
+ /*! Returns the string "IncrementChainingTimeStampF1D"*/
+ string getName() const {
+ return "IncrementChainingTimeStampF1D";
+ }
+ /*! the () operator.*/
+ void operator()(Interface1D& inter);
+ };
+
+ // ChainingTimeStampF1D
+/*! Sets the chaining time stamp of the Interface1D. */
+ class LIB_VIEW_MAP_EXPORT ChainingTimeStampF1D : public UnaryFunction1D<void>
+ {
+ public:
+ /*! Returns the string "ChainingTimeStampF1D"*/
+ string getName() const {
+ return "ChainingTimeStampF1D";
+ }
+ /*! the () operator.*/
+ void operator()(Interface1D& inter);
+ };
+
+
+ // Curvature2DAngleF1D
+/*! Returns the 2D curvature as an angle for an Interface1D. */
+ class LIB_VIEW_MAP_EXPORT Curvature2DAngleF1D : public UnaryFunction1D<real>
+ {
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Curvature2DAngleF1D(IntegrationType iType = MEAN) : UnaryFunction1D<real>(iType) {}
+ /*! Returns the string "Curvature2DAngleF1D"*/
+ string getName() const {
+ return "Curvature2DAngleF1D";
+ }
+ /*! the () operator.*/
+ real operator()(Interface1D& inter) {
+ return integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+ private:
+ Functions0D::Curvature2DAngleF0D _fun;
+ };
+
+ // Normal2DF1D
+ /*! Returns the 2D normal for an interface 1D. */
+ class LIB_VIEW_MAP_EXPORT Normal2DF1D : public UnaryFunction1D<Vec2f>
+ {
+ public:
+ /*! Builds the functor.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ Normal2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {}
+ /*! Returns the string "Normal2DF1D"*/
+ string getName() const {
+ return "Normal2DF1D";
+ }
+ /*! the () operator.*/
+ Vec2f operator()(Interface1D& inter) {
+ return integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+ private:
+ Functions0D::Normal2DF0D _fun;
+ };
+
+ // GetShapeF1D
+ /*! Returns list of shapes covered by this Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetShapeF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+ {
+ public:
+ /*! Builds the functor.
+ */
+ GetShapeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+ /*! Returns the string "GetShapeF1D"*/
+ string getName() const {
+ return "GetShapeF1D";
+ }
+ /*! the () operator.*/
+ std::vector<ViewShape*> operator()(Interface1D& inter);
+ };
+
+ // GetOccludersF1D
+ /*! Returns list of occluding shapes covered by this Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetOccludersF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+ {
+ public:
+ /*! Builds the functor.
+ */
+ GetOccludersF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+ /*! Returns the string "GetOccludersF1D"*/
+ string getName() const {
+ return "GetOccludersF1D";
+ }
+ /*! the () operator.*/
+ std::vector<ViewShape*> operator()(Interface1D& inter);
+ };
+
+ // GetOccludeeF1D
+ /*! Returns list of occluded shapes covered by this Interface1D. */
+ class LIB_VIEW_MAP_EXPORT GetOccludeeF1D : public UnaryFunction1D<std::vector<ViewShape*> >
+ {
+ public:
+ /*! Builds the functor.
+ */
+ GetOccludeeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {}
+ /*! Returns the string "GetOccludeeF1D"*/
+ string getName() const {
+ return "GetOccludeeF1D";
+ }
+ /*! the () operator.*/
+ std::vector<ViewShape*> operator()(Interface1D& inter);
+ };
+
+ // internal
+ ////////////
+
+ // getOccludeeF1D
+ LIB_VIEW_MAP_EXPORT
+ void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+ // getOccludersF1D
+ LIB_VIEW_MAP_EXPORT
+ void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+ // getShapeF1D
+ LIB_VIEW_MAP_EXPORT
+ void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes);
+
+} // end of namespace Functions1D
+
+#endif // FUNCTIONS1D_HPP
diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h
new file mode 100755
index 00000000000..eec39d2f7bc
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface0D.h
@@ -0,0 +1,351 @@
+//
+// Filename : Interface0D.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Interface to 0D elts
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INTERFACE0D_H
+# define INTERFACE0D_H
+
+# include <string>
+# include <iostream>
+# include "../system/Id.h"
+# include "../system/Precision.h"
+# include "../winged_edge/Nature.h"
+# include "../geometry/Geom.h"
+using namespace std;
+
+//
+// Interface0D
+//
+//////////////////////////////////////////////////
+
+class FEdge;
+class SVertex;
+class ViewVertex;
+class NonTVertex;
+class TVertex;
+/*! Base class for any 0D element. */
+class Interface0D
+{
+public:
+
+ /*! Returns the string "Interface0D".*/
+ virtual string getExactTypeName() const {
+ return "Interface0D";
+ }
+
+ // Data access methods
+
+ /*! Returns the 3D x coordinate of the point. */
+ virtual real getX() const {
+ cerr << "Warning: method getX() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 3D y coordinate of the point. */
+ virtual real getY() const {
+ cerr << "Warning: method getY() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 3D z coordinate of the point. */
+ virtual real getZ() const {
+ cerr << "Warning: method getZ() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 3D point. */
+ virtual Geometry::Vec3f getPoint3D() const {
+ cerr << "Warning: method getPoint3D() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 2D x coordinate of the point. */
+ virtual real getProjectedX() const {
+ cerr << "Warning: method getProjectedX() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 2D y coordinate of the point. */
+ virtual real getProjectedY() const {
+ cerr << "Warning: method getProjectedY() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 2D z coordinate of the point. */
+ virtual real getProjectedZ() const {
+ cerr << "Warning: method getProjectedZ() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the 2D point. */
+ virtual Geometry::Vec2f getPoint2D() const {
+ cerr << "Warning: method getPoint2D() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the FEdge that lies between this Interface0D and the
+ * Interface0D given as argument. */
+ virtual FEdge* getFEdge(Interface0D&) {
+ cerr << "Warning: method getFEdge() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the Id of the point. */
+ virtual Id getId() const {
+ cerr << "Warning: method getId() not implemented" << endl;
+ return Id(0, 0);
+ }
+
+ /*! Returns the nature of the point. */
+ virtual Nature::VertexNature getNature() const {
+ cerr << "Warning: method getNature() not implemented" << endl;
+ return Nature::POINT;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ cerr << "Warning: can't cast this Interface0D in SVertex" << endl;
+ return 0;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ cerr << "Warning: can't cast this Interface0D in ViewVertex" << endl;
+ return 0;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ cerr << "Warning: can't cast this Interface0D in NonTVertex" << endl;
+ return 0;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ cerr << "Warning: can't cast this Interface0D in TVertex" << endl;
+ return 0;
+ }
+};
+
+
+//
+// Interface0DIteratorNested
+//
+//////////////////////////////////////////////////
+
+class Interface0DIteratorNested
+{
+public:
+
+ virtual ~Interface0DIteratorNested() {}
+
+ virtual string getExactTypeName() const {
+ return "Interface0DIteratorNested";
+ }
+
+ virtual Interface0D& operator*() = 0;
+
+ virtual Interface0D* operator->() {
+ return &(operator*());
+ }
+
+ virtual void increment() = 0;
+
+ virtual void decrement() = 0;
+
+ virtual bool isBegin() const = 0;
+
+ virtual bool isEnd() const = 0;
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const = 0;
+
+ virtual bool operator!=(const Interface0DIteratorNested& it) const {
+ return !(*this == it);
+ }
+
+ /*! Returns the curvilinear abscissa */
+ virtual float t() const = 0;
+ /*! Returns the point parameter 0<u<1 */
+ virtual float u() const = 0;
+
+ virtual Interface0DIteratorNested* copy() const = 0;
+};
+
+
+//
+// Interface0DIterator
+//
+//////////////////////////////////////////////////
+
+/*! Class defining an iterator over Interface0D elements.
+ * An instance of this iterator is always obtained
+ * from a 1D element.
+ * \attention In the scripting language, you must call
+ * \code it2 = Interface0DIterator(it1) \endcode instead of \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 Interface0DIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+class Interface0DIterator
+{
+public:
+
+ Interface0DIterator(Interface0DIteratorNested* it = NULL) {
+ _iterator = it;
+ }
+
+ /*! Copy constructor */
+ Interface0DIterator(const Interface0DIterator& it) {
+ _iterator = it._iterator->copy();
+ }
+
+ /*! Destructor */
+ virtual ~Interface0DIterator() {
+ if (_iterator)
+ delete _iterator;
+ }
+
+ /*! Operator =
+ * \attention In the scripting language, you must call
+ * \code it2 = Interface0DIterator(it1) \endcode instead of \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 Interface0DIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+ Interface0DIterator& operator=(const Interface0DIterator& it) {
+ if(_iterator)
+ delete _iterator;
+ _iterator = it._iterator->copy();
+ return *this;
+ }
+
+ /*! Returns the string "Interface0DIterator". */
+ string getExactTypeName() const {
+ if (!_iterator)
+ return "Interface0DIterator";
+ return _iterator->getExactTypeName() + "Proxy";
+ }
+
+ // FIXME test it != 0 (exceptions ?)
+
+ /*! Returns a reference to the pointed Interface0D.
+ * In the scripting language, you must call
+ * "getObject()" instead using this operator.
+ */
+ Interface0D& operator*() {
+ return _iterator->operator*();
+ }
+
+ /*! Returns a pointer to the pointed Interface0D.
+ * Can't be called in the scripting language.
+ */
+ Interface0D* operator->() {
+ return &(operator*());
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ Interface0DIterator& operator++() {
+ _iterator->increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ Interface0DIterator operator++(int) {
+ Interface0DIterator ret(*this);
+ _iterator->increment();
+ return ret;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ Interface0DIterator& operator--() {
+ _iterator->decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ Interface0DIterator operator--(int) {
+ Interface0DIterator ret(*this);
+ _iterator->decrement();
+ return ret;
+ }
+
+ /*! Increments. */
+ void increment() {
+ _iterator->increment();
+ }
+
+ /*! Decrements. */
+ void decrement() {
+ _iterator->decrement();
+ }
+
+ /*! Returns true if the pointed Interface0D is the
+ * first of the 1D element containing the points over
+ * which we're iterating.
+ */
+ bool isBegin() const {
+ return _iterator->isBegin();
+ }
+
+ /*! Returns true if the pointed Interface0D is after the
+ * after the last point of the 1D element we're iterating from.
+ */
+ bool isEnd() const {
+ return _iterator->isEnd();
+ }
+
+ /*! operator == . */
+ bool operator==(const Interface0DIterator& it) const {
+ return _iterator->operator==(*(it._iterator));
+ }
+
+ /*! operator != . */
+ bool operator!=(const Interface0DIterator& it) const {
+ return !(*this == it);
+ }
+
+ /*! Returns the curvilinear abscissa. */
+ inline float t() const {
+ return _iterator->t();
+ }
+ /*! Returns the point parameter in the curve 0<=u<=1. */
+ inline float u() const {
+ return _iterator->u();
+ }
+protected:
+
+ Interface0DIteratorNested* _iterator;
+};
+
+#endif // INTERFACE0D_H
diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h
new file mode 100755
index 00000000000..812187e5ec1
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface1D.h
@@ -0,0 +1,202 @@
+//
+// Filename : Interface1D.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Interface to 1D elts
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef INTERFACE1D_H
+# define INTERFACE1D_H
+
+# include <string>
+# include <iostream>
+# include <float.h>
+# include "../system/Id.h"
+# include "../system/Precision.h"
+# include "../winged_edge/Nature.h"
+# include "Functions0D.h"
+
+using namespace std;
+/*! \file Interface1D.h
+ * Interface1D and related tools definitions
+ */
+// Integration method
+/*! The different integration
+ * methods that can be invoked
+ * to integrate into a single value the set of values obtained
+ * from each 0D element of a 1D element.
+ */
+typedef enum {
+ MEAN,/*!< The value computed for the 1D element is the mean of the values obtained for the 0D elements.*/
+ MIN,/*!< The value computed for the 1D element is the minimum of the values obtained for the 0D elements.*/
+ MAX,/*!< The value computed for the 1D element is the maximum of the values obtained for the 0D elements.*/
+ FIRST,/*!< The value computed for the 1D element is the first of the values obtained for the 0D elements.*/
+ LAST/*!< The value computed for the 1D element is the last of the values obtained for the 0D elements.*/
+} IntegrationType;
+
+/*! Returns a single
+ * value from a set of values evaluated at each 0D element
+ * of this 1D element.
+ * \param fun
+ * The UnaryFunction0D used to compute a value at each Interface0D.
+ * \param it
+ * The Interface0DIterator used to iterate over the 0D elements of
+ * this 1D element. The integration will occur over the 0D elements
+ * starting from the one pointed by it.
+ * \param it_end
+ * The Interface0DIterator pointing the end of the 0D elements of the
+ * 1D element.
+ * \param integration_type
+ * The integration method used to compute a single value from
+ * a set of values.
+ * \return the single value obtained for the 1D element.
+ */
+template <class T>
+T integrate(UnaryFunction0D<T>& fun,
+ Interface0DIterator it,
+ Interface0DIterator it_end,
+ IntegrationType integration_type = MEAN) {
+ T res;
+ T res_tmp;
+ unsigned size;
+ switch (integration_type) {
+ case MIN:
+ res = fun(it);++it;
+ for (; !it.isEnd(); ++it) {
+ res_tmp = fun(it);
+ if (res_tmp < res)
+ res = res_tmp;
+ }
+ break;
+ case MAX:
+ res = fun(it);++it;
+ for (; !it.isEnd(); ++it) {
+ res_tmp = fun(it);
+ if (res_tmp > res)
+ res = res_tmp;
+ }
+ break;
+ case FIRST:
+ res = fun(it);
+ break;
+ case LAST:
+ res = fun(--it_end);
+ break;
+ case MEAN:
+ default:
+ res = fun(it);++it;
+ for (size = 1; !it.isEnd(); ++it, ++size)
+ res += fun(it);
+ res /= (size ? size : 1);
+ break;
+ }
+ return res;
+}
+
+//
+// Interface1D
+//
+//////////////////////////////////////////////////
+
+/*! Base class for any 1D element. */
+class Interface1D
+{
+public:
+
+ /*! Default constructor */
+ Interface1D() {_timeStamp=0;}
+
+ /*! Returns the string "Interface1D" .*/
+ virtual string getExactTypeName() const {
+ return "Interface1D";
+ }
+
+ // Iterator access
+
+ /*! Returns an iterator over the Interface1D vertices,
+ * pointing to the first vertex.
+ */
+ virtual Interface0DIterator verticesBegin() = 0;
+ /*! Returns an iterator over the Interface1D vertices,
+ * pointing after the last vertex.
+ */
+ virtual Interface0DIterator verticesEnd() = 0;
+ /*! Returns an iterator over the Interface1D points,
+ * pointing to the first point. The difference with
+ * verticesBegin() is that here we can iterate over
+ * points of the 1D element at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this 1D element.
+ */
+ virtual Interface0DIterator pointsBegin(float t=0.f) = 0;
+ /*! Returns an iterator over the Interface1D points,
+ * pointing after the last point. The difference with
+ * verticesEnd() is that here we can iterate over
+ * points of the 1D element at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this 1D element.
+ */
+ virtual Interface0DIterator pointsEnd(float t=0.f) = 0;
+
+ // Data access methods
+
+ /*! Returns the 2D length of the 1D element. */
+ virtual real getLength2D() const {
+ cerr << "Warning: method getLength2D() not implemented" << endl;
+ return 0;
+ }
+
+ /*! Returns the Id of the 1D element .*/
+ virtual Id getId() const {
+ cerr << "Warning: method getId() not implemented" << endl;
+ return Id(0, 0);
+ }
+
+ // FIXME: ce truc n'a rien a faire la...(c une requete complexe qui doit etre ds les Function1D)
+ /*! Returns the nature of the 1D element. */
+ virtual Nature::EdgeNature getNature() const {
+ cerr << "Warning: method getNature() not implemented" << endl;
+ return Nature::NO_FEATURE;
+ }
+
+ /*! Returns the time stamp of the 1D element. Mainly used for selection. */
+ virtual unsigned getTimeStamp() const {
+ return _timeStamp;
+ }
+
+ /*! Sets the time stamp for the 1D element. */
+ inline void setTimeStamp(unsigned iTimeStamp){
+ _timeStamp = iTimeStamp;
+ }
+
+protected:
+ unsigned _timeStamp;
+};
+
+#endif // INTERFACE1D_H
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.cpp b/source/blender/freestyle/intern/view_map/Silhouette.cpp
new file mode 100755
index 00000000000..db4f82d369e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.cpp
@@ -0,0 +1,370 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "Silhouette.h"
+#include "ViewMap.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* SVertex */
+ /* */
+ /* */
+ /**********************************/
+
+Nature::VertexNature SVertex::getNature() const {
+ Nature::VertexNature nature = Nature::S_VERTEX;
+ if (_pViewVertex)
+ nature |= _pViewVertex->getNature();
+ return nature;
+}
+
+SVertex * SVertex::castToSVertex(){
+ return this;
+}
+
+ViewVertex * SVertex::castToViewVertex(){
+ return _pViewVertex;
+}
+
+NonTVertex * SVertex::castToNonTVertex(){
+ return dynamic_cast<NonTVertex*>(_pViewVertex);
+}
+
+TVertex * SVertex::castToTVertex(){
+ return dynamic_cast<TVertex*>(_pViewVertex);
+}
+
+float SVertex::shape_importance() const
+{
+ return shape()->importance();
+}
+
+//Material SVertex::material() const {return _Shape->material();}
+Id SVertex::shape_id() const {return _Shape->getId();}
+const SShape * SVertex::shape() const {return _Shape;}
+
+const int SVertex::qi() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->qi();
+}
+
+occluder_container::const_iterator SVertex::occluders_begin() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_begin();
+}
+
+occluder_container::const_iterator SVertex::occluders_end() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_end();
+}
+
+bool SVertex::occluders_empty() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_empty();
+}
+
+int SVertex::occluders_size() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluders_size();
+}
+
+const Polygon3r& SVertex::occludee() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occludee();
+}
+
+const SShape* SVertex::occluded_shape() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occluded_shape();
+}
+
+const bool SVertex::occludee_empty() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->occludee_empty();
+}
+
+real SVertex::z_discontinuity() const
+{
+ if (getNature() & Nature::T_VERTEX)
+ Exception::raiseException();
+ return (_FEdges[0])->z_discontinuity();
+}
+
+FEdge* SVertex::fedge()
+{
+ if (getNature() & Nature::T_VERTEX)
+ return 0;
+ return _FEdges[0];
+}
+
+FEdge* SVertex::getFEdge(Interface0D& inter)
+{
+ FEdge * result = 0;
+ SVertex* iVertexB = dynamic_cast<SVertex*>(&inter);
+ if (!iVertexB)
+ return result;
+ vector<FEdge*>::const_iterator fe=_FEdges.begin(), feend=_FEdges.end();
+ for(;
+ fe!=feend;
+ ++fe)
+ {
+ if( (((*fe)->vertexA() == this) && ((*fe)->vertexB() == iVertexB))
+ || (((*fe)->vertexB() == this) && ((*fe)->vertexA() == iVertexB)))
+ result = (*fe);
+ }
+ if((result == 0) && (getNature() & Nature::T_VERTEX))
+ {
+ SVertex *brother;
+ ViewVertex *vvertex = viewvertex();
+ TVertex * tvertex = dynamic_cast<TVertex*>(vvertex);
+ if(tvertex)
+ {
+ brother = tvertex->frontSVertex();
+ if(this == brother)
+ brother = tvertex->backSVertex();
+ const vector<FEdge*>& fedges = brother->fedges();
+ for(fe=fedges.begin(),feend=fedges.end();
+ fe!=feend;
+ ++fe)
+ {
+ if( (((*fe)->vertexA() == brother) && ((*fe)->vertexB() == iVertexB))
+ || (((*fe)->vertexB() == brother) && ((*fe)->vertexA() == iVertexB)))
+ result = (*fe);
+ }
+ }
+ }
+ if((result == 0) && (iVertexB->getNature() & Nature::T_VERTEX))
+ {
+ SVertex *brother;
+ ViewVertex *vvertex = iVertexB->viewvertex();
+ TVertex * tvertex = dynamic_cast<TVertex*>(vvertex);
+ if(tvertex)
+ {
+ brother = tvertex->frontSVertex();
+ if(iVertexB == brother)
+ brother = tvertex->backSVertex();
+ for(fe=_FEdges.begin(),feend=_FEdges.end();
+ fe!=feend;
+ ++fe)
+ {
+ if( (((*fe)->vertexA() == this) && ((*fe)->vertexB() == brother))
+ || (((*fe)->vertexB() == this) && ((*fe)->vertexA() == brother)))
+ result = (*fe);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+int FEdge::viewedge_nature() const {return _ViewEdge->getNature();}
+//float FEdge::viewedge_length() const {return _ViewEdge->viewedge_length();}
+const SShape* FEdge::occluded_shape() const
+{
+ ViewShape * aShape = _ViewEdge->aShape();
+ if(aShape == 0)
+ return 0;
+ return aShape->sshape();
+}
+
+float FEdge::shape_importance() const
+{
+ return _VertexA->shape()->importance();
+}
+
+int FEdge::invisibility() const
+{
+ return _ViewEdge->qi();
+}
+
+occluder_container::const_iterator FEdge::occluders_begin() const {return _ViewEdge->occluders_begin();}
+occluder_container::const_iterator FEdge::occluders_end() const {return _ViewEdge->occluders_end();}
+bool FEdge::occluders_empty() const {return _ViewEdge->occluders_empty();}
+int FEdge::occluders_size() const {return _ViewEdge->occluders_size();}
+const bool FEdge::occludee_empty() const
+{
+ return _ViewEdge->occludee_empty();
+}
+
+
+
+Id FEdge::shape_id() const
+{
+ return _VertexA->shape()->getId();
+}
+const SShape* FEdge::shape() const
+{
+ return _VertexA->shape();
+}
+
+real FEdge::z_discontinuity() const
+{
+ if(!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER))
+ {
+ return 0;
+ }
+
+ BBox<Vec3r> box = ViewMap::getInstance()->getScene3dBBox();
+
+ Vec3r bbox_size_vec(box.getMax() - box.getMin());
+ real bboxsize = bbox_size_vec.norm();
+ if(occludee_empty())
+
+ {
+ //return FLT_MAX;
+
+ return 1.0;
+
+ //return bboxsize;
+
+ }
+ // real result;
+ // z_discontinuity_functor<SVertex> _functor;
+
+ // Evaluate<SVertex,z_discontinuity_functor<SVertex> >(&_functor, iCombination, result )
+ Vec3r middle((_VertexB->point3d()-_VertexA->point3d()));
+
+ middle /= 2;
+ Vec3r disc_vec(middle - _occludeeIntersection);
+ real res = disc_vec.norm() / bboxsize;
+ return res;
+
+ //return fabs((middle.z()-_occludeeIntersection.z()));
+}
+
+
+//float FEdge::local_average_depth(int iCombination ) const
+//{
+//
+// float result;
+// local_average_depth_functor<SVertex> functor;
+// Evaluate(&functor, iCombination, result);
+//
+// return result;
+//}
+//float FEdge::local_depth_variance(int iCombination ) const
+//{
+// float result;
+//
+// local_depth_variance_functor<SVertex> functor;
+//
+// Evaluate(&functor, iCombination, result);
+//
+// return result;
+//}
+//
+//
+//real FEdge::local_average_density( float sigma, int iCombination) const
+//{
+// float result;
+//
+// density_functor<SVertex> functor(sigma);
+//
+// Evaluate(&functor, iCombination, result);
+//
+// return result;
+//}
+//
+////Vec3r FEdge::normal(int& oException /* = Exception::NO_EXCEPTION */)
+////{
+//// Vec3r Na = _VertexA->normal(oException);
+//// if(oException != Exception::NO_EXCEPTION)
+//// return Na;
+//// Vec3r Nb = _VertexB->normal(oException);
+//// if(oException != Exception::NO_EXCEPTION)
+//// return Nb;
+//// return (Na+Nb)/2.0;
+////}
+//
+//Vec3r FEdge::curvature2d_as_vector(int iCombination) const
+//{
+// Vec3r result;
+// curvature2d_as_vector_functor<SVertex> _functor;
+// Evaluate<Vec3r,curvature2d_as_vector_functor<SVertex> >(&_functor, iCombination, result );
+// return result;
+//}
+//
+//real FEdge::curvature2d_as_angle(int iCombination) const
+//{
+// real result;
+// curvature2d_as_angle_functor<SVertex> _functor;
+// Evaluate<real,curvature2d_as_angle_functor<SVertex> >(&_functor, iCombination, result );
+// return result;
+//}
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdgeSharp */
+ /* */
+ /* */
+ /**********************************/
+
+//Material FEdge::material() const
+//{
+// return _VertexA->shape()->material();
+//}
+const Material& FEdgeSharp::aMaterial() const {
+ return _VertexA->shape()->material(_aMaterialIndex);
+}
+
+const Material& FEdgeSharp::bMaterial() const {
+ return _VertexA->shape()->material(_bMaterialIndex);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdgeSmooth */
+ /* */
+ /* */
+ /**********************************/
+
+const Material& FEdgeSmooth::material() const {
+ return _VertexA->shape()->material(_MaterialIndex);
+}
diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h
new file mode 100755
index 00000000000..e88bf23b210
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -0,0 +1,1417 @@
+//
+// Filename : Silhouette.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a silhouette structure
+// Date of creation : 25/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SILHOUETTE_H
+# define SILHOUETTE_H
+
+# include <iostream>
+# include <string>
+# include <vector>
+# include <set>
+# include <float.h>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../geometry/BBox.h"
+# include "../scene_graph/Material.h"
+# include "../geometry/Polygon.h"
+# include "../system/Exception.h"
+# include "Interface0D.h"
+# include "Interface1D.h"
+# include "../winged_edge/Curvature.h"
+
+using namespace std;
+using namespace Geometry;
+
+class ViewShape;
+typedef vector<ViewShape*> occluder_container;
+
+ /**********************************/
+ /* */
+ /* */
+ /* SVertex */
+ /* */
+ /* */
+ /**********************************/
+
+class FEdge;
+class ViewVertex;
+class SShape;
+
+/*! Class to define a vertex of the embedding. */
+class LIB_VIEW_MAP_EXPORT SVertex : public Interface0D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "SVertex" .*/
+ virtual string getExactTypeName() const {
+ return "SVertex";
+ }
+
+ // Data access methods
+
+ /*! Returns the 3D x coordinate of the vertex .*/
+ virtual real getX() const {
+ return _Point3D.x();
+ }
+
+ /*! Returns the 3D y coordinate of the vertex .*/
+ virtual real getY() const {
+ return _Point3D.y();
+ }
+
+ /*! Returns the 3D z coordinate of the vertex .*/
+ virtual real getZ() const {
+ return _Point3D.z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ return _Point3D;
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const {
+ return _Point2D.x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const {
+ return _Point2D.y();
+ }
+
+ /*! Returns the projected 3D z coordinate of the vertex .*/
+ virtual real getProjectedZ() const {
+ return _Point2D.z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return Vec2f((float)_Point2D.x(),(float)_Point2D.y());
+ }
+
+ /*! Returns the FEdge that lies between this Svertex and the
+ * Interface0D given as argument. */
+ virtual FEdge* getFEdge(Interface0D&);
+
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+
+ /*! Returns the nature of the vertex .*/
+ virtual Nature::VertexNature getNature() const;
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex();
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex();
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex();
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex();
+
+public:
+
+ typedef vector<FEdge*> fedges_container;
+
+private:
+
+ Id _Id;
+ Vec3r _Point3D;
+ Vec3r _Point2D;
+ set<Vec3r> _Normals;
+ vector<FEdge*> _FEdges; // the edges containing this vertex
+ SShape *_Shape; // the shape to which belongs the vertex
+ ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one.
+ real _curvatureFredo;
+ Vec2r _directionFredo;
+ CurvatureInfo* _curvature_info;
+
+public:
+
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+
+ /*! Default constructor.*/
+ inline SVertex() {
+ _Id = 0;
+ userdata = NULL;
+ _Shape = NULL;
+ _pViewVertex = 0;
+ _curvature_info = 0;
+ }
+
+ /*! Builds a SVertex from 3D coordinates and an Id. */
+ inline SVertex(const Vec3r &iPoint3D, const Id& id) {
+ _Point3D = iPoint3D;
+ _Id=id;
+ userdata = NULL;
+ _Shape = NULL;
+ _pViewVertex=0;
+ _curvature_info = 0;
+ }
+
+ /*! Copy constructor. */
+ inline SVertex(SVertex& iBrother) {
+ _Id = iBrother._Id;
+ _Point3D = iBrother.point3D();
+ _Point2D = iBrother.point2D();
+ _Normals = iBrother._Normals;
+ _FEdges = iBrother.fedges();
+ _Shape = iBrother.shape();
+ _pViewVertex = iBrother._pViewVertex;
+ if (!(iBrother._curvature_info))
+ _curvature_info = 0;
+ else
+ _curvature_info = new CurvatureInfo(*(iBrother._curvature_info));
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+
+ /*! Destructor. */
+ virtual ~SVertex() {
+ if (_curvature_info)
+ delete _curvature_info;
+ }
+
+ /*! Cloning method. */
+ virtual SVertex * dupplicate() {
+ SVertex *clone = new SVertex(*this);
+ return clone;
+ }
+
+ /*! operator == */
+ virtual bool operator==(const SVertex& iBrother) {
+ return ((_Point2D == iBrother._Point2D) &&
+ (_Point3D == iBrother._Point3D));
+ }
+
+ /* accessors */
+ inline const Vec3r& point3D() const {return _Point3D;}
+ inline const Vec3r& point2D() const {return _Point2D;}
+ /*! Returns the set of normals for this Vertex.
+ * In a smooth surface, a vertex has exactly one normal.
+ * In a sharp surface, a vertex can have any number of normals.
+ */
+ inline set<Vec3r> normals() {return _Normals;}
+ /*! Returns the number of different normals for this vertex. */
+ inline unsigned normalsSize() const {return _Normals.size();}
+ inline const vector<FEdge*>& fedges() {return _FEdges;}
+ inline fedges_container::iterator fedges_begin() {return _FEdges.begin();}
+ inline fedges_container::iterator fedges_end() {return _FEdges.end();}
+ inline SShape * shape() {return _Shape;}
+ inline real z() const {return _Point2D[2];}
+ /*! If this SVertex is also a ViewVertex, this method
+ * returns a pointer onto this ViewVertex. 0 is returned
+ * otherwise.
+ */
+ inline ViewVertex * viewvertex() {return _pViewVertex;}
+
+ /*! modifiers */
+ /*! Sets the 3D coordinates of the SVertex. */
+ inline void SetPoint3D(const Vec3r &iPoint3D) {_Point3D = iPoint3D;}
+ /*! Sets the 3D projected coordinates of the SVertex. */
+ inline void SetPoint2D(const Vec3r &iPoint2D) {_Point2D = iPoint2D;}
+ /*! Adds a normal to the Svertex's set of normals. If the same
+ * normal is already in the set, nothing changes.
+ */
+ inline void AddNormal(const Vec3r& iNormal)
+ {
+ _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done
+ }
+
+ void setCurvatureInfo(CurvatureInfo* ci) {
+ _curvature_info = ci;
+ }
+
+ const CurvatureInfo* getCurvatureInfo() const {
+ return _curvature_info;
+ }
+
+ /* Fredo's normal and curvature*/
+ void setCurvatureFredo(real c) {_curvatureFredo=c;}
+ void setDirectionFredo(Vec2r d) {_directionFredo=d;}
+ real curvatureFredo () {return _curvatureFredo;}
+ const Vec2r directionFredo () {return _directionFredo;}
+
+ /*! Sets the Id */
+ inline void SetId(const Id& id) {_Id = id;}
+ inline void SetFEdges(const vector<FEdge*>& iFEdges) {_FEdges = iFEdges;}
+ inline void SetShape(SShape *iShape) {_Shape = iShape;}
+ inline void SetViewVertex(ViewVertex *iViewVertex) {_pViewVertex = iViewVertex;}
+ /*! Add an FEdge to the list of edges emanating from this SVertex. */
+ inline void AddFEdge(FEdge* iFEdge) {_FEdges.push_back(iFEdge);}
+ /* replaces edge 1 by edge 2 in the list of edges */
+ inline void Replace(FEdge *e1, FEdge *e2)
+ {
+ vector<FEdge*>::iterator insertedfe;
+ for(vector<FEdge*>::iterator fe=_FEdges.begin(),fend=_FEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ if((*fe) == e1)
+ {
+ insertedfe = _FEdges.insert(fe, e2);// inserts e2 before fe.
+ // returns an iterator pointing toward e2. fe is invalidated.
+ // we want to remove e1, but we can't use fe anymore:
+ insertedfe++; // insertedfe points now to e1
+ _FEdges.erase(insertedfe);
+ return;
+ }
+ }
+ }
+
+public:
+
+ /* Information access interface */
+
+ FEdge *fedge() ; // for non T vertex
+ inline const Vec3r& point2d() const {return point2D();}
+ inline const Vec3r& point3d() const {return point3D();}
+ inline Vec3r normal() const {if(_Normals.size() == 1) return (*(_Normals.begin())); Exception::raiseException(); return *(_Normals.begin());}
+ //Material material() const ;
+ Id shape_id() const ;
+ const SShape* shape() const ;
+ float shape_importance() const ;
+
+ const int qi() const ;
+ occluder_container::const_iterator occluders_begin() const ;
+ occluder_container::const_iterator occluders_end() const ;
+ bool occluders_empty() const ;
+ int occluders_size() const ;
+ const Polygon3r& occludee() const ;
+ const SShape * occluded_shape() const ;
+ const bool occludee_empty() const ;
+ real z_discontinuity() const ;
+ //inline float local_average_depth() const ;
+ // inline float local_depth_variance() const ;
+ // inline real local_average_density(float sigma = 2.3f) const ;
+ //inline Vec3r shaded_color() const ;
+ // inline Vec3r orientation2d() const ;
+ // inline Vec3r orientation3d() const ;
+ // inline Vec3r curvature2d_as_vector() const ;
+ /*! angle in radians */
+ // inline real curvature2d_as_angle() const ;
+
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+class ViewEdge;
+/*! Base Class for feature edges.
+ * This FEdge can represent a silhouette, a crease,
+ * a ridge/valley, a border or a suggestive contour.
+ * For silhouettes, the FEdge is oriented
+ * such as, the visible face lies on the left of the edge.
+ * For borders, the FEdge is oriented
+ * such as, the face lies on the left of the edge.
+ * An FEdge can represent an initial edge of the mesh
+ * or runs accross a face of the initial mesh depending
+ * on the smoothness or sharpness of the mesh.
+ * This class is specialized into a smooth and a sharp
+ * version since their properties slightly vary from
+ * one to the other.
+ */
+class LIB_VIEW_MAP_EXPORT FEdge : public Interface1D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "FEdge" . */
+ virtual string getExactTypeName() const {
+ return "FEdge";
+ }
+
+ // Data access methods
+
+ /*! Returns the 2D length of the FEdge. */
+ virtual real getLength2D() const {
+ if (!_VertexA || !_VertexB)
+ return 0;
+ return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm();
+ }
+
+ /*! Returns the Id of the FEdge. */
+ virtual Id getId() const {
+ return _Id;
+ }
+
+public:
+
+ // An edge can only be of one kind (SILHOUETTE or BORDER, etc...)
+ // For an multi-nature edge there must be several different FEdge.
+ // DEBUG:
+ // Vec3r A;
+ // Vec3r u;
+ // vector<Polygon3r> _Occludees;
+ // Vec3r intersection;
+ // vector<Vec3i> _Cells;
+
+protected:
+ SVertex *_VertexA;
+ SVertex *_VertexB;
+ Id _Id;
+ Nature::EdgeNature _Nature;
+ //vector<Polygon3r> _Occluders; // visibility // NON GERE PAR LE COPY CONSTRUCTOR!!
+
+ FEdge *_NextEdge; // next edge on the chain
+ FEdge *_PreviousEdge;
+ ViewEdge *_ViewEdge;
+ // Sometimes we need to deport the visibility computation onto another
+ // edge. For example the exact edges use edges of the mesh to
+ // compute their visibility
+
+ Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge
+ Vec3r _occludeeIntersection;
+ bool _occludeeEmpty;
+
+ bool _isSmooth;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void *userdata;
+ /*! Default constructor */
+ inline FEdge() {
+ userdata = NULL;
+ _Nature = Nature::NO_FEATURE;
+ _NextEdge = NULL;
+ _PreviousEdge = NULL;
+ _ViewEdge = NULL;
+ //_hasVisibilityPoint=false;
+ _occludeeEmpty = true;
+ _isSmooth = false;
+ }
+ /*! Builds an FEdge going from vA to vB. */
+ inline FEdge(SVertex *vA, SVertex *vB) {
+ userdata = NULL;
+ _VertexA = vA;
+ _VertexB = vB;
+ _Nature = Nature::NO_FEATURE;
+ _NextEdge=NULL;
+ _PreviousEdge=NULL;
+ _ViewEdge = NULL;
+ //_hasVisibilityPoint=false;
+ _occludeeEmpty = true;
+ _isSmooth = false;
+ }
+ /*! Copy constructor */
+ inline FEdge(FEdge& iBrother)
+ {
+ _VertexA = iBrother.vertexA();
+ _VertexB = iBrother.vertexB();
+ _NextEdge = iBrother.nextEdge();
+ _PreviousEdge = iBrother._PreviousEdge;
+ _Nature = iBrother.getNature();
+ _Id = iBrother._Id;
+ _ViewEdge = iBrother._ViewEdge;
+ //_hasVisibilityPoint = iBrother._hasVisibilityPoint;
+ //_VisibilityPointA = iBrother._VisibilityPointA;
+ //_VisibilityPointB = iBrother._VisibilityPointB;
+ _aFace = iBrother._aFace;
+ _occludeeEmpty = iBrother._occludeeEmpty;
+ _isSmooth = iBrother._isSmooth;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+ /*! Destructor */
+ virtual ~FEdge() {}
+ /*! Cloning method. */
+ virtual FEdge* dupplicate()
+ {
+ FEdge *clone = new FEdge(*this);
+ return clone;
+ }
+ /* accessors */
+ /*! Returns the first SVertex. */
+ inline SVertex* vertexA() {return _VertexA;}
+ /*! Returns the second SVertex. */
+ inline SVertex* vertexB() {return _VertexB;}
+ /*! Returns the first SVertex if i=0, the seccond SVertex
+ * if i=1. */
+ inline SVertex* operator[](const unsigned short int& i) const{
+ return i%2==0 ? _VertexA : _VertexB;
+ }
+ /*! Returns the nature of the FEdge. */
+ inline Nature::EdgeNature getNature() const {return _Nature;}
+ /*! Returns the FEdge following this one in the ViewEdge.
+ * If this FEdge is the last of the ViewEdge, 0 is returned.
+ */
+ inline FEdge * nextEdge() {return _NextEdge;}
+ /*! Returns the Edge preceding this one in the ViewEdge.
+ * If this FEdge is the first one of the ViewEdge, 0 is returned.
+ */
+ inline FEdge * previousEdge() {return _PreviousEdge;}
+ inline SShape * shape() {return _VertexA->shape();}
+ //inline int invisibility() const {return _Occluders.size();}
+ int invisibility() const ;
+ //inline const vector<Polygon3r>& occluders() const {return _Occluders;}
+ /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */
+ inline ViewEdge * viewedge() const {return _ViewEdge;}
+ inline Vec3r center3d() {return Vec3r((_VertexA->point3D()+_VertexB->point3D())/2.0);}
+ inline Vec3r center2d() {return Vec3r((_VertexA->point2D()+_VertexB->point2D())/2.0);}
+ // inline bool hasVisibilityPoint() const {return _hasVisibilityPoint;}
+ // inline Vec3r visibilityPointA() const {return _VisibilityPointA;}
+ // inline Vec3r visibilityPointB() const {return _VisibilityPointB;}
+ inline const Polygon3r& aFace() const {return _aFace;}
+ inline const Vec3r& getOccludeeIntersection() { return _occludeeIntersection; }
+ inline bool getOccludeeEmpty() { return _occludeeEmpty; }
+ /*! Returns true if this FEdge is a smooth FEdge. */
+ inline bool isSmooth() const {return _isSmooth;}
+
+ /* modifiers */
+ /*! Sets the first SVertex. */
+ inline void SetVertexA(SVertex *vA) {_VertexA = vA;}
+ /*! Sets the second SVertex. */
+ inline void SetVertexB(SVertex *vB) {_VertexB = vB;}
+ /*! Sets the FEdge Id . */
+ inline void SetId(const Id& id) {_Id = id;}
+ /*! Sets the pointer to the next FEdge. */
+ inline void SetNextEdge(FEdge* iEdge) {_NextEdge = iEdge;}
+ /*! Sets the pointer to the previous FEdge. */
+ inline void SetPreviousEdge(FEdge *iEdge) {_PreviousEdge = iEdge;}
+ /*! Sets the nature of this FEdge. */
+ inline void SetNature(Nature::EdgeNature iNature) {_Nature = iNature;}
+ //inline void AddOccluder(Polygon3r& iPolygon) {_Occluders.push_back(iPolygon);}
+ /*! Sets the ViewEdge to which this FEdge belongs to. */
+ inline void SetViewEdge(ViewEdge *iViewEdge) {_ViewEdge = iViewEdge;}
+ // inline void SetHasVisibilityPoint(bool iBool) {_hasVisibilityPoint = iBool;}
+ // inline void SetVisibilityPointA(const Vec3r& iPoint) {_VisibilityPointA = iPoint;}
+ // inline void SetVisibilityPointB(const Vec3r& iPoint) {_VisibilityPointB = iPoint;}
+ inline void SetaFace(Polygon3r& iFace) {_aFace = iFace;}
+ inline void SetOccludeeIntersection(const Vec3r& iPoint) {_occludeeIntersection = iPoint;}
+ inline void SetOccludeeEmpty(bool iempty) {_occludeeEmpty = iempty;}
+ /*! Sets the flag telling whether this FEdge is smooth or sharp.
+ * true for Smooth, false for Sharp.
+ */
+ inline void SetSmooth(bool iFlag) {_isSmooth = iFlag;}
+
+ /* checks whether two FEdge have a common vertex.
+ * Returns a pointer on the common vertex if it exists,
+ * NULL otherwise.
+ */
+ static inline SVertex* CommonVertex(FEdge *iEdge1, FEdge* iEdge2)
+ {
+ if((NULL == iEdge1) || (NULL == iEdge2))
+ return NULL;
+
+ SVertex *sv1 = iEdge1->vertexA();
+ SVertex *sv2 = iEdge1->vertexB();
+ SVertex *sv3 = iEdge2->vertexA();
+ SVertex *sv4 = iEdge2->vertexB();
+
+ if((sv1 == sv3) || (sv1 == sv4))
+ {
+ return sv1;
+ }
+ else if((sv2 == sv3) || (sv2 == sv4))
+ {
+ return sv2;
+ }
+
+ return NULL;
+ }
+
+ inline const SVertex* min2d() const
+ {
+ if(_VertexA->point2D() < _VertexB->point2D())
+ return _VertexA;
+ else
+ return _VertexB;
+ }
+ inline const SVertex* max2d() const
+ {
+ if(_VertexA->point2D() < _VertexB->point2D())
+ return _VertexB;
+ else
+ return _VertexA;
+ }
+
+ /* Information access interface */
+ /* Information access interface */
+
+ //Material material() const ;
+ Id shape_id() const ;
+ const SShape * shape() const ;
+ float shape_importance() const ;
+ inline const int qi() const {return invisibility();}
+ occluder_container::const_iterator occluders_begin() const ;
+ occluder_container::const_iterator occluders_end() const ;
+ bool occluders_empty() const ;
+ int occluders_size() const ;
+ inline const Polygon3r& occludee() const {return aFace();}
+ const SShape * occluded_shape() const ;
+ //inline const bool occludee_empty() const {return _occludeeEmpty;}
+ const bool occludee_empty() const ;
+ real z_discontinuity() const ;
+ // inline float local_average_depth(int iCombination = 0) const ;
+ // inline float local_depth_variance(int iCombination = 0) const ;
+ // inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const ;
+ //inline Vec3r shaded_color(int iCombination = 0) const {}
+ int viewedge_nature() const ;
+ //float viewedge_length() const ;
+ inline Vec3r orientation2d() const {return Vec3r(_VertexB->point2d()-_VertexA->point2d());}
+ inline Vec3r orientation3d() const {return Vec3r(_VertexB->point3d()-_VertexA->point3d());}
+ // //inline real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);}
+ // inline Vec3r curvature2d_as_vector(int iCombination = 0) const ;
+ // /* angle in degrees*/
+ // inline real curvature2d_as_angle(int iCombination = 0) const ;
+
+
+ // Iterator access (Interface1D)
+ /*! Returns an iterator over the 2 (!) SVertex
+ * pointing to the first SVertex. */
+ virtual inline Interface0DIterator verticesBegin();
+ /*! Returns an iterator over the 2 (!) SVertex
+ * pointing after the last SVertex. */
+ virtual inline Interface0DIterator verticesEnd();
+
+ /*! Returns an iterator over the FEdge points,
+ * pointing to the first point. The difference with
+ * verticesBegin() is that here we can iterate over
+ * points of the FEdge at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this FEdge.
+ */
+ virtual inline Interface0DIterator pointsBegin(float t=0.f);
+ /*! Returns an iterator over the FEdge points,
+ * pointing after the last point. The difference with
+ * verticesEnd() is that here we can iterate over
+ * points of the FEdge at a any given sampling.
+ * Indeed, for each iteration, a virtual point is created.
+ * \param t
+ * The sampling with which we want to iterate over points of
+ * this FEdge.
+ */
+ virtual inline Interface0DIterator pointsEnd(float t=0.f);
+};
+
+//
+// SVertexIterator
+//
+/////////////////////////////////////////////////
+
+namespace FEdgeInternal {
+
+ class SVertexIterator : public Interface0DIteratorNested
+ {
+ public:
+
+ SVertexIterator() {
+ _vertex = NULL;
+ _edge = NULL;
+ }
+
+ SVertexIterator(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _edge = vi._edge;
+ }
+
+ SVertexIterator(SVertex* v, FEdge* edge) {
+ _vertex = v;
+ _edge = edge;
+ }
+
+ SVertexIterator& operator=(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _edge = vi._edge;
+ return *this;
+ }
+
+ virtual string getExactTypeName() const {
+ return "SVertexIterator";
+ }
+
+ virtual SVertex& operator*() {
+ return *_vertex;
+ }
+
+ virtual SVertex* operator->() {
+ return &(operator*());
+ }
+
+ virtual SVertexIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ virtual SVertexIterator operator++(int) {
+ SVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ virtual SVertexIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ virtual SVertexIterator operator--(int) {
+ SVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ virtual void increment() {
+ if (_vertex == _edge->vertexB()) {
+ _vertex = 0;
+ return;
+ }
+
+ _vertex = _edge->vertexB();
+ }
+
+ virtual void decrement() {
+ if (_vertex == _edge->vertexA()) {
+ _vertex = 0;
+ return;
+ }
+ _vertex = _edge->vertexA();
+ }
+
+ virtual bool isBegin() const {
+ return _vertex == _edge->vertexA();
+ }
+
+ virtual bool isEnd() const {
+ return _vertex == _edge->vertexB();
+ }
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const {
+ const SVertexIterator* it_exact = dynamic_cast<const SVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return ((_vertex == it_exact->_vertex) &&
+ (_edge == it_exact->_edge));
+ }
+
+ virtual float t() const{
+ if(_vertex == _edge->vertexA()){
+ return 0;
+ }
+ return ((float)_edge->getLength2D());
+ }
+ virtual float u() const{
+ if(_vertex == _edge->vertexA()){
+ return 0;
+ }
+ return 1.0;
+ }
+ virtual SVertexIterator* copy() const {
+ return new SVertexIterator(*this);
+ }
+
+ private:
+
+ SVertex* _vertex;
+ FEdge* _edge;
+ };
+
+} // end of namespace FEdgeInternal
+
+// Iterator access (implementation)
+
+Interface0DIterator FEdge::verticesBegin() {
+ Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this));
+ return ret;
+}
+
+Interface0DIterator FEdge::verticesEnd() {
+ Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this));
+ return ret;
+}
+
+Interface0DIterator FEdge::pointsBegin(float t) {
+ return verticesBegin();
+}
+
+Interface0DIterator FEdge::pointsEnd(float t) {
+ return verticesEnd();
+}
+
+/*! Class defining a sharp FEdge. A Sharp FEdge
+ * corresponds to an initial edge of the input mesh.
+ * It can be a silhouette, a crease or a border.
+ * If it is a crease edge, then it is borded
+ * by two faces of the mesh. Face a lies on its right
+ * whereas Face b lies on its left.
+ * If it is a border edge, then it doesn't have any
+ * face on its right, and thus Face a = 0.
+ */
+class LIB_VIEW_MAP_EXPORT FEdgeSharp : public FEdge
+{
+protected:
+ Vec3r _aNormal; // When following the edge, normal of the right face
+ Vec3r _bNormal; // When following the edge, normal of the left face
+ unsigned _aMaterialIndex;
+ unsigned _bMaterialIndex;
+
+public:
+ /*! Default constructor. */
+ inline FEdgeSharp() : FEdge(){
+ _aMaterialIndex = _bMaterialIndex = 0;
+ }
+ /*! Builds an FEdgeSharp going from vA to vB. */
+ inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB){
+ _aMaterialIndex = _bMaterialIndex = 0;
+ }
+ /*! Copy constructor. */
+ inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother){
+ _aNormal = iBrother._aNormal;
+ _bNormal = iBrother._bNormal;
+ _aMaterialIndex = iBrother._aMaterialIndex;
+ _bMaterialIndex = iBrother._bMaterialIndex;
+ }
+ /*! Destructor. */
+ virtual ~FEdgeSharp() {}
+ /*! Cloning method. */
+ virtual FEdge* dupplicate(){
+ FEdge *clone = new FEdgeSharp(*this);
+ return clone;
+ }
+ /*! Returns the normal to the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no normal.
+ */
+ inline const Vec3r& normalA() {return _aNormal;}
+ /*! Returns the normal to the face lying on the
+ * left of the FEdge.
+ */
+ inline const Vec3r& normalB() {return _bNormal;}
+ /*! Returns the index of the material of the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no material.
+ */
+ inline unsigned aMaterialIndex() const {return _aMaterialIndex;}
+ /*! Returns the material of the face lying on the
+ * right of the FEdge. If this FEdge is a border,
+ * it has no Face on its right and therefore, no material.
+ */
+ const Material& aMaterial() const ;
+ /*! Returns the index of the material of the face lying on the
+ * left of the FEdge.
+ */
+ inline unsigned bMaterialIndex() const {return _bMaterialIndex;}
+ /*! Returns the material of the face lying on the
+ * left of the FEdge.
+ */
+ const Material& bMaterial() const ;
+
+ /*! Sets the normal to the face lying on the right of the FEdge. */
+ inline void SetNormalA(const Vec3r& iNormal) {_aNormal = iNormal;}
+ /*! Sets the normal to the face lying on the left of the FEdge. */
+ inline void SetNormalB(const Vec3r& iNormal) {_bNormal = iNormal;}
+ /*! Sets the index of the material lying on the right of the FEdge.*/
+ inline void SetaMaterialIndex(unsigned i) {_aMaterialIndex = i;}
+ /*! Sets the index of the material lying on the left of the FEdge.*/
+ inline void SetbMaterialIndex(unsigned i) {_bMaterialIndex = i;}
+
+};
+
+/*! Class defining a smooth edge. This kind of edge typically
+ * runs across a face of the input mesh. It can be
+ * a silhouette, a ridge or valley, a suggestive contour.
+ */
+class LIB_VIEW_MAP_EXPORT FEdgeSmooth : public FEdge
+{
+protected:
+ Vec3r _Normal;
+ unsigned _MaterialIndex;
+ // bool _hasVisibilityPoint;
+ // Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented
+ // Vec3r _VisibilityPointB; // using its 2 extremity points A and B
+ void * _Face; // In case of exact silhouette, Face is the WFace crossed by Fedge
+ // NON GERE PAR LE COPY CONSTRUCTEUR
+public:
+ /*! Default constructor. */
+ inline FEdgeSmooth() : FEdge(){
+ _Face=0;
+ _MaterialIndex = 0;
+ _isSmooth = true;
+ }
+ /*! Builds an FEdgeSmooth going from vA to vB. */
+ inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB){
+ _Face=0;
+ _MaterialIndex = 0;
+ _isSmooth = true;
+
+ }
+ /*! Copy constructor. */
+ inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother){
+ _Normal = iBrother._Normal;
+ _Face = iBrother._Face;
+ _MaterialIndex = iBrother._MaterialIndex;
+ _isSmooth = true;
+ }
+ /*! Destructor. */
+ virtual ~FEdgeSmooth() {}
+ /*! Cloning method. */
+ virtual FEdge* dupplicate(){
+ FEdge *clone = new FEdgeSmooth(*this);
+ return clone;
+ }
+
+ inline void * face() const {return _Face;}
+ /*! Returns the normal to the Face it is running accross. */
+ inline const Vec3r& normal() {return _Normal;}
+ /*! Returns the index of the material of the face it is running accross. */
+ inline unsigned materialIndex() const {return _MaterialIndex;}
+ /*! Returns the material of the face it is running accross. */
+ const Material& material() const ;
+
+ inline void SetFace(void * iFace) {_Face = iFace;}
+ /*! Sets the normal to the Face it is running accross. */
+ inline void SetNormal(const Vec3r& iNormal) {_Normal = iNormal;}
+ /*! Sets the index of the material of the face it is running accross. */
+ inline void SetMaterialIndex(unsigned i) {_MaterialIndex = i;}
+};
+ /**********************************/
+ /* */
+ /* */
+ /* SShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+/*! Class to define a feature shape. It is the gathering
+ * of feature elements from an identified input shape
+ */
+class LIB_VIEW_MAP_EXPORT SShape
+{
+private:
+ vector<FEdge*> _chains; // list of fedges that are chains starting points.
+ vector<SVertex*> _verticesList; // list of all vertices
+ vector<FEdge*> _edgesList; // list of all edges
+ Id _Id;
+ BBox<Vec3r> _BBox;
+ vector<Material> _Materials;
+
+ float _importance;
+
+ ViewShape *_ViewShape;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void* userdata; // added by E.T.
+ /*! Default constructor */
+ inline SShape()
+ {
+ userdata = 0;
+
+ _importance = 0.f;
+ _ViewShape = 0;
+ }
+ /*! Copy constructor */
+ inline SShape(SShape& iBrother)
+ {
+ userdata = 0;
+ _Id = iBrother._Id;
+ _BBox = iBrother.bbox();
+ _Materials = iBrother._Materials;
+
+ _importance = iBrother._importance;
+
+ _ViewShape = iBrother._ViewShape;
+
+
+ //---------
+ // vertices
+ //---------
+ vector<SVertex*>::iterator sv,svend;
+ vector<SVertex*>& verticesList = iBrother.GetVertexList();
+ for(sv=verticesList.begin(), svend=verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ SVertex *newv = new SVertex(*(*sv));
+ newv->SetShape(this);
+ _verticesList.push_back(newv);
+ }
+
+ //------
+ // edges
+ //------
+ vector<FEdge*>::iterator e,eend;
+ vector<FEdge*>& edgesList = iBrother.GetEdgeList();
+ for(e=edgesList.begin(),eend=edgesList.end();
+ e!=eend;
+ e++)
+ {
+ FEdge *newe = (*e)->dupplicate();
+ _edgesList.push_back(newe);
+ }
+
+ //-------------------------
+ // starting chain edges
+ //-------------------------
+ vector<FEdge*>::iterator fe,fend;
+ vector<FEdge*>& fedges = iBrother.GetChains();
+ for(fe=fedges.begin(),fend=fedges.end();
+ fe!=fend;
+ fe++)
+ {
+ _chains.push_back((FEdge*)((*fe)->userdata));
+ }
+
+
+ //-------------------------
+ // remap edges in vertices:
+ //-------------------------
+ for(sv=_verticesList.begin(),svend=_verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ const vector<FEdge*>& fedgeList = (*sv)->fedges();
+ vector<FEdge*> newfedgelist;
+ for(vector<FEdge*>::const_iterator fed=fedgeList.begin(),fedend=fedgeList.end();
+ fed!=fedend;
+ fed++)
+ {
+ FEdge *current = *fed;
+ newfedgelist.push_back((FEdge*)current->userdata);
+ }
+ (*sv)->SetFEdges(newfedgelist);
+ }
+
+ //-------------------------------------
+ // remap vertices and nextedge in edges:
+ //-------------------------------------
+ for(e=_edgesList.begin(),eend=_edgesList.end();
+ e!=eend;
+ e++)
+ {
+ (*e)->SetVertexA((SVertex*)((*e)->vertexA()->userdata));
+ (*e)->SetVertexB((SVertex*)((*e)->vertexB()->userdata));
+ (*e)->SetNextEdge((FEdge*)((*e)->nextEdge()->userdata));
+ (*e)->SetPreviousEdge((FEdge*)((*e)->previousEdge()->userdata));
+ }
+
+
+ // reset all brothers userdata to NULL:
+ //-------------------------------------
+ //---------
+ // vertices
+ //---------
+ for(sv=_verticesList.begin(),svend=_verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ (*sv)->userdata = NULL;
+ }
+
+ //------
+ // edges
+ //------
+ for(e=_edgesList.begin(),eend=_edgesList.end();
+ e!=eend;
+ e++)
+ {
+ (*e)->userdata = NULL;
+ }
+ }
+ /*! Cloning method. */
+ virtual SShape * dupplicate()
+ {
+ SShape *clone = new SShape(*this);
+ return clone;
+ }
+ /*! Destructor. */
+ virtual inline ~SShape()
+ {
+ vector<SVertex*>::iterator sv,svend;
+ vector<FEdge*>::iterator e,eend;
+ if(0 != _verticesList.size())
+ {
+ for(sv=_verticesList.begin(),svend=_verticesList.end();
+ sv!=svend;
+ sv++)
+ {
+ delete (*sv);
+ }
+ _verticesList.clear();
+ }
+
+ if(0 != _edgesList.size())
+ {
+ for(e=_edgesList.begin(),eend=_edgesList.end();
+ e!=eend;
+ e++)
+ {
+ delete (*e);
+ }
+ _edgesList.clear();
+ }
+
+ //! Clear the chains list
+ //-----------------------
+ if(0 != _chains.size())
+ {
+ _chains.clear();
+ }
+ }
+
+ /*! Adds a FEdge to the list of FEdges. */
+ inline void AddEdge(FEdge *iEdge)
+ {
+ _edgesList.push_back(iEdge);
+ }
+
+ /*! Adds a SVertex to the list of SVertex of this Shape.
+ * The SShape attribute of the SVertex is also set to 'this'.
+ */
+ inline void AddNewVertex(SVertex* iv) {iv->SetShape(this);_verticesList.push_back(iv);}
+ inline void AddChain(FEdge *iEdge){
+ _chains.push_back(iEdge);
+ }
+
+ inline SVertex * CreateSVertex(const Vec3r& P3D, const Vec3r& P2D, const Id& id)
+ {
+ SVertex *Ia = new SVertex(P3D, id);
+ Ia->SetPoint2D(P2D);
+ AddNewVertex(Ia);
+ return Ia;
+ }
+ /* splits an edge into several edges.
+ * The edge's vertices are passed rather than
+ * the edge itself. This way, all feature edges (SILHOUETTE,
+ * CREASE, BORDER) are splitted in the same time.
+ * The processed edges are flagged as done (using the userdata
+ * flag).One single new vertex is created whereas
+ * several splitted edges might created for the different
+ * kinds of edges. These new elements are added to the lists
+ * maintained by the shape.
+ * new chains are also created.
+ * ioA
+ * The first vertex for the edge that gets splitted
+ * ioB
+ * The second vertex for the edge that gets splitted
+ * iParameters
+ * A vector containing 2D real vectors indicating the parameters
+ * giving the intersections coordinates in 3D and in 2D.
+ * These intersections points must be sorted from B to A.
+ * Each parameter defines the intersection point I as I=A+T*AB.
+ * T<0 and T>1 are then incorrect insofar as they give intersections
+ * points that lie outside the segment.
+ * ioNewEdges
+ * The edges that are newly created (the initial edges are not
+ * included) are added to this list.
+ */
+ inline void SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges)
+ {
+
+ SVertex *ioA = fe->vertexA();
+ SVertex *ioB = fe->vertexB();
+ Vec3r A = ioA->point3D();
+ Vec3r B = ioB->point3D();
+ Vec3r a = ioA->point2D();
+ Vec3r b = ioB->point2D();
+ SVertex *svA, *svB;
+
+ Vec3r newpoint3d,newpoint2d;
+ vector<SVertex*> intersections;
+ real t,T;
+ for(vector<Vec2r>::const_iterator p=iParameters.begin(),pend=iParameters.end();
+ p!=pend;
+ p++)
+ {
+ T=(*p)[0];
+ t=(*p)[1];
+
+ if((t < 0) || (t > 1))
+ cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl;
+
+ // compute the 3D and 2D coordinates for the intersections points:
+ newpoint3d = Vec3r(A + T*(B-A));
+ newpoint2d = Vec3r(a + t*(b-a));
+
+ // create new SVertex:
+ // (we keep B's id)
+ SVertex* newVertex = new SVertex(newpoint3d, ioB->getId());
+ newVertex->SetPoint2D(newpoint2d);
+
+ // Add this vertex to the intersections list:
+ intersections.push_back(newVertex);
+
+ // Add this vertex to this sshape:
+ AddNewVertex(newVertex);
+ }
+
+ for(vector<SVertex*>::iterator sv=intersections.begin(),svend=intersections.end();
+ sv!=svend;
+ sv++)
+ {
+ svA = fe->vertexA();
+ svB = fe->vertexB();
+
+ // We split edge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ // The edge AB becomes edge AA'.
+ (fe)->SetVertexB((*sv));
+ // a new edge, A'B is created.
+ FEdge *newEdge;
+ if(fe->isSmooth()){
+ newEdge = new FEdgeSmooth((*sv), svB);
+ FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge);
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ se->SetMaterialIndex(fes->materialIndex());
+ }else{
+ newEdge = new FEdgeSharp((*sv), svB);
+ FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(fe);
+ se->SetaMaterialIndex(fes->aMaterialIndex());
+ se->SetbMaterialIndex(fes->bMaterialIndex());
+ }
+
+ newEdge->SetNature((fe)->getNature());
+
+
+ // to build a new chain:
+ AddChain(newEdge);
+ // add the new edge to the sshape edges list.
+ AddEdge(newEdge);
+ // add new edge to the list of new edges passed as argument:
+ ioNewEdges.push_back(newEdge);
+
+ // update edge A'B for the next pointing edge
+ newEdge->SetNextEdge((fe)->nextEdge());
+ fe->nextEdge()->SetPreviousEdge(newEdge);
+ Id id(fe->getId().getFirst(), fe->getId().getSecond()+1);
+ newEdge->SetId(fe->getId());
+ fe->SetId(id);
+
+ // update edge AA' for the next pointing edge
+ //ioEdge->SetNextEdge(newEdge);
+ (fe)->SetNextEdge(NULL);
+
+ // update vertex pointing edges list:
+ // -- vertex B --
+ svB->Replace((fe), newEdge);
+ // -- vertex A' --
+ (*sv)->AddFEdge((fe));
+ (*sv)->AddFEdge(newEdge);
+ }
+
+ }
+
+ /* splits an edge into 2 edges. The new vertex and edge are added
+ * to the sshape list of vertices and edges
+ * a new chain is also created.
+ * returns the new edge.
+ * ioEdge
+ * The edge that gets splitted
+ * newpoint
+ * x,y,z coordinates of the new point.
+ */
+ inline FEdge* SplitEdgeIn2(FEdge* ioEdge, SVertex * ioNewVertex)
+ {
+ SVertex *A = ioEdge->vertexA();
+ SVertex *B = ioEdge->vertexB();
+
+
+ // We split edge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+
+ // a new edge, A'B is created.
+ FEdge *newEdge;
+ if(ioEdge->isSmooth()){
+ newEdge = new FEdgeSmooth(ioNewVertex, B);
+ FEdgeSmooth * se = dynamic_cast<FEdgeSmooth*>(newEdge);
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(ioEdge);
+ se->SetMaterialIndex(fes->materialIndex());
+ }else{
+ newEdge = new FEdgeSharp(ioNewVertex, B);
+ FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(ioEdge);
+ se->SetaMaterialIndex(fes->aMaterialIndex());
+ se->SetbMaterialIndex(fes->bMaterialIndex());
+ }
+ newEdge->SetNature(ioEdge->getNature());
+
+
+ if(ioEdge->nextEdge() != 0)
+ ioEdge->nextEdge()->SetPreviousEdge(newEdge);
+
+ // update edge A'B for the next pointing edge
+ newEdge->SetNextEdge(ioEdge->nextEdge());
+ // update edge A'B for the previous pointing edge
+ newEdge->SetPreviousEdge(0); // because it is now a TVertex
+ Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1);
+ newEdge->SetId(ioEdge->getId());
+ ioEdge->SetId(id);
+
+ // update edge AA' for the next pointing edge
+ ioEdge->SetNextEdge(0); // because it is now a TVertex
+
+ // update vertex pointing edges list:
+ // -- vertex B --
+ B->Replace(ioEdge, newEdge);
+ // -- vertex A' --
+ ioNewVertex->AddFEdge(ioEdge);
+ ioNewVertex->AddFEdge(newEdge);
+
+ // to build a new chain:
+ AddChain(newEdge);
+ AddEdge(newEdge); // FIXME ??
+
+ // The edge AB becomes edge AA'.
+ ioEdge->SetVertexB(ioNewVertex);
+
+ if(ioEdge->isSmooth()){
+ ((FEdgeSmooth*)newEdge)->SetFace(((FEdgeSmooth*)ioEdge)->face());
+ }
+
+ return newEdge;
+ }
+
+ /*! Sets the Bounding Box of the Shape */
+ inline void SetBBox(const BBox<Vec3r>& iBBox) {_BBox = iBBox;}
+
+ /*! Compute the bbox of the sshape */
+ inline void ComputeBBox()
+ {
+ if(0 == _verticesList.size())
+ return;
+
+ Vec3r firstVertex = _verticesList[0]->point3D();
+ real XMax = firstVertex[0];
+ real YMax = firstVertex[1];
+ real ZMax = firstVertex[2];
+
+ real XMin = firstVertex[0];
+ real YMin = firstVertex[1];
+ real ZMin = firstVertex[2];
+
+ vector<SVertex*>::iterator v,vend;
+ // parse all the coordinates to find
+ // the Xmax, YMax, ZMax
+ for(v=_verticesList.begin(),vend=_verticesList.end();
+ v!=vend;
+ v++)
+ {
+ Vec3r vertex = (*v)->point3D();
+ // X
+ real x = vertex[0];
+ if(x > XMax)
+ XMax = x;
+ if(x < XMin)
+ XMin = x;
+
+ // Y
+ real y = vertex[1];
+ if(y > YMax)
+ YMax = y;
+ if(y < YMin)
+ YMin = y;
+
+ // Z
+ real z = vertex[2];
+ if(z > ZMax)
+ ZMax = z;
+ if(z < ZMin)
+ ZMin = z;
+ }
+
+
+ SetBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+ }
+
+ inline void RemoveEdgeFromChain(FEdge *iEdge)
+ {
+ for(vector<FEdge*>::iterator fe=_chains.begin(), feend=_chains.end();
+ fe!=feend;
+ fe++)
+ {
+ if(iEdge == (*fe))
+ {
+ _chains.erase(fe);
+ break;
+ }
+ }
+ }
+
+ inline void RemoveEdge(FEdge *iEdge)
+ {
+ for(vector<FEdge*>::iterator fe=_edgesList.begin(), feend=_edgesList.end();
+ fe!=feend;
+ fe++)
+ {
+ if(iEdge == (*fe))
+ {
+ _edgesList.erase(fe);
+ break;
+ }
+ }
+ }
+
+ /* accessors */
+ /*! Returns the list of SVertex of the Shape. */
+ inline vector<SVertex*>& GetVertexList() {return _verticesList;} // Get vertices list
+ /*! Returns the list of FEdges of the Shape. */
+ inline vector<FEdge*>& GetEdgeList() {return _edgesList;} // Get edges list
+ inline vector<FEdge*>& GetChains() {return _chains;}
+ /*! Returns the bounding box of the shape. */
+ inline const BBox<Vec3r>& bbox() {return _BBox;}
+ /*! Returns the ith material of the shape. */
+ inline const Material& material(unsigned i) const {return _Materials[i];}
+ /*! Returns the list of materials of the Shape. */
+ inline const vector<Material>& materials() const {return _Materials;}
+ inline ViewShape * viewShape() {return _ViewShape;}
+ inline float importance() const {return _importance;}
+ /*! Returns the Id of the Shape. */
+ inline Id getId() const { return _Id; }
+
+ /* Modififers */
+ /*! Sets the Id of the shape.*/
+ inline void SetId(Id id) {_Id = id;}
+ /*! Sets the list of materials for the shape */
+ inline void SetMaterials(const vector<Material>& iMaterials) {_Materials = iMaterials;}
+ inline void SetViewShape(ViewShape *iShape) {_ViewShape = iShape;}
+ inline void SetImportance(float importance){_importance = importance;}
+};
+
+#endif // SILHOUETTE_H
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
new file mode 100755
index 00000000000..19b8a632ffe
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
@@ -0,0 +1,185 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SilhouetteGeomEngine.h"
+#include "Silhouette.h"
+#include "../geometry/GeomUtils.h"
+
+using namespace std;
+
+Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0,0,0);
+real SilhouetteGeomEngine::_translation[3] = {0,0,0};
+real SilhouetteGeomEngine::_modelViewMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_projectionMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_transform[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+int SilhouetteGeomEngine::_viewport[4] = {1,1,1,1}; // the viewport
+real SilhouetteGeomEngine::_Focal = 0.0;
+
+real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = {{1,0,0,0},
+ {0,1,0,0},
+ {0,0,1,0},
+ {0,0,0,1}};
+real SilhouetteGeomEngine::_znear = 0.0;
+real SilhouetteGeomEngine::_zfar = 100.0;
+
+SilhouetteGeomEngine * SilhouetteGeomEngine::_pInstance = 0;
+
+void SilhouetteGeomEngine::SetTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal)
+{
+ unsigned int i,j;
+ _translation[0] = iModelViewMatrix[3][0];
+ _translation[1] = iModelViewMatrix[3][1];
+ _translation[2] = iModelViewMatrix[3][2];
+
+ for(i=0; i<4; i++){
+ for(j=0; j<4; j++)
+ {
+ _modelViewMatrix[i][j] = iModelViewMatrix[j][i];
+ _glModelViewMatrix[i][j] = iModelViewMatrix[i][j];
+ }
+ }
+
+ for(i=0; i<4; i++){
+ for(j=0; j<4; j++)
+ {
+ _projectionMatrix[i][j] = iProjectionMatrix[j][i];
+ _glProjectionMatrix[i][j] = iProjectionMatrix[i][j];
+ }
+ }
+
+ for(i=0; i<4; i++){
+ for(j=0; j<4; j++)
+ {
+ _transform[i][j] = 0;
+ for(unsigned int k=0; k<4; k++)
+ _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j];
+ }
+ }
+
+ for(i=0; i<4; i++){
+ _viewport[i] = iViewport[i];
+ }
+ _Focal = iFocal;
+}
+
+void SilhouetteGeomEngine::SetFrustum(real iZNear, real iZFar)
+{
+ _znear = iZNear;
+ _zfar = iZFar;
+}
+
+void SilhouetteGeomEngine::retrieveViewport(int viewport[4]){
+ memcpy(viewport, _viewport, 4*sizeof(int));
+}
+//#define HUGE 1e9
+
+void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex*>& ioVertices)
+{
+ Vec3r newPoint;
+ // real min=HUGE;
+ // real max=-HUGE;
+ vector<SVertex*>::iterator sv, svend;
+
+ for(sv=ioVertices.begin(), svend=ioVertices.end();
+ sv!=svend;
+ sv++)
+ {
+ GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
+ newPoint[2] = (-newPoint[2]-_znear)/(_zfar-_znear); // normalize Z between 0 and 1
+ (*sv)->SetPoint2D(newPoint);
+ //cerr << (*sv)->point2d().z() << " ";
+ // real d=(*sv)->point2d()[2];
+ // if (d>max) max =d;
+ // if (d<min) min =d;
+ }
+ // for(sv=ioVertices.begin(), svend=ioVertices.end();
+ // sv!=svend;
+ // sv++)
+ // {
+ // Vec3r P((*sv)->point2d());
+ // (*sv)->SetPoint2D(Vec3r(P[0], P[1], 1.0-(P[2]-min)/(max-min)));
+ // //cerr<<(*sv)->point2d()[2]<<" ";
+ // }
+}
+
+void SilhouetteGeomEngine::ProjectSilhouette(SVertex* ioVertex)
+{
+ Vec3r newPoint;
+ // real min=HUGE;
+ // real max=-HUGE;
+ vector<SVertex*>::iterator sv, svend;
+ GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport);
+ newPoint[2] = (-newPoint[2]-_znear)/(_zfar-_znear); // normalize Z between 0 and 1
+ ioVertex->SetPoint2D(newPoint);
+}
+
+real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t)
+{
+ // we need to compute for each parameter t the corresponding
+ // parameter T which gives the intersection in 3D.
+ //currentEdge = (*fe);
+ Vec3r A = (fe)->vertexA()->point3D();
+ Vec3r B = (fe)->vertexB()->point3D();
+ Vec3r Ai = (fe)->vertexA()->point2D();
+ Vec3r Bi = (fe)->vertexB()->point2D();
+ Vec3r AB = Vec3r((B-A)); // the edge
+ Vec3r ABi(Bi-Ai);
+ Vec3r Ac, Bc;
+ GeomUtils::fromWorldToCamera(A, Ac, _modelViewMatrix);
+ GeomUtils::fromWorldToCamera(B, Bc, _modelViewMatrix);
+
+ Vec3r Ii = Vec3r((Ai+t*ABi)); // I image
+ // let us compute the 3D point corresponding to the 2D intersection point
+ // and lying on the edge:
+ Vec3r Ir, Ic;
+ GeomUtils::fromImageToRetina(Ii, Ir, _viewport);
+ GeomUtils::fromRetinaToCamera(Ir, Ic, -_Focal, _projectionMatrix);
+
+ real T;
+ T = (Ic[2]*Ac[1] - Ic[1]*Ac[2])/(Ic[1]*(Bc[2]-Ac[2])-Ic[2]*(Bc[1]-Ac[1]));
+
+ return T;
+}
+
+Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M)
+
+{
+
+ Vec3r newPoint;
+ GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport);
+ newPoint[2] = (-newPoint[2]-_znear)/(_zfar-_znear); // normalize Z between 0 and 1
+ return newPoint;
+
+}
+
diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
new file mode 100755
index 00000000000..159dda1afc0
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
@@ -0,0 +1,122 @@
+//
+// Filename : SilhouetteGeomEngine.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to perform all geometric operations dedicated
+// to silhouette. That, for example, implies that
+// this geom engine has as member data the viewpoint,
+// transformations, projections...
+// Date of creation : 03/09/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef SILHOUETTEGEOMENGINE_H
+# define SILHOUETTEGEOMENGINE_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+
+using namespace Geometry;
+
+class SVertex;
+class FEdge;
+
+class LIB_VIEW_MAP_EXPORT SilhouetteGeomEngine
+{
+private:
+ static Vec3r _Viewpoint; // The viewpoint under which the silhouette has to be computed
+ static real _translation[3];
+ static real _modelViewMatrix[4][4]; // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j)
+ static real _projectionMatrix[4][4]; // the projection matrix (_projectionMatrix[i][j] means element of line i and column j)
+ static real _transform[4][4]; // the global transformation from world to screen (projection included) (_transform[i][j] means element of line i and column j)
+ static int _viewport[4]; // the viewport
+ static real _Focal;
+
+ static real _znear;
+ static real _zfar;
+
+ static real _glProjectionMatrix[4][4]; // GL style (column major) projection matrix
+ static real _glModelViewMatrix[4][4]; // GL style (column major) model view matrix
+
+
+
+ static SilhouetteGeomEngine *_pInstance;
+public:
+
+ /*! retrieves an instance on the singleton */
+ static SilhouetteGeomEngine * getInstance()
+ {
+ if(0 == _pInstance)
+ {
+ _pInstance = new SilhouetteGeomEngine;
+ }
+ return _pInstance;
+ }
+
+ /*! Sets the current viewpoint */
+ static inline void SetViewpoint(const Vec3r& ivp) {_Viewpoint = ivp;}
+
+ /*! Sets the current transformation
+ * iModelViewMatrix
+ * The 4x4 model view matrix, in column major order (openGL like).
+ * iProjection matrix
+ * The 4x4 projection matrix, in column major order (openGL like).
+ * iViewport
+ * The viewport. 4 real array: origin.x, origin.y, width, length
+ * iFocal
+ * The focal length
+ */
+ static void SetTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], const int iViewport[4], real iFocal) ;
+
+ /*! Sets the current znear and zfar
+ */
+ static void SetFrustum(real iZNear, real iZFar) ;
+
+ /* accessors */
+ static void retrieveViewport(int viewport[4]);
+
+ /*! Projects the silhouette in camera coordinates
+ * This method modifies the ioEdges passed as argument.
+ * ioVertices
+ * The vertices to project. It is modified during the
+ * operation.
+ */
+ static void ProjectSilhouette(std::vector<SVertex*>& ioVertices);
+ static void ProjectSilhouette(SVertex* ioVertex);
+
+ /*! transforms the parameter t defining a 2D intersection for edge fe in order to obtain
+ * the parameter giving the corresponding 3D intersection.
+ * Returns the 3D parameter
+ * fe
+ * The edge
+ * t
+ * The parameter for the 2D intersection.
+ */
+ static real ImageToWorldParameter(FEdge *fe, real t);
+
+ /*! From world to image */
+ static Vec3r WorldToImage(const Vec3r& M);
+};
+
+#endif // SILHOUETTEGEOMENGINE_H
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
new file mode 100755
index 00000000000..b2604606aa7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
@@ -0,0 +1,243 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SteerableViewMap.h"
+#include "../image/ImagePyramid.h"
+#include "../image/Image.h"
+#include "Silhouette.h"
+#include <math.h>
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+#include <qstring.h>
+#include <qimage.h>
+
+SteerableViewMap::SteerableViewMap(unsigned int nbOrientations){
+ _nbOrientations = nbOrientations;
+ _bound = cos(M_PI/(float)_nbOrientations);
+ for(unsigned i=0; i<_nbOrientations; ++i){
+ _directions.push_back(Vec2d(cos((float)i*M_PI/(float)_nbOrientations), sin((float)i*M_PI/(float)_nbOrientations)));
+ }
+ Build();
+}
+
+void SteerableViewMap::Build(){
+ _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM
+ memset((_imagesPyramids),0,(_nbOrientations+1)*sizeof(ImagePyramid*));
+}
+
+SteerableViewMap::SteerableViewMap(const SteerableViewMap& iBrother){
+ _nbOrientations = iBrother._nbOrientations;
+ unsigned i;
+ _bound = iBrother._bound;
+ _directions = iBrother._directions;
+ _mapping = iBrother._mapping;
+ _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM
+ for(i=0;i<_nbOrientations+1;++i)
+ _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast<GaussianPyramid*>(iBrother._imagesPyramids[i])));
+}
+
+SteerableViewMap::~SteerableViewMap(){
+ Clear();
+}
+
+void SteerableViewMap::Clear(){
+ unsigned i;
+ if(_imagesPyramids){
+ for(i=0; i<=_nbOrientations; ++i){
+ if(_imagesPyramids[i])
+ delete (_imagesPyramids)[i];
+ }
+ delete [] _imagesPyramids;
+ _imagesPyramids = 0;
+ }
+ if(!_mapping.empty()){
+ for(map<unsigned int, double*>::iterator m=_mapping.begin(), mend=_mapping.end();
+ m!=mend;
+ ++m){
+ delete [] (*m).second;
+ }
+ _mapping.clear();
+ }
+}
+
+void SteerableViewMap::Reset(){
+ Clear();
+ Build();
+}
+
+double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i){
+ double dotp = fabs(dir*_directions[i]);
+ if(dotp < _bound)
+ return 0;
+ if(dotp>1)
+ dotp = 1;
+
+ return cos((float)_nbOrientations/2.0*acos(dotp));
+}
+
+double * SteerableViewMap::AddFEdge(FEdge *iFEdge){
+ unsigned i;
+ unsigned id = iFEdge->getId().getFirst();
+ map<unsigned int, double* >::iterator o = _mapping.find(id);
+ if(o!=_mapping.end()){
+ return (*o).second;
+ }
+ double * res = new double[_nbOrientations];
+ for(i=0; i<_nbOrientations; ++i){
+ res[i] = 0;
+ }
+ Vec3r o2d3 = iFEdge->orientation2d();
+ Vec2r o2d2(o2d3.x(), o2d3.y());
+ real norm = o2d2.norm();
+ if(norm < 1e-6){
+ return res;
+ }
+ o2d2/=norm;
+
+ for(i=0; i<_nbOrientations; ++i){
+ res[i] = ComputeWeight(o2d2, i);
+ }
+ _mapping[id] = res;
+ return res;
+}
+
+unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient){
+ Vec2f dir(orient);
+ unsigned res = 0;
+ real norm = dir.norm();
+ if(norm < 1e-6){
+ return _nbOrientations+1;
+ }
+ dir/=norm;
+ double maxw = 0.f;
+ unsigned winner = _nbOrientations+1;
+ for(unsigned i=0; i<_nbOrientations; ++i){
+ double w = ComputeWeight(dir, i);
+ if(w>maxw){
+ maxw = w;
+ winner = i;
+ }
+ }
+ return winner;
+}
+
+
+unsigned SteerableViewMap::getSVMNumber(unsigned id){
+ map<unsigned int, double* >::iterator o = _mapping.find(id);
+ if(o!=_mapping.end()){
+ double* wvalues= (*o).second;
+ double maxw = 0.f;
+ unsigned winner = _nbOrientations+1;
+ for(unsigned i=0; i<_nbOrientations; ++i){
+ double w = wvalues[i];
+ if(w>maxw){
+ maxw = w;
+ winner = i;
+ }
+ }
+ return winner;
+ }
+ return _nbOrientations+1;
+}
+
+void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, bool copy, unsigned iNbLevels, float iSigma){
+ for(unsigned i=0; i<=_nbOrientations; ++i){
+ ImagePyramid * svm = (_imagesPyramids)[i];
+ if(svm)
+ delete svm;
+ if(copy)
+ svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma);
+ else
+ svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma);
+ _imagesPyramids[i] = svm;
+ }
+}
+
+float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y){
+ ImagePyramid *pyramid = _imagesPyramids[iOrientation];
+ if(pyramid==0){
+ cout << "Warning: this steerable ViewMap level doesn't exist" << endl;
+ return 0;
+ }
+ if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height()))
+ return 0;
+ //float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)*255.f;
+ float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)/32.f; // we encode both the directionality and the lines counting on 8 bits
+ // (because of frame buffer). Thus, we allow until 8 lines to pass through
+ // the same pixel, so that we can discretize the Pi/_nbOrientations angle into
+ // 32 slices. Therefore, for example, in the vertical direction, a vertical line
+ // will have the value 32 on each pixel it passes through.
+ return v;
+}
+
+float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y){
+ return readSteerableViewMapPixel(_nbOrientations,iLevel,x,y);
+}
+
+unsigned int SteerableViewMap::getNumberOfPyramidLevels() const{
+ if(_imagesPyramids[0])
+ return _imagesPyramids[0]->getNumberOfLevels();
+ return 0;
+}
+void SteerableViewMap::saveSteerableViewMap() const {
+ for(unsigned i=0; i<=_nbOrientations; ++i){
+ if(_imagesPyramids[i] == 0){
+ cerr << "SteerableViewMap warning: orientation " << i <<" of steerable View Map whas not been computed yet" << endl;
+ continue;
+ }
+ int ow = _imagesPyramids[i]->width(0);
+ int oh = _imagesPyramids[i]->height(0);
+ QString base("SteerableViewMap");
+ for(unsigned j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){
+ float coeff = 1;//1/255.f; //100*255;//*pow(2,j);
+ QImage qtmp(ow, oh, QImage::Format_RGB32);
+ for(unsigned y=0;y<oh;++y){
+ for(unsigned x=0;x<ow;++x){
+ int c = (int)(coeff*_imagesPyramids[i]->pixel(x,y,j));
+ if(c>255)
+ c=255;
+ //int c = (int)(_imagesPyramids[i]->pixel(x,y,j));
+ qtmp.setPixel(x,y,qRgb(c,c,c));
+ }
+ }
+ qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
+ }
+ // QString base("SteerableViewMap");
+ // for(unsigned j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){
+ // GrayImage * img = _imagesPyramids[i]->getLevel(j);
+ // int ow = img->width();
+ // int oh = img->height();
+ // float coeff = 1; //100*255;//*pow(2,j);
+ // QImage qtmp(ow, oh, 32);
+ // for(unsigned y=0;y<oh;++y){
+ // for(unsigned x=0;x<ow;++x){
+ // int c = (int)(coeff*img->pixel(x,y));
+ // if(c>255)
+ // c=255;
+ // //int c = (int)(_imagesPyramids[i]->pixel(x,y,j));
+ // qtmp.setPixel(x,y,qRgb(c,c,c));
+ // }
+ // }
+ // qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
+ // }
+ //
+ }
+}
diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
new file mode 100755
index 00000000000..fe7c2493752
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h
@@ -0,0 +1,153 @@
+//
+// Filename : SteerbaleViewMap.h
+// Author(s) : Stephane Grabli
+// Purpose : Convenient access to the steerable ViewMap
+// to which any element of the ViewMap belongs to.
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+#ifndef STEERABLEVIEWMAP_H
+# define STEERABLEVIEWMAP_H
+
+#include <map>
+#include "../system/FreestyleConfig.h"
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+using namespace std;
+
+class FEdge;
+class ImagePyramid;
+class GrayImage;
+/*! This class checks for every FEdge in which steerable
+ * it belongs and stores the mapping allowing to retrieve
+ * this information from the FEdge Id
+ */
+class LIB_VIEW_MAP_EXPORT SteerableViewMap{
+protected:
+ map<unsigned int, double* > _mapping; // for each vector the list of nbOrientations weigths corresponding to its contributions to the nbOrientations directional maps
+ unsigned _nbOrientations;
+ ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM
+
+ // internal
+ double _bound; // cos(Pi/N)
+ vector<Vec2d> _directions;
+
+public:
+ SteerableViewMap(unsigned int nbOrientations = 4);
+ SteerableViewMap(const SteerableViewMap& iBrother);
+ virtual ~SteerableViewMap();
+
+ /*! Resets everything */
+ virtual void Reset();
+
+ /*! Adds a FEdge to steerable VM.
+ * Returns the nbOrientations weigths corresponding to
+ * the FEdge contributions to the nbOrientations directional maps.
+ */
+ double* AddFEdge(FEdge *iFEdge);
+
+ /*! Compute the weight of direction dir for orientation iNOrientation */
+ double ComputeWeight(const Vec2d& dir, unsigned iNOrientation);
+
+ /*! Returns the number of the SVM to which a direction belongs
+ * to.
+ * \param dir
+ * The direction
+ */
+ unsigned getSVMNumber(const Vec2f& dir);
+
+ /*! Returns the number of the SVM to which a FEdge belongs
+ * most.
+ * \param id
+ * The First element of the Id struct of the FEdge
+ * we're intersted in.
+ */
+ unsigned getSVMNumber(unsigned id);
+
+ /*! Builds _nbOrientations+1 pyramids of images from the _nbOrientations+1 base images
+ * of the steerable viewmap.
+ * \param steerableBases
+ * The _nbOrientations+1 images constituing the basis for the steerable
+ * pyramid.
+ * \param copy
+ * If false, the data is not duplicated, and Canvas deals
+ * with the memory management of these _nbOrientations+1 images. If true, data
+ * is copied, and it's up to the caller to delete the images.
+ * \params iNbLevels
+ * The number of levels desired for each pyramid.
+ * If iNbLevels == 0, the complete pyramid is built.
+ * \param iSigma
+ * The sigma that will be used for the gaussian blur
+ */
+ void buildImagesPyramids(GrayImage **steerableBases, bool copy = false, unsigned iNbLevels=4, float iSigma = 1.f);
+
+ /*! Reads a pixel value in one of the VewMap density steerable pyramids.
+ * Returns a value between 0 and 1.
+ * \param iOrientation
+ * the number telling which orientation we need to check.
+ * There are _nbOrientations+1 oriented ViewMaps:
+ * 0 -> the ViewMap containing every horizontal lines
+ * 1 -> the ViewMap containing every lines whose orientation is around PI/4
+ * 2 -> the ViewMap containing every vertical lines
+ * 3 -> the ViewMap containing every lines whose orientation is around 3PI/4
+ * 4 -> the complete ViewMap
+ * \param iLevel
+ * The level of the pyramid we want to read
+ * \param x
+ * The abscissa of the desired pixel specified in level0 coordinate
+ * system. The origin is the lower left corner.
+ * \param y
+ * The ordinate of the desired pixel specified in level0 coordinate
+ * system. The origin is the lower left corner.
+ */
+ float readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y);
+
+ /*! Reads a pixel in the one of the level of the
+ * pyramid containing the images of the complete
+ * ViewMap.
+ * Returns a value between 0 and 1.
+ * Equivalent to : readSteerableViewMapPixel(nbOrientations, x,y)
+ */
+ float readCompleteViewMapPixel(int iLevel, int x, int y);
+
+ /*! Returns the number of levels in the pyramids */
+ unsigned int getNumberOfPyramidLevels() const;
+
+ /*! Returns the number of orientations */
+ unsigned int getNumberOfOrientations() const{
+ return _nbOrientations;
+ }
+
+ /*! for debug purposes */
+ void saveSteerableViewMap() const ;
+
+protected:
+ void Clear();
+ void Build();
+
+
+};
+
+#endif // STEERABLEVIEWMAP_H
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
new file mode 100755
index 00000000000..20b3aeb144d
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp
@@ -0,0 +1,666 @@
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewEdgeXBuilder.h"
+#include "../winged_edge/WXEdge.h"
+#include "ViewMap.h"
+#include "SilhouetteGeomEngine.h"
+#include <list>
+
+using namespace std;
+
+void ViewEdgeXBuilder::Init(ViewShape *oVShape){
+ if(0 == oVShape)
+ return;
+
+ // for design conveniance, we store the current SShape.
+ _pCurrentSShape = oVShape->sshape();
+ if(0 == _pCurrentSShape)
+ return;
+
+ _pCurrentVShape = oVShape;
+
+ // Reset previous data
+ //--------------------
+ if(!_SVertexMap.empty())
+ _SVertexMap.clear();
+}
+
+void ViewEdgeXBuilder::BuildViewEdges( WXShape *iWShape, ViewShape *oVShape,
+ vector<ViewEdge*>& ioVEdges,
+ vector<ViewVertex*>& ioVVertices,
+ vector<FEdge*>& ioFEdges,
+ vector<SVertex*>& ioSVertices){
+ // Reinit structures
+ Init(oVShape);
+
+ ViewEdge *vedge ;
+ // Let us build the smooth stuff
+ //----------------------------------------
+ // We parse all faces to find the ones
+ // that contain smooth edges
+ vector<WFace*>& wfaces = iWShape->GetFaceList();
+ vector<WFace*>::iterator wf, wfend;
+ WXFace *wxf;
+ for(wf=wfaces.begin(), wfend=wfaces.end();
+ wf!=wfend;
+ wf++){
+ wxf = dynamic_cast<WXFace*>(*wf);
+ if(false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ?
+ continue;
+ // parse all smooth layers:
+ vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers();
+ for(vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend=smoothLayers.end();
+ sl!=slend;
+ ++sl){
+ if(!(*sl)->hasSmoothEdge())
+ continue;
+ if(stopSmoothViewEdge((*sl))) // has it been parsed already ?
+ continue;
+ // here we know that we're dealing with a face layer that has not been
+ // processed yet and that contains a smooth edge.
+ vedge = BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
+ }
+ }
+
+ // Now let's build sharp view edges:
+ //----------------------------------
+ // Reset all userdata for WXEdge structure
+ //----------------------------------------
+ //iWShape->ResetUserData();
+
+ WXEdge * wxe;
+ vector<WEdge*>& wedges = iWShape->GetEdgeList();
+ //
+ //------------------------------
+ for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end();
+ we!=weend;
+ we++){
+ wxe = dynamic_cast<WXEdge*>(*we);
+ if(Nature::NO_FEATURE == wxe->nature())
+ continue;
+
+ if(!stopSharpViewEdge(wxe)){
+ bool b=true;
+ if(wxe->order() == -1)
+ b = false;
+ BuildSharpViewEdge(OWXEdge(wxe,b));
+ }
+ }
+
+ // Reset all userdata for WXEdge structure
+ //----------------------------------------
+ iWShape->ResetUserData();
+
+ // Add all these new edges to the scene's feature edges list:
+ //-----------------------------------------------------------
+ vector<FEdge*>& newedges = _pCurrentSShape->GetEdgeList();
+ vector<SVertex*>& newVertices = _pCurrentSShape->GetVertexList();
+ vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices();
+ vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges();
+
+ // inserts in ioFEdges, at its end, all the edges of newedges
+ ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
+ ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
+ ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
+ ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
+
+}
+
+ViewEdge * ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer){
+ // Find first edge:
+ OWXFaceLayer first = iFaceLayer;
+ OWXFaceLayer currentFace = first;
+
+ // bidirectional chaining.
+ // first direction
+ list<OWXFaceLayer> facesChain;
+ unsigned size = 0;
+ while(!stopSmoothViewEdge(currentFace.fl)){
+ facesChain.push_back(currentFace);
+ ++size;
+ currentFace.fl->userdata = (void*)1; // processed
+ // Find the next edge!
+ currentFace = FindNextFaceLayer(currentFace);
+ }
+ OWXFaceLayer end = facesChain.back();
+ // second direction
+ currentFace = FindPreviousFaceLayer(first);
+ while(!stopSmoothViewEdge(currentFace.fl)){
+ facesChain.push_front(currentFace);
+ ++size;
+ currentFace.fl->userdata = (void*)1; // processed
+ // Find the previous edge!
+ currentFace = FindPreviousFaceLayer(currentFace);
+ }
+ first = facesChain.front();
+
+ if(iFaceLayer.fl->nature() & Nature::RIDGE){
+ if(size<4){
+ return 0;
+ }
+ }
+
+ // Start a new chain edges
+ ViewEdge * newVEdge = new ViewEdge;
+ newVEdge->SetId(_currentViewId);
+ ++_currentViewId;
+
+ _pCurrentVShape->AddEdge(newVEdge);
+
+
+ // build FEdges
+ FEdge * feprevious = 0;
+ FEdge * fefirst = 0;
+ FEdge * fe;
+ for(list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend=facesChain.end();
+ fl!=flend;
+ ++fl){
+ fe = BuildSmoothFEdge(feprevious, (*fl));
+ fe->SetViewEdge(newVEdge);
+ if(!fefirst)
+ fefirst = fe;
+ feprevious = fe;
+ }
+ // Store the chain starting edge:
+ _pCurrentSShape->AddChain(fefirst);
+ newVEdge->SetNature(iFaceLayer.fl->nature());
+ newVEdge->SetFEdgeA(fefirst);
+ newVEdge->SetFEdgeB(fe);
+
+ // is it a closed loop ?
+ if((first == end) && (size != 1)){
+ fefirst->SetPreviousEdge(fe);
+ fe->SetNextEdge(fefirst);
+ newVEdge->SetA(0);
+ newVEdge->SetB(0);
+ }else{
+ ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
+ ViewVertex *vvb = MakeViewVertex(fe->vertexB());
+
+ ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge);
+ ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge);
+
+ newVEdge->SetA(vva);
+ newVEdge->SetB(vvb);
+ }
+
+ return newVEdge;
+}
+
+ViewEdge * ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge) {
+ // Start a new sharp chain edges
+ ViewEdge * newVEdge = new ViewEdge;
+ newVEdge->SetId(_currentViewId);
+ ++_currentViewId;
+ unsigned size=0;
+
+ _pCurrentVShape->AddEdge(newVEdge);
+
+ // Find first edge:
+ OWXEdge firstWEdge = iWEdge;
+ OWXEdge previousWEdge = firstWEdge;
+ OWXEdge currentWEdge = firstWEdge;
+ list<OWXEdge> edgesChain;
+ // bidirectional chaining
+ // first direction:
+ while(!stopSharpViewEdge(currentWEdge.e)){
+ edgesChain.push_back(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void*)1; // processed
+ // Find the next edge!
+ currentWEdge = FindNextWEdge(currentWEdge);
+ }
+ OWXEdge endWEdge = edgesChain.back();
+ // second direction
+ currentWEdge = FindPreviousWEdge(firstWEdge);
+ while(!stopSharpViewEdge(currentWEdge.e)){
+ edgesChain.push_front(currentWEdge);
+ ++size;
+ currentWEdge.e->userdata = (void*)1; // processed
+ // Find the previous edge!
+ currentWEdge = FindPreviousWEdge(currentWEdge);
+ }
+ firstWEdge = edgesChain.front();
+
+ // build FEdges
+ FEdge * feprevious = 0;
+ FEdge * fefirst = 0;
+ FEdge * fe;
+ for(list<OWXEdge>::iterator we = edgesChain.begin(), weend=edgesChain.end();
+ we!=weend;
+ ++we){
+ fe = BuildSharpFEdge(feprevious, (*we));
+ fe->SetViewEdge(newVEdge);
+ if(!fefirst)
+ fefirst = fe;
+ feprevious = fe;
+ }
+ // Store the chain starting edge:
+ _pCurrentSShape->AddChain(fefirst);
+ newVEdge->SetNature(iWEdge.e->nature());
+ newVEdge->SetFEdgeA(fefirst);
+ newVEdge->SetFEdgeB(fe);
+
+ // is it a closed loop ?
+ if((firstWEdge == endWEdge) && (size!=1)){
+ fefirst->SetPreviousEdge(fe);
+ fe->SetNextEdge(fefirst);
+ newVEdge->SetA(0);
+ newVEdge->SetB(0);
+ }else{
+ ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
+ ViewVertex *vvb = MakeViewVertex(fe->vertexB());
+
+ ((NonTVertex*)vva)->AddOutgoingViewEdge(newVEdge);
+ ((NonTVertex*)vvb)->AddIncomingViewEdge(newVEdge);
+
+ newVEdge->SetA(vva);
+ newVEdge->SetB(vvb);
+ }
+
+ return newVEdge;
+}
+
+OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer& iFaceLayer){
+ WXFace *nextFace = 0;
+ WOEdge * woeend;
+ real tend;
+ if(iFaceLayer.order){
+ woeend = iFaceLayer.fl->getSmoothEdge()->woeb();
+ tend = iFaceLayer.fl->getSmoothEdge()->tb();
+ }else{
+ woeend = iFaceLayer.fl->getSmoothEdge()->woea();
+ tend = iFaceLayer.fl->getSmoothEdge()->ta();
+ }
+ // special case of EDGE_VERTEX config:
+ if((tend == 0.0) || (tend == 1.0)){
+ WVertex *nextVertex;
+ if(tend == 0.0)
+ nextVertex = woeend->GetaVertex();
+ else
+ nextVertex = woeend->GetbVertex();
+ if(nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
+ return OWXFaceLayer(0,true);
+ bool found = false;
+ WVertex::face_iterator f=nextVertex->faces_begin();
+ WVertex::face_iterator fend=nextVertex->faces_end();
+ while((!found) && (f!=fend)){
+ nextFace = dynamic_cast<WXFace*>(*f);
+ if((0 != nextFace) && (nextFace!=iFaceLayer.fl->getFace())){
+ vector<WXFaceLayer*> sameNatureLayers;
+ nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if(sameNatureLayers.size() == 1) {// don't know
+ // maybe should test whether this face has
+ // also a vertex_edge configuration
+ WXFaceLayer * winner = sameNatureLayers[0];
+ if(woeend == winner->getSmoothEdge()->woea()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ ++f;
+ }
+ }else{
+ nextFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woeend));
+ if(0 == nextFace)
+ return OWXFaceLayer(0,true);
+ // if the next face layer has either no smooth edge or
+ // no smooth edge of same nature, no next face
+ if(!nextFace->hasSmoothEdges())
+ return OWXFaceLayer(0,true);
+ vector<WXFaceLayer*> sameNatureLayers;
+ nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face
+ return OWXFaceLayer(0,true);
+ else{
+ WXFaceLayer * winner = sameNatureLayers[0];
+ if(woeend == winner->getSmoothEdge()->woea()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ return OWXFaceLayer(0,true);
+}
+
+OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer) {
+ WXFace *previousFace = 0;
+ WOEdge * woebegin;
+ real tend;
+ if(iFaceLayer.order){
+ woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
+ tend = iFaceLayer.fl->getSmoothEdge()->ta();
+ }else{
+ woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
+ tend = iFaceLayer.fl->getSmoothEdge()->tb();
+ }
+
+ // special case of EDGE_VERTEX config:
+ if((tend == 0.0) || (tend == 1.0)){
+ WVertex *previousVertex;
+ if(tend == 0.0)
+ previousVertex = woebegin->GetaVertex();
+ else
+ previousVertex = woebegin->GetbVertex();
+ if(previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
+ return OWXFaceLayer(0,true);
+ bool found = false;
+ WVertex::face_iterator f=previousVertex->faces_begin();
+ WVertex::face_iterator fend=previousVertex->faces_end();
+ while((!found) && (f!=fend)){
+ previousFace = dynamic_cast<WXFace*>(*f);
+ if((0 != previousFace) && (previousFace!=iFaceLayer.fl->getFace())){
+ vector<WXFaceLayer*> sameNatureLayers;
+ previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if(sameNatureLayers.size() == 1) {// don't know
+ // maybe should test whether this face has
+ // also a vertex_edge configuration
+ WXFaceLayer * winner = sameNatureLayers[0];
+ if(woebegin == winner->getSmoothEdge()->woeb()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ ++f;
+ }
+ }else{
+ previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
+ if(0 == previousFace)
+ return OWXFaceLayer(0,true);
+
+ // if the next face layer has either no smooth edge or
+ // no smooth edge of same nature, no next face
+ if(!previousFace->hasSmoothEdges())
+ return OWXFaceLayer(0,true);
+ vector<WXFaceLayer*> sameNatureLayers;
+ previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
+ if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face
+ return OWXFaceLayer(0,true);
+ else{
+ WXFaceLayer * winner = sameNatureLayers[0];
+ if(woebegin == winner->getSmoothEdge()->woeb()->twin())
+ return OWXFaceLayer(winner,true);
+ else
+ return OWXFaceLayer(winner,false);
+ }
+ }
+ return OWXFaceLayer(0,true);
+}
+
+FEdge * ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl){
+ SVertex *va, *vb;
+ FEdgeSmooth *fe;
+ // retrieve exact silhouette data
+ WXSmoothEdge *se = ifl.fl->getSmoothEdge();
+
+ Vec3r normal;
+ // Make the 2 Svertices
+ if(feprevious == 0){ // that means that we don't have any vertex already built for that face
+ real ta = se->ta();
+ Vec3r A1(se->woea()->GetaVertex()->GetVertex());
+ Vec3r A2(se->woea()->GetbVertex()->GetVertex());
+ Vec3r A(A1+ta*(A2-A1));
+
+ va = MakeSVertex(A);
+ // Set normal:
+ Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(se->woea()->GetaVertex()));
+ Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(se->woea()->GetbVertex()));
+ Vec3r na((1 - ta) * NA1 + ta * NA2);
+ na.normalize();
+ va->AddNormal(na);
+ normal = na;
+
+ // Set CurvatureInfo
+ CurvatureInfo* curvature_info_a = new CurvatureInfo(*(dynamic_cast<WXVertex*>(se->woea()->GetaVertex())->curvatures()),
+ *(dynamic_cast<WXVertex*>(se->woea()->GetbVertex())->curvatures()),
+ ta);
+ va->setCurvatureInfo(curvature_info_a);
+ }
+ else
+ va = feprevious->vertexB();
+
+ real tb = se->tb();
+ Vec3r B1(se->woeb()->GetaVertex()->GetVertex());
+ Vec3r B2(se->woeb()->GetbVertex()->GetVertex());
+ Vec3r B(B1+tb*(B2-B1));
+
+ vb = MakeSVertex(B);
+ // Set normal:
+ Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(se->woeb()->GetaVertex()));
+ Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(se->woeb()->GetbVertex()));
+ Vec3r nb((1 - tb) * NB1 + tb * NB2);
+ nb.normalize();
+ normal += nb;
+ vb->AddNormal(nb);
+
+ // Set CurvatureInfo
+ CurvatureInfo* curvature_info_b = new CurvatureInfo(*(dynamic_cast<WXVertex*>(se->woeb()->GetaVertex())->curvatures()),
+ *(dynamic_cast<WXVertex*>(se->woeb()->GetbVertex())->curvatures()),
+ tb);
+ vb->setCurvatureInfo(curvature_info_b);
+
+ // if the order is false we must swap va and vb
+ if(!ifl.order){
+ SVertex *tmp = va;
+ va = vb;
+ vb = tmp;
+ }
+
+ // Creates the corresponding feature edge
+ fe = new FEdgeSmooth(va, vb);
+ fe->SetNature(ifl.fl->nature());
+ fe->SetId(_currentFId);
+ fe->SetMaterialIndex(ifl.fl->getFace()->materialIndex());
+ fe->SetFace(ifl.fl->getFace());
+ fe->SetNormal(normal);
+ fe->SetPreviousEdge(feprevious);
+ if(feprevious)
+ feprevious->SetNextEdge(fe);
+ _pCurrentSShape->AddEdge(fe);
+ va->AddFEdge(fe);
+ vb->AddFEdge(fe);
+
+ ++_currentFId;
+ ifl.fl->userdata = fe;
+ return fe;
+}
+
+bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer){
+ if(0 == iFaceLayer)
+ return true;
+ if(iFaceLayer->userdata == 0)
+ return false;
+ return true;
+}
+
+OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge& iEdge){
+ if(Nature::NO_FEATURE == iEdge.e->nature())
+ return OWXEdge(0, true);
+
+ WVertex *v;
+ if(true == iEdge.order)
+ v = iEdge.e->GetbVertex();
+ else
+ v = iEdge.e->GetaVertex();
+
+ if(((WXVertex*)v)->isFeature())
+ return 0;
+
+
+ vector<WEdge*>& vEdges = (v)->GetEdges();
+ for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end();
+ ve!=veend;
+ ve++){
+ WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
+ if(wxe == iEdge.e)
+ continue; // same edge as the one processed
+
+ if(wxe->nature() != iEdge.e->nature())
+ continue;
+
+ if(wxe->GetaVertex() == v){
+ // That means that the face necesarily lies on the edge left.
+ // So the vertex order is OK.
+ return OWXEdge(wxe, true);
+ }else{
+ // That means that the face necesarily lies on the edge left.
+ // So the vertex order is OK.
+ return OWXEdge(wxe, false);
+ }
+ }
+ // we did not find:
+ return OWXEdge(0, true);
+}
+
+OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge& iEdge){
+ if(Nature::NO_FEATURE == iEdge.e->nature())
+ return OWXEdge(0, true);
+
+ WVertex *v;
+ if(true == iEdge.order)
+ v = iEdge.e->GetaVertex();
+ else
+ v = iEdge.e->GetbVertex();
+
+ if(((WXVertex*)v)->isFeature())
+ return 0;
+
+
+ vector<WEdge*>& vEdges = (v)->GetEdges();
+ for(vector<WEdge*>::iterator ve=vEdges.begin(),veend=vEdges.end();
+ ve!=veend;
+ ve++){
+ WXEdge *wxe = dynamic_cast<WXEdge*>(*ve);
+ if(wxe == iEdge.e)
+ continue; // same edge as the one processed
+
+ if(wxe->nature() != iEdge.e->nature())
+ continue;
+
+ if(wxe->GetbVertex() == v){
+ return OWXEdge(wxe, true);
+ }else{
+ return OWXEdge(wxe, false);
+ }
+ }
+ // we did not find:
+ return OWXEdge(0, true);
+}
+
+FEdge * ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe){
+ SVertex *va, *vb;
+ FEdgeSharp *fe;
+ WXVertex *wxVA, *wxVB;
+ if(iwe.order){
+ wxVA = (WXVertex*)iwe.e->GetaVertex();
+ wxVB = (WXVertex*)iwe.e->GetbVertex();
+ }else{
+ wxVA = (WXVertex*)iwe.e->GetbVertex();
+ wxVB = (WXVertex*)iwe.e->GetaVertex();
+ }
+ // Make the 2 SVertex
+ va = MakeSVertex(wxVA->GetVertex());
+ vb = MakeSVertex(wxVB->GetVertex());
+
+ // get the faces normals and the material indices
+ Vec3r normalA, normalB;
+ unsigned matA(0), matB(0);
+ if(iwe.order){
+ normalB = (iwe.e->GetbFace()->GetNormal());
+ matB = (iwe.e->GetbFace()->materialIndex());
+ if(!(iwe.e->nature() & Nature::BORDER)) {
+ normalA = (iwe.e->GetaFace()->GetNormal());
+ matA = (iwe.e->GetaFace()->materialIndex());
+ }
+ }else{
+ normalA = (iwe.e->GetbFace()->GetNormal());
+ matA = (iwe.e->GetbFace()->materialIndex());
+ if(!(iwe.e->nature() & Nature::BORDER)) {
+ normalB = (iwe.e->GetaFace()->GetNormal());
+ matB = (iwe.e->GetaFace()->materialIndex());
+ }
+ }
+ // Creates the corresponding feature edge
+ // Creates the corresponding feature edge
+ fe = new FEdgeSharp(va, vb);
+ fe->SetNature(iwe.e->nature());
+ fe->SetId(_currentFId);
+ fe->SetaMaterialIndex(matA);
+ fe->SetbMaterialIndex(matB);
+ fe->SetNormalA(normalA);
+ fe->SetNormalB(normalB);
+ fe->SetPreviousEdge(feprevious);
+ if(feprevious)
+ feprevious->SetNextEdge(fe);
+ _pCurrentSShape->AddEdge(fe);
+ va->AddFEdge(fe);
+ vb->AddFEdge(fe);
+ //Add normals:
+ va->AddNormal(normalA);
+ va->AddNormal(normalB);
+ vb->AddNormal(normalA);
+ vb->AddNormal(normalB);
+
+ ++_currentFId;
+ iwe.e->userdata = fe;
+ return fe;
+}
+
+bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge){
+ if(0 == iEdge)
+ return true;
+ if(iEdge->userdata == 0)
+ return false;
+ return true;
+}
+
+SVertex * ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint){
+ SVertex *va;
+ // Check whether the vertices are already in the table:
+ // fisrt vertex
+ // -------------
+ SVertexMap::const_iterator found = _SVertexMap.find(iPoint);
+ if (found != _SVertexMap.end()) {
+ va = (*found).second;
+ }else{
+ va = new SVertex(iPoint, _currentSVertexId);
+ SilhouetteGeomEngine::ProjectSilhouette(va);
+ ++_currentSVertexId;
+ // Add the svertex to the SShape svertex list:
+ _pCurrentSShape->AddNewVertex(va);
+ // Add the svertex in the table using its id:
+ _SVertexMap[iPoint] = va;
+ }
+ return va;
+}
+
+ViewVertex * ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex){
+ ViewVertex *vva = iSVertex->viewvertex();
+ if(vva != 0)
+ return vva;
+ vva = new NonTVertex(iSVertex);
+ // Add the view vertex to the ViewShape svertex list:
+ _pCurrentVShape->AddVertex(vva);
+ return vva;
+}
+
diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
new file mode 100755
index 00000000000..9e2837b49a7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
@@ -0,0 +1,214 @@
+//
+// Filename : ViewEdgeXBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build view edges and the underlying chains
+// of feature edges...
+// Date of creation : 27/10/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWEDGEXBUILDER_H
+# define VIEWEDGEXBUILDER_H
+
+# include <map>
+# include <utility>
+# include <vector>
+
+# if defined(__GNUC__) && (__GNUC__ >= 3)
+//hash_map is not part of the C++ standard anymore; hash_map.h has been kept though for backward compatibility
+# include <hash_map.h>
+# else
+# include <hash_map>
+# endif
+
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "Interface1D.h"
+
+using namespace Geometry;
+using namespace std;
+
+class SVertex;
+/*! Defines a hash table used for searching the SVertex */
+struct SVertexHasher {
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3r& p) const {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+};
+
+// Key_compare predicate for hash_map. In particular, return false if equal.
+struct epsilonEquals{
+ bool operator()(const Vec3r& v1, const Vec3r& v2) const{
+ real norm = (v1-v2).norm();
+ return (norm<1e-06);
+ }
+};
+
+
+// typedef hash_map<Vec3r, SVertex*, SVertexHasher, epsilonEquals> SVertexMap;
+typedef map<Vec3r , SVertex*> SVertexMap;
+
+class WXFaceLayer;
+/*! class to describe an oriented smooth edge */
+class OWXFaceLayer{
+public:
+ WXFaceLayer * fl;
+ bool order;
+
+ OWXFaceLayer() {fl=0;order=true;}
+ OWXFaceLayer(WXFaceLayer *ifl, bool iOrder=true){fl = ifl;order=iOrder;}
+ OWXFaceLayer& operator=(const OWXFaceLayer& iBrother){
+ fl = iBrother.fl;
+ order = iBrother.order;
+ return *this;
+ }
+ bool operator==(const OWXFaceLayer& b){
+ return ((fl == b.fl) && (order == b.order));
+ }
+ bool operator!=(const OWXFaceLayer& b){
+ return !(*this==b);
+ }
+};
+
+class WXEdge;
+/*! class to describe an oriented sharp edge */
+class OWXEdge{
+public:
+ WXEdge * e;
+ bool order;
+
+ OWXEdge() {e=0;order=true;}
+ OWXEdge(WXEdge *ie, bool iOrder=true){e = ie;order=iOrder;}
+ OWXEdge& operator=(const OWXEdge& iBrother){
+ e = iBrother.e;
+ order = iBrother.order;
+ return *this;
+ }
+ bool operator==(const OWXEdge& b){
+ return ((e == b.e) && (order == b.order));
+ }
+ bool operator!=(const OWXEdge& b){
+ return !(*this==b);
+ }
+};
+
+class WOEdge;
+class WXEdge;
+class WXShape;
+class SVertex;
+class FEdge;
+class ViewVertex;
+class ViewEdge;
+class ViewShape;
+class LIB_VIEW_MAP_EXPORT ViewEdgeXBuilder
+{
+protected:
+ int _currentViewId; // Id for view edges
+ int _currentFId; // Id for FEdges
+ int _currentSVertexId; // Id for SVertex
+public:
+
+ inline ViewEdgeXBuilder()
+ {_currentViewId = 1;_currentFId=0;_currentSVertexId=0;}
+ virtual ~ViewEdgeXBuilder(){}
+
+ /*! Builds a view shape from a WXShape in which the feature edges
+ * are flagged
+ * Builds chains of feature edges (so ViewEdges) from a WXShape
+ * iWShape
+ * The Winged Edge structure in which all silhouette edges
+ * and vertices are flagged.
+ * oViewShape
+ * The Silhouette Shape in which the chains must be added.
+ * ioVEdges
+ * The list of new ViewEdges.
+ * ioVVertices
+ * THe new ViewVertices
+ * ioFEdges
+ * A list in which all new FEdges are added
+ * ioSVertices
+ * A list of SVertex where all created SVertex are added.
+ */
+ virtual void BuildViewEdges(WXShape *iWShape, ViewShape *oVShape,
+ std::vector<ViewEdge*>& ioVEdges,
+ std::vector<ViewVertex*>& ioVVertices,
+ std::vector<FEdge*>& ioFEdges,
+ std::vector<SVertex*>& ioSVertices) ;
+
+ /*! Builds a smooth view edge, starting the face iFace.*/
+ ViewEdge * BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer);
+
+ /*! Makes a sharp viewedge
+ */
+ ViewEdge * BuildSharpViewEdge(const OWXEdge& iWEdge) ;
+
+
+public:
+ /*! accessors */
+ inline int currentViewId() const { return _currentViewId; }
+ inline int currentFId() const { return _currentFId; }
+ inline int currentSVertexId() const { return _currentSVertexId; }
+ /*! modifiers */
+ inline void SetCurrentViewId(int id) { _currentViewId = id; }
+ inline void SetCurrentFId(int id) { _currentFId = id; }
+ inline void SetCurrentSVertexId(int id) { _currentSVertexId = id; }
+
+protected:
+ /*! Init the view edges building */
+ virtual void Init(ViewShape *oVShape) ;
+
+ // SMOOTH //
+ /*! checks whether a face has already been processed or not */
+ bool stopSmoothViewEdge(WXFaceLayer *iFaceLayer);
+ OWXFaceLayer FindNextFaceLayer(const OWXFaceLayer& iFaceLayer);
+ OWXFaceLayer FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer);
+ FEdge * BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl);
+
+ // SHARP //
+ /*! checks whether a WEdge has already been processed or not */
+ bool stopSharpViewEdge(WXEdge *iFace);
+ OWXEdge FindNextWEdge(const OWXEdge& iEdge);
+ OWXEdge FindPreviousWEdge(const OWXEdge& iEdge);
+ FEdge * BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe);
+
+ // GENERAL //
+ /*! Instanciate a SVertex if it hasn't been already created */
+ SVertex * MakeSVertex(Vec3r& iPoint);
+ /*! instanciate a ViewVertex from a SVertex, if it doesn't exist yet */
+ ViewVertex * MakeViewVertex(SVertex *iSVertex);
+
+ //tmp values
+ // IdHashTable _hashtable;
+ // VVIdHashTable _multivertexHashTable;
+ SVertexMap _SVertexMap;
+ SShape *_pCurrentSShape;
+ ViewShape * _pCurrentVShape;
+};
+
+#endif
+
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp
new file mode 100755
index 00000000000..9a2d262b703
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp
@@ -0,0 +1,703 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMap.h"
+#include "../geometry/GeomUtils.h"
+#include <float.h>
+#include "ViewMapIterators.h"
+#include "ViewMapAdvancedIterators.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+ViewMap * ViewMap::_pInstance = 0;
+
+ViewMap::~ViewMap()
+{
+ // The view vertices must be deleted here as some of them
+ // are shared between two shapes:
+ for(vector<ViewVertex*>::iterator vv=_VVertices.begin(), vvend=_VVertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ delete (*vv);
+ }
+ _VVertices.clear();
+
+ for(vector<ViewShape*>::iterator vs=_VShapes.begin(),vsend=_VShapes.end();
+ vs!=vsend;
+ vs++)
+ {
+ delete (*vs);
+ }
+ _VShapes.clear();
+
+ _FEdges.clear();
+ _SVertices.clear();
+ _VEdges.clear();
+}
+
+ViewShape * ViewMap::viewShape(unsigned id)
+{
+ int index = _shapeIdToIndex[id];
+ return _VShapes[ index ];
+}
+void ViewMap::AddViewShape(ViewShape *iVShape) {
+ _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size();
+ _VShapes.push_back(iVShape);
+}
+const FEdge * ViewMap::GetClosestFEdge(real x, real y) const
+{
+ // find the closest of this candidates:
+ real minDist = DBL_MAX;
+ FEdge * winner = 0;
+ for(fedges_container::const_iterator fe=_FEdges.begin(),feend=_FEdges.end();
+ fe!=feend;
+ fe++)
+ {
+ Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
+ Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
+ real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x,y),A, B);
+ if(dist < minDist)
+ {
+ minDist = dist;
+ winner = (*fe);
+ }
+
+ }
+ if(winner==0)
+ return 0;
+
+ return winner;
+}
+
+const ViewEdge * ViewMap::GetClosestViewEdge(real x, real y) const
+{
+ // find the closest of this candidates:
+ real minDist = DBL_MAX;
+ FEdge * winner = 0;
+ for(fedges_container::const_iterator fe=_FEdges.begin(),feend=_FEdges.end();
+ fe!=feend;
+ fe++)
+ {
+ Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
+ Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
+ real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x,y),A, B);
+ if(dist < minDist)
+ {
+ minDist = dist;
+ winner = (*fe);
+ }
+
+ }
+ if(winner==0)
+ return 0;
+
+ return winner->viewedge();
+}
+
+
+TVertex* ViewMap::CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA,
+ const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB,
+ const Id& id)
+{
+ ViewShape *vshapeA = iFEdgeA->viewedge()->viewShape();
+ SShape *shapeA = iFEdgeA->shape();
+ ViewShape *vshapeB = iFEdgeB->viewedge()->viewShape();
+ SShape *shapeB = iFEdgeB->shape();
+
+ SVertex * Ia = shapeA->CreateSVertex(iA3D, iA2D, iFEdgeA->vertexA()->getId());
+ SVertex * Ib = shapeB->CreateSVertex(iB3D, iB2D, iFEdgeB->vertexA()->getId());
+
+ // depending on which of these 2 svertices is the nearest from the
+ // viewpoint, we're going to build the TVertex by giving them in
+ // an order or another (the first one must be the nearest)
+ real dista = Ia->point2D()[2];
+ real distb = Ib->point2D()[2];
+
+ TVertex * tvertex;
+ if(dista < distb)
+ tvertex = new TVertex(Ia, Ib);
+ else
+ tvertex = new TVertex(Ib,Ia);
+
+ tvertex->SetId(id);
+
+ // add these vertices to the view map
+ AddViewVertex(tvertex);
+ AddSVertex(Ia);
+ AddSVertex(Ib);
+
+ // and this T Vertex to the view shapes:
+ vshapeA->AddVertex(tvertex);
+ vshapeB->AddVertex(tvertex);
+
+ return tvertex;
+}
+
+ViewVertex * ViewMap::InsertViewVertex(SVertex *iVertex,
+ vector<ViewEdge*>& newViewEdges){
+ NonTVertex *vva = dynamic_cast<NonTVertex*>(iVertex->viewvertex());
+ if(vva != 0)
+ return vva;
+ // beacuse it is not already a ViewVertex, this SVertex must have only
+ // 2 FEdges. The incoming one still belongs to ioEdge, the outgoing one
+ // now belongs to newVEdge
+ const vector<FEdge*>& fedges = iVertex->fedges();
+ if(fedges.size()!=2){
+ cerr << "ViewMap warning: Can't split the ViewEdge" << endl;
+ return 0;
+ }
+ FEdge * fend(0), * fbegin(0);
+ for(vector<FEdge*>::const_iterator fe=fedges.begin(), feend=fedges.end();
+ fe!=feend;
+ ++fe){
+ if((*fe)->vertexB() == iVertex){
+ fend = (*fe);
+ }
+ if((*fe)->vertexA() == iVertex){
+ fbegin = (*fe);
+ }
+ if((fbegin!=0) && (fend!=0))
+ break;
+ }
+ ViewEdge *ioEdge = fbegin->viewedge();
+ ViewShape * vshape = ioEdge->viewShape();
+ vva = new NonTVertex(iVertex);
+ // if the ViewEdge is a closed loop, we don't create
+ // a new VEdge
+ if(ioEdge->A() == 0){
+ // closed loop
+ ioEdge->SetA(vva);
+ ioEdge->SetB(vva);
+ // update sshape
+ vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeA());
+ vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeB());
+
+ ioEdge->SetFEdgeA(fbegin);
+ ioEdge->SetFEdgeB(fend);
+
+ // Update FEdges
+ fend->SetNextEdge(0);
+ fbegin->SetPreviousEdge(0);
+
+ // update new View Vertex:
+ vva->AddOutgoingViewEdge(ioEdge);
+ vva->AddIncomingViewEdge(ioEdge);
+
+ vshape->sshape()->AddChain(ioEdge->fedgeA());
+ vshape->sshape()->AddChain(ioEdge->fedgeB());
+ }else{
+ // Create new ViewEdge
+ ViewEdge * newVEdge = new ViewEdge(vva, ioEdge->B(), fbegin, ioEdge->fedgeB(), vshape);
+ newVEdge->SetId(Id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond()+1));
+ newVEdge->SetNature(ioEdge->getNature());
+ //newVEdge->UpdateFEdges(); // done in the ViewEdge constructor
+ // Update old ViewEdge
+ ioEdge->SetB(vva);
+ ioEdge->SetFEdgeB(fend);
+
+ // Update FEdges
+ fend->SetNextEdge(0);
+ fbegin->SetPreviousEdge(0);
+
+ // update new View Vertex:
+ vva->AddOutgoingViewEdge(newVEdge);
+ vva->AddIncomingViewEdge(ioEdge);
+ // update ViewShape
+ //vshape->AddEdge(newVEdge);
+ // update SShape
+ vshape->sshape()->AddChain(fbegin);
+ // update ViewMap
+ //_VEdges.push_back(newVEdge);
+ newViewEdges.push_back(newVEdge);
+ }
+
+ // update ViewShape
+ vshape->AddVertex(vva);
+
+ // update ViewMap
+ _VVertices.push_back(vva);
+
+ return vva;
+}
+
+//FEdge * ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector<ViewEdge*>& oNewVEdges){
+// SShape * sshape = ioEdge->shape();
+// FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex);
+// AddFEdge(newFEdge);
+// InsertViewVertex(ioVertex, oNewVEdges);
+// return newFEdge;
+//}
+
+ /**********************************/
+ /* */
+ /* */
+ /* TVertex */
+ /* */
+ /* */
+ /**********************************/
+
+// is dve1 before dve2 ? (does it have a smaller angle ?)
+bool ViewEdgeComp(ViewVertex::directedViewEdge& dve1, ViewVertex::directedViewEdge& dve2){
+ FEdge *fe1;
+ if(dve1.second)
+ fe1 = dve1.first->fedgeB();
+ else
+ fe1 = dve1.first->fedgeA();
+ FEdge *fe2;
+ if(dve2.second)
+ fe2 = dve2.first->fedgeB();
+ else
+ fe2 = dve2.first->fedgeA();
+
+ Vec3r V1 = fe1->orientation2d();
+ Vec2r v1(V1.x(), V1.y());v1.normalize();
+ Vec3r V2 = fe2->orientation2d();
+ Vec2r v2(V2.x(), V2.y());v2.normalize();
+ if(v1.y() > 0){
+ if(v2.y() < 0)
+ return true;
+ else
+ return (v1.x() > v2.x());
+ }else{
+ if(v2.y() > 0)
+ return false;
+ else
+ return (v1.x() < v2.x());
+ }
+ return false;
+}
+void TVertex::SetFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming) {
+ if (!iFrontEdgeA) {
+ cerr << "Warning: null pointer passed as argument of TVertex::SetFrontEdgeA()" << endl;
+ return;
+ }
+ _FrontEdgeA = directedViewEdge(iFrontEdgeA, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _FrontEdgeA)){
+ ++dve;
+ }
+ _sortedEdges.insert( dve, &_FrontEdgeA);
+ }
+ else
+ _sortedEdges.push_back(&_FrontEdgeA);
+}
+void TVertex::SetFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming) {
+ if (!iFrontEdgeB) {
+ cerr << "Warning: null pointer passed as argument of TVertex::SetFrontEdgeB()" << endl;
+ return;
+ }
+ _FrontEdgeB = directedViewEdge(iFrontEdgeB, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _FrontEdgeB)){
+ ++dve;
+ }
+ _sortedEdges.insert(dve, &_FrontEdgeB);
+ }
+ else
+ _sortedEdges.push_back(&_FrontEdgeB);
+}
+void TVertex::SetBackEdgeA(ViewEdge *iBackEdgeA, bool incoming) {
+ if (!iBackEdgeA) {
+ cerr << "Warning: null pointer passed as argument of TVertex::SetBackEdgeA()" << endl;
+ return;
+ }
+ _BackEdgeA = directedViewEdge(iBackEdgeA, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeA)){
+ ++dve;
+ }
+ _sortedEdges.insert(dve, &_BackEdgeA);
+ }
+ else
+ _sortedEdges.push_back(&_BackEdgeA);
+}
+void TVertex::SetBackEdgeB(ViewEdge *iBackEdgeB, bool incoming) {
+ if (!iBackEdgeB) {
+ cerr << "Warning: null pointer passed as argument of TVertex::SetBackEdgeB()" << endl;
+ return;
+ }
+ _BackEdgeB = directedViewEdge(iBackEdgeB, incoming);
+ if(!_sortedEdges.empty()){
+ edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeB)){
+ ++dve;
+ }
+ _sortedEdges.insert(dve, &_BackEdgeB);
+ }
+ else
+ _sortedEdges.push_back(&_BackEdgeB);
+}
+void TVertex::Replace(ViewEdge *iOld, ViewEdge *iNew)
+{
+ // theoritically, we only replace edges for which this
+ // view vertex is the B vertex
+ if((iOld == _FrontEdgeA.first) && (_FrontEdgeA.first->B() == this))
+ {
+ _FrontEdgeA.first = iNew;
+ return;
+ }
+ if((iOld == _FrontEdgeB.first) && (_FrontEdgeB.first->B() == this))
+ {
+ _FrontEdgeB.first = iNew;
+ return;
+ }
+ if((iOld == _BackEdgeA.first) && (_BackEdgeA.first->B() == this))
+ {
+ _BackEdgeA.first = iNew;
+ return;
+ }
+ if((iOld == _BackEdgeB.first) && (_BackEdgeB.first->B() == this))
+ {
+ _BackEdgeB.first = iNew;
+ return;
+ }
+}
+
+/*! iterators access */
+ViewVertex::edge_iterator TVertex::edges_begin()
+{
+ //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ViewVertex::const_edge_iterator TVertex::edges_begin() const
+{
+ //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ViewVertex::edge_iterator TVertex::edges_end()
+{
+ //return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0,true));
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+ViewVertex::const_edge_iterator TVertex::edges_end() const
+{
+ //return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, directedViewEdge(0, true));
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+ViewVertex::edge_iterator TVertex::edges_iterator(ViewEdge *iEdge)
+{
+ for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((*it)->first == iEdge)
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+
+ // directedViewEdge dEdge;
+ // if(_FrontEdgeA.first == iEdge)
+ // dEdge = _FrontEdgeA;
+ // else if(_FrontEdgeB.first == iEdge)
+ // dEdge = _FrontEdgeB;
+ // else if(_BackEdgeA.first == iEdge)
+ // dEdge = _BackEdgeA;
+ // else if(_BackEdgeB.first == iEdge)
+ // dEdge = _BackEdgeB;
+ // return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
+}
+ViewVertex::const_edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) const
+{
+ for(edge_pointers_container::const_iterator it=_sortedEdges.begin(), itend=_sortedEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((*it)->first == iEdge)
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+
+ // directedViewEdge dEdge;
+ // if(_FrontEdgeA.first == iEdge)
+ // dEdge = _FrontEdgeA;
+ // else if(_FrontEdgeB.first == iEdge)
+ // dEdge = _FrontEdgeB;
+ // else if(_BackEdgeA.first == iEdge)
+ // dEdge = _BackEdgeA;
+ // else if(_BackEdgeB.first == iEdge)
+ // dEdge = _BackEdgeB;
+ // return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
+}
+
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
+}
+ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge) {
+ for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((*it)->first == iEdge)
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), it);
+ }
+ return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
+}
+ /**********************************/
+ /* */
+ /* */
+ /* NonTVertex */
+ /* */
+ /* */
+ /**********************************/
+
+void NonTVertex::AddOutgoingViewEdge(ViewEdge * iVEdge){
+ // let's keep the viewedges ordered in CCW order
+ // in the 2D image plan
+ directedViewEdge idve(iVEdge, false);
+ if(!_ViewEdges.empty()){
+ edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(*dve, idve)){
+ ++dve;
+ }
+ _ViewEdges.insert(dve, idve);
+ }
+ else
+ _ViewEdges.push_back(idve);
+}
+
+void NonTVertex::AddIncomingViewEdge(ViewEdge * iVEdge){
+ // let's keep the viewedges ordered in CCW order
+ // in the 2D image plan
+ directedViewEdge idve(iVEdge, true);
+ if(!_ViewEdges.empty()){
+ edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
+ while((dve!=dveend) && ViewEdgeComp(*dve, idve)){
+ ++dve;
+ }
+ _ViewEdges.insert(dve, idve);
+ }
+ else
+ _ViewEdges.push_back(idve);
+}
+
+/*! iterators access */
+ViewVertex::edge_iterator NonTVertex::edges_begin()
+{
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertex::const_edge_iterator NonTVertex::edges_begin() const
+{
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertex::edge_iterator NonTVertex::edges_end()
+{
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+ViewVertex::const_edge_iterator NonTVertex::edges_end() const
+{
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+ViewVertex::edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge)
+{
+ for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((it)->first == iEdge)
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertex::const_edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge) const
+{
+ for(edges_container::const_iterator it=_ViewEdges.begin(), itend=_ViewEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((it)->first == iEdge)
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesBegin() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd() {
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
+}
+ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge) {
+ for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end();
+ it!=itend;
+ it++)
+ {
+ if((it)->first == iEdge)
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), it);
+ }
+ return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
+}
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+real ViewEdge::getLength2D() const
+{
+ float length = 0.f;
+ ViewEdge::const_fedge_iterator itlast = fedge_iterator_last();
+ ViewEdge::const_fedge_iterator it = fedge_iterator_begin(), itend=fedge_iterator_end();
+ Vec2r seg;
+ do{
+ seg = Vec2r((*it)->orientation2d()[0], (*it)->orientation2d()[1]);
+ length += seg.norm();
+ ++it;
+ }while((it!=itend) && (it!=itlast));
+ return length;
+}
+
+
+//! view edge iterator
+ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator() {return edge_iterator(this);}
+ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const {return const_edge_iterator((ViewEdge*)this);}
+//! feature edge iterator
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin() {return fedge_iterator(this->_FEdgeA, this->_FEdgeB);}
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const {return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB);}
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last() {return fedge_iterator(this->_FEdgeB, this->_FEdgeB);}
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const {return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB);}
+ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end() {return fedge_iterator(0, this->_FEdgeB);}
+ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const {return const_fedge_iterator(0, this->_FEdgeB);}
+//! embedding vertex iterator
+ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const {return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);}
+ViewEdge::vertex_iterator ViewEdge::vertices_begin() {return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA);}
+ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const {return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);}
+ViewEdge::vertex_iterator ViewEdge::vertices_last() {return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);}
+ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const {return const_vertex_iterator(0, _FEdgeB, 0);}
+ViewEdge::vertex_iterator ViewEdge::vertices_end() {return vertex_iterator(0, _FEdgeB, 0);}
+
+
+Interface0DIterator ViewEdge::verticesBegin() {
+ Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(this->_FEdgeA->vertexA(), this->_FEdgeA->vertexA(), 0, _FEdgeA, 0.f));
+ return ret;
+}
+
+Interface0DIterator ViewEdge::verticesEnd() {
+ Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(0, this->_FEdgeA->vertexA(), _FEdgeB, 0, getLength2D()));
+ return ret;
+}
+
+Interface0DIterator ViewEdge::pointsBegin(float t) {
+ return verticesBegin();
+}
+
+Interface0DIterator ViewEdge::pointsEnd(float t) {
+ return verticesEnd();
+}
+
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+ViewShape::~ViewShape()
+{
+ _Vertices.clear();
+
+ if(!(_Edges.empty()))
+ {
+ for(vector<ViewEdge*>::iterator e=_Edges.begin(), eend=_Edges.end();
+ e!=eend;
+ e++)
+ {
+ delete (*e);
+ }
+ _Edges.clear();
+ }
+
+ if(0 != _SShape)
+ {
+ delete _SShape;
+ _SShape = 0;
+ }
+}
+
+void ViewShape::RemoveEdge(ViewEdge * iViewEdge)
+{
+ FEdge * fedge = iViewEdge->fedgeA();
+ for(vector<ViewEdge*>::iterator ve=_Edges.begin(),veend=_Edges.end();
+ ve!=veend;
+ ve++)
+ {
+ if(iViewEdge == (*ve))
+ {
+ _Edges.erase(ve);
+ _SShape->RemoveEdge(fedge);
+ break;
+ }
+ }
+}
+
+void ViewShape::RemoveVertex(ViewVertex * iViewVertex)
+{
+ for(vector<ViewVertex*>::iterator vv=_Vertices.begin(), vvend=_Vertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ if(iViewVertex == (*vv))
+ {
+ _Vertices.erase(vv);
+ break;
+ }
+ }
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+void ViewEdge::UpdateFEdges()
+{
+ FEdge *currentEdge = _FEdgeA;
+ do
+ {
+ currentEdge->SetViewEdge(this);
+ currentEdge = currentEdge->nextEdge();
+ }while((currentEdge != NULL) && (currentEdge!= _FEdgeB));
+ // last one
+ _FEdgeB->SetViewEdge(this);
+
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h
new file mode 100755
index 00000000000..bdbb140e130
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -0,0 +1,1487 @@
+//
+// Filename : ViewMap.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a View Map (ViewVertex, ViewEdge, etc.)
+// Date of creation : 03/09/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAP_H
+# define VIEWMAP_H
+
+# include "../system/BaseIterator.h"
+# include "../system/FreestyleConfig.h"
+# include "../geometry/GeomUtils.h"
+# include "Interface0D.h"
+# include "Interface1D.h"
+# include "Silhouette.h" // defines the embedding
+# include <map>
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+
+/* Density
+ Mean area depth value
+ distance to a point
+ */
+
+class ViewVertex;
+class ViewEdge;
+class ViewShape;
+class TVertex;
+
+/*! Class defining the ViewMap.*/
+class LIB_VIEW_MAP_EXPORT ViewMap
+{
+public:
+
+ typedef vector<ViewEdge*> viewedges_container;
+ typedef vector<ViewVertex*> viewvertices_container;
+ typedef vector<ViewShape*> viewshapes_container;
+ typedef vector<SVertex*> svertices_container;
+ typedef vector<FEdge*> fedges_container;
+ typedef map<int,int> id_to_index_map;
+
+private:
+
+ static ViewMap *_pInstance;
+ viewshapes_container _VShapes; // view shapes
+ viewedges_container _VEdges; // view edges
+ viewvertices_container _VVertices; // view vertices
+ fedges_container _FEdges; // feature edges (embedded edges)
+ svertices_container _SVertices; // embedded vertices
+ BBox<Vec3r> _scene3DBBox;
+ id_to_index_map _shapeIdToIndex; // Mapping between the WShape or VShape id to the VShape index in the
+ // _VShapes vector. Used in the method viewShape(int id) to access a shape from its id.
+
+public:
+
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void* userdata;
+
+ /*! Default constructor. */
+ ViewMap() {
+ _pInstance = this;
+ userdata = 0;
+ }
+ /*! Destructor. */
+ virtual ~ViewMap();
+
+ /*! Gets the viewedge the nearest to the
+ * 2D position specified as argument
+ */
+ const ViewEdge * GetClosestViewEdge(real x, real y) const ;
+
+ /*! Gets the Fedge the nearest to the
+ * 2D position specified as argument
+ */
+ const FEdge * GetClosestFEdge(real x, real y) const ;
+
+ /* accessors */
+ /*! The ViewMap is a singleton class. This static method
+ * returns the instance of the ViewMap.
+ */
+ static inline ViewMap * getInstance() {return _pInstance;}
+ /* Returns the list of ViewShapes of the scene. */
+ inline viewshapes_container& ViewShapes() {return _VShapes;}
+ /* Returns the list of ViewEdges of the scene. */
+ inline viewedges_container& ViewEdges() {return _VEdges;}
+ /* Returns the list of ViewVertices of the scene. */
+ inline viewvertices_container& ViewVertices() {return _VVertices;}
+ /* Returns the list of FEdges of the scene. */
+ inline fedges_container& FEdges() {return _FEdges;}
+ /* Returns the list of SVertices of the scene. */
+ inline svertices_container& SVertices() {return _SVertices;}
+ /* Returns an iterator pointing onto the first ViewEdge of the list. */
+ inline viewedges_container::iterator viewedges_begin() {return _VEdges.begin();}
+ inline viewedges_container::iterator viewedges_end() {return _VEdges.end();}
+ inline int viewedges_size() {return _VEdges.size();}
+ ViewShape * viewShape(unsigned index);
+ id_to_index_map& shapeIdToIndexMap() {return _shapeIdToIndex;}
+
+ /*! Returns the scene 3D bounding box. */
+ inline BBox<Vec3r> getScene3dBBox() const {return _scene3DBBox;}
+
+ /* modifiers */
+ void AddViewShape(ViewShape *iVShape);
+ inline void AddViewEdge(ViewEdge *iVEdge) {_VEdges.push_back(iVEdge);}
+ inline void AddViewVertex(ViewVertex *iVVertex) {_VVertices.push_back(iVVertex);}
+ inline void AddFEdge(FEdge *iFEdge) {_FEdges.push_back(iFEdge);}
+ inline void AddSVertex(SVertex *iSVertex) {_SVertices.push_back(iSVertex);}
+ /*! Sets the scene 3D bounding box. */
+ inline void setScene3dBBox(const BBox<Vec3r>& bbox) {_scene3DBBox=bbox;}
+
+ /* Creates a T vertex in the view map.
+ * A T vertex is the intersection between 2
+ * FEdges (before these ones are splitted).
+ * The TVertex is a 2D intersection but it
+ * corresponds to a 3D point on each of the 2 FEdges.
+ * iA3D
+ * The 3D coordinates of the point corresponding
+ * to the intersection on the first edge.
+ * iA2D
+ * The x,y,z 2D coordinates of the projection
+ * of iA3D
+ * iFEdgeA
+ * The first FEdge
+ * iB3D
+ * The 3D coordinates of the point corresponding
+ * to the intersection on the second edge.
+ * iB2D
+ * The x,y,z 2D coordinates of the projection
+ * of iB3D
+ * iFEdgeB
+ * The second FEdge
+ * id
+ * The id that must be given to that TVertex
+ */
+ TVertex* CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA,
+ const Vec3r& iB3D, const Vec3r& iB2D, FEdge *iFEdgeB,
+ const Id& id);
+
+ /* Updates the structures to take into account the fact
+ * that a SVertex must now be considered as a ViewVertex
+ * iVertex
+ * The SVertex on top of which the ViewVertex is built (it is necessarily
+ * a NonTVertex because it is a SVertex)
+ * newViewEdges
+ * The new ViewEdges that must be add to the ViewMap
+ */
+ ViewVertex * InsertViewVertex(SVertex *iVertex, vector<ViewEdge*>& newViewEdges);
+
+ /* connects a FEdge to the graph trough a SVertex */
+ //FEdge * Connect(FEdge *ioEdge, SVertex *ioVertex);
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewVertex */
+ /* */
+ /* */
+ /**********************************/
+
+class ViewEdge;
+class SShape;
+
+namespace ViewVertexInternal {
+ class edge_const_traits;
+ class edge_nonconst_traits;
+ template<class Traits> class edge_iterator_base ;
+ class orientedViewEdgeIterator;
+} // end of namespace ViewEdgeInternal
+/*! Class to define a view vertex
+ * A view vertex is a feature vertex corresponding
+ * to a point of the image graph, where the characteristics of an
+ * edge might change (nature, visibility, ...).
+ * A ViewVertex can be of two kinds: a TVertex when
+ * it corresponds to the intersection between two
+ * ViewEdges or a NonTVertex when it corresponds to a
+ * vertex of the initial input mesh (it is the case
+ * for vertices such as corners for example).
+ * Thus, this class can be specialized into two classes,
+ * the TVertex class and the NonTVertex class.
+ */
+class LIB_VIEW_MAP_EXPORT ViewVertex : public Interface0D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "ViewVertex" .*/
+ virtual string getExactTypeName() const {
+ return "ViewVertex";
+ }
+
+public:
+ friend class ViewShape;
+ typedef pair<ViewEdge*, bool> directedViewEdge; // if bool = true, the ViewEdge is incoming
+
+ typedef vector<directedViewEdge> edges_container;
+
+ typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_nonconst_traits> edge_iterator;
+ typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_const_traits> const_edge_iterator;
+
+private:
+
+ Nature::VertexNature _Nature;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void * userdata;
+ /*! Default constructor.*/
+ inline ViewVertex() {userdata = 0;_Nature = Nature::VIEW_VERTEX; }
+ inline ViewVertex(Nature::VertexNature nature) {
+ userdata = 0;
+ _Nature = Nature::VIEW_VERTEX | nature;
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline ViewVertex(ViewVertex& iBrother)
+ {
+ _Nature = iBrother._Nature;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+ /*! Cloning method. */
+ virtual ViewVertex * dupplicate() = 0;
+
+public:
+ /*! Destructor. */
+ virtual ~ViewVertex() {}
+
+ /* accessors */
+ /*! Returns the nature of the vertex .*/
+ virtual Nature::VertexNature getNature() const {
+ return _Nature;
+ }
+
+ /* modifiers */
+ /*! Sets the nature of the vertex. */
+ inline void setNature(Nature::VertexNature iNature) {_Nature = iNature;}
+
+ /* Replaces old edge by new edge */
+ virtual void Replace(ViewEdge *, ViewEdge *) {}
+
+public:
+
+ /* iterators access */
+ // allows iteration on the edges that comes from/goes to
+ // this vertex in CCW order (order defined in 2D in the image plan)
+ virtual edge_iterator edges_begin() = 0;
+ virtual const_edge_iterator edges_begin() const = 0;
+ virtual edge_iterator edges_end() = 0;
+ virtual const_edge_iterator edges_end() const = 0;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge) = 0;
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const = 0;
+
+ // Iterator access
+ /*! Returns an iterator over the ViewEdges that goes to or comes from
+ * this ViewVertex pointing to the first ViewEdge of the list.
+ * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() = 0;
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex,
+ * pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() = 0;
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge
+ * given as argument.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0;
+
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* TVertex */
+ /* */
+ /* */
+ /**********************************/
+
+/*! class to define a T vertex, i.e. an intersection between
+ * two edges.
+ * It points towards 2 SVertex and 4 View edges.
+ * Among these ViewEdges, 2 are front and 2 are back.
+ * Basically the front edge hides part of the back edge.
+ * So, among the back edges, 1 is of invisibility n
+ * and the other of visibility n+1
+ */
+class LIB_VIEW_MAP_EXPORT TVertex : public ViewVertex
+{
+public:
+ typedef vector<directedViewEdge*> edge_pointers_container;
+public: // Implementation of Interface0D
+
+ /*! Returns the string "TVertex" .*/
+ virtual string getExactTypeName() const {
+ return "TVertex";
+ }
+
+ // Data access methods
+ /* Returns the 3D x coordinate of the vertex .
+ * Ambiguous in this case.
+ */
+ virtual real getX() const {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().x();
+ }
+
+ virtual real getY() const {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().y();
+ }
+
+ virtual real getZ() const {
+ cerr << "Warning: getX() undefined for this point" << endl;
+ return _FrontSVertex->point3D().z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ cerr << "Warning: getPoint3D() undefined for this point" << endl;
+ return _FrontSVertex->getPoint3D();
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const {
+ return _FrontSVertex->point2D().x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const {
+ return _FrontSVertex->point2D().y();
+ }
+
+ virtual real getProjectedZ() const {
+ return _FrontSVertex->point2D().z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return _FrontSVertex->getPoint2D();
+ }
+
+ /*! Returns the Id of the TVertex .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ // it can't
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ return this;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ return this;
+ }
+
+private:
+ SVertex *_FrontSVertex;
+ SVertex *_BackSVertex;
+ directedViewEdge _FrontEdgeA;
+ directedViewEdge _FrontEdgeB;
+ directedViewEdge _BackEdgeA;
+ directedViewEdge _BackEdgeB;
+ Id _Id; // id to identify t vertices . these id will be negative in order not to be mixed with NonTVertex ids.
+ edge_pointers_container _sortedEdges; // the list of the four ViewEdges, ordered in CCW order (in the image plan)
+
+
+public:
+ /*! Default constructor.*/
+ inline TVertex() : ViewVertex(Nature::T_VERTEX)
+ {
+ _FrontSVertex = 0;
+ _BackSVertex = 0;
+ _FrontEdgeA.first = 0;
+ _FrontEdgeB.first = 0;
+ _BackEdgeA.first = 0;
+ _BackEdgeB.first = 0;
+
+ }
+
+ inline TVertex(SVertex *svFront, SVertex *svBack)
+ : ViewVertex(Nature::T_VERTEX)
+ {
+ _FrontSVertex = svFront;
+ _BackSVertex = svBack;
+ _FrontEdgeA.first = 0;
+ _FrontEdgeB.first = 0;
+ _BackEdgeA.first = 0;
+ _BackEdgeB.first = 0;
+ svFront->SetViewVertex(this);
+ svBack->SetViewVertex(this);
+ }
+
+protected:
+ /*! Copy constructor. */
+ inline TVertex(TVertex& iBrother)
+ : ViewVertex(iBrother)
+ {
+ _FrontSVertex = iBrother._FrontSVertex;
+ _BackSVertex = iBrother._BackSVertex;
+ _FrontEdgeA = iBrother._FrontEdgeA;
+ _FrontEdgeB = iBrother._FrontEdgeB;
+ _BackEdgeA = iBrother._BackEdgeA;
+ _BackEdgeB = iBrother._BackEdgeB;
+ _sortedEdges = iBrother._sortedEdges;
+ }
+
+ /*! Cloning method. */
+ virtual ViewVertex * dupplicate()
+ {
+ TVertex *clone = new TVertex(*this);
+ return clone;
+ }
+
+public:
+ /* accessors */
+ /*! Returns the SVertex that is closer to the viewpoint. */
+ inline SVertex *frontSVertex() {return _FrontSVertex;}
+ /*! Returns the SVertex that is further away from the viewpoint. */
+ inline SVertex *backSVertex() {return _BackSVertex;}
+ inline directedViewEdge& frontEdgeA() {return _FrontEdgeA;}
+ inline directedViewEdge& frontEdgeB() {return _FrontEdgeB;}
+ inline directedViewEdge& backEdgeA() {return _BackEdgeA;}
+ inline directedViewEdge& backEdgeB() {return _BackEdgeB;}
+
+ /* modifiers */
+ /*! Sets the SVertex that is closer to the viewpoint. */
+ inline void SetFrontVertex(SVertex *iFrontSVertex) {_FrontSVertex = iFrontSVertex;_FrontSVertex->SetViewVertex(this);}
+ /*! Sets the SVertex that is further away from the viewpoint. */
+ inline void SetBackSVertex(SVertex *iBackSVertex) {_BackSVertex = iBackSVertex;_BackSVertex->SetViewVertex(this);}
+ void SetFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming=true);
+ void SetFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming=true) ;
+ void SetBackEdgeA(ViewEdge *iBackEdgeA, bool incoming=true);
+ void SetBackEdgeB(ViewEdge *iBackEdgeB, bool incoming=true) ;
+ /*! Sets the Id. */
+ inline void SetId(const Id& iId) {_Id = iId;}
+
+ /*! Returns the SVertex (among the 2) belonging to the FEdge iFEdge */
+ inline SVertex * GetSVertex(FEdge *iFEdge)
+ {
+ const vector<FEdge*>& vfEdges = _FrontSVertex->fedges();
+ vector<FEdge*>::const_iterator fe,fend;
+ for(fe=vfEdges.begin(),fend=vfEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ if((*fe) == iFEdge)
+ return _FrontSVertex;
+ }
+
+ const vector<FEdge*>& vbEdges = _BackSVertex->fedges();
+ for(fe=vbEdges.begin(),fend=vbEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ if((*fe) == iFEdge)
+ return _BackSVertex;
+ }
+ return 0;
+ }
+
+ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew);
+
+ /*! returns the mate edge of iEdgeA.
+ * For example, if iEdgeA is frontEdgeA,
+ * then frontEdgeB is returned. If iEdgeA is
+ * frontEdgeB then frontEdgeA is returned.
+ * Same for back edges
+ */
+ virtual ViewEdge * mate(ViewEdge* iEdgeA)
+ {
+ if(iEdgeA == _FrontEdgeA.first)
+ return _FrontEdgeB.first;
+ if(iEdgeA == _FrontEdgeB.first)
+ return _FrontEdgeA.first;
+ if(iEdgeA == _BackEdgeA.first)
+ return _BackEdgeB.first;
+ if(iEdgeA == _BackEdgeB.first)
+ return _BackEdgeA.first;
+ return 0;
+ }
+
+ /* iterators access */
+ virtual edge_iterator edges_begin();
+ virtual const_edge_iterator edges_begin() const;
+ virtual edge_iterator edges_end();
+ virtual const_edge_iterator edges_end() const;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge);
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
+
+ /*! Returns an iterator over the ViewEdges that goes to or comes from
+ * this ViewVertex pointing to the first ViewEdge of the list.
+ * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() ;
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex,
+ * pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() ;
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge
+ * given as argument.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) ;
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* NonTVertex */
+ /* */
+ /* */
+ /**********************************/
+
+
+// (non T vertex)
+/*! View vertex for corners, cusps, etc...
+ * Associated to a single SVertex.
+ * Can be associated to 2 or several view edges
+ */
+class LIB_VIEW_MAP_EXPORT NonTVertex : public ViewVertex
+{
+public:
+ typedef vector<directedViewEdge> edges_container;
+
+public: // Implementation of Interface0D
+
+ /*! Returns the string "ViewVertex" .*/
+ virtual string getExactTypeName() const {
+ return "NonTVertex";
+ }
+
+ // Data access methods
+ /*! Returns the 3D x coordinate of the vertex .*/
+ virtual real getX() const {
+ return _SVertex->point3D().x();
+ }
+ /*! Returns the 3D y coordinate of the vertex .*/
+ virtual real getY() const {
+ return _SVertex->point3D().y();
+ }
+
+ /*! Returns the 3D z coordinate of the vertex .*/
+ virtual real getZ() const {
+ return _SVertex->point3D().z();
+ }
+
+ /*! Returns the 3D point. */
+ virtual Vec3f getPoint3D() const {
+ return _SVertex->getPoint3D();
+ }
+
+ /*! Returns the projected 3D x coordinate of the vertex .*/
+ virtual real getProjectedX() const {
+ return _SVertex->point2D().x();
+ }
+
+ /*! Returns the projected 3D y coordinate of the vertex .*/
+ virtual real getProjectedY() const {
+ return _SVertex->point2D().y();
+ }
+
+ /*! Returns the projected 3D z coordinate of the vertex .*/
+ virtual real getProjectedZ() const {
+ return _SVertex->point2D().z();
+ }
+
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return _SVertex->getPoint2D();
+ }
+
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const {
+ return _SVertex->getId();
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ return _SVertex;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ return this;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ return this;
+ }
+
+private:
+ SVertex *_SVertex;
+ edges_container _ViewEdges;
+public:
+ /*! Default constructor.*/
+ inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX) { _SVertex = 0; }
+ /*! Builds a NonTVertex from a SVertex. */
+ inline NonTVertex(SVertex* iSVertex) : ViewVertex(Nature::NON_T_VERTEX)
+ {
+ _SVertex = iSVertex;
+ _SVertex->SetViewVertex(this);
+ }
+protected:
+ /*! Copy constructor. */
+ inline NonTVertex(NonTVertex& iBrother)
+ : ViewVertex(iBrother)
+ {
+ _SVertex = iBrother._SVertex;
+ _SVertex->SetViewVertex(this);
+ _ViewEdges = iBrother._ViewEdges;
+ }
+ /*! Cloning method. */
+ virtual ViewVertex * dupplicate()
+ {
+ NonTVertex *clone = new NonTVertex(*this);
+ return clone;
+ }
+public:
+ /*! destructor. */
+ virtual ~NonTVertex() {}
+
+ /* accessors */
+ /*! Returns the SVertex on top of which this NonTVertex is built. */
+ inline SVertex * svertex() {return _SVertex;}
+ inline edges_container& viewedges() {return _ViewEdges;}
+
+ /* modifiers */
+ /*! Sets the SVertex on top of which this NonTVertex is built. */
+ inline void SetSVertex(SVertex *iSVertex) {_SVertex = iSVertex;_SVertex->SetViewVertex(this);}
+ inline void SetViewEdges(const vector<directedViewEdge>& iViewEdges) {_ViewEdges = iViewEdges;}
+ void AddIncomingViewEdge(ViewEdge * iVEdge) ;
+ void AddOutgoingViewEdge(ViewEdge * iVEdge) ;
+ inline void AddViewEdge(ViewEdge * iVEdge, bool incoming=true) {
+ if(incoming)
+ AddIncomingViewEdge(iVEdge);
+ else
+ AddOutgoingViewEdge(iVEdge);
+ }
+ /* Replaces old edge by new edge */
+ virtual void Replace(ViewEdge *iOld, ViewEdge *iNew)
+ {
+
+ edges_container::iterator insertedve;
+ for(edges_container::iterator ve=_ViewEdges.begin(),vend=_ViewEdges.end();
+ ve!=vend;
+ ve++)
+ {
+ if((ve)->first == iOld)
+ {
+ insertedve = _ViewEdges.insert(ve, directedViewEdge(iNew, ve->second));// inserts e2 before ve.
+ // returns an iterator pointing toward e2. ve is invalidated.
+ // we want to remove e1, but we can't use ve anymore:
+ insertedve++; // insertedve points now to e1
+ _ViewEdges.erase(insertedve);
+ return;
+ }
+ }
+ }
+
+
+ /* iterators access */
+ virtual edge_iterator edges_begin();
+ virtual const_edge_iterator edges_begin() const;
+ virtual edge_iterator edges_end();
+ virtual const_edge_iterator edges_end() const;
+ virtual edge_iterator edges_iterator(ViewEdge *iEdge);
+ virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
+
+ /*! Returns an iterator over the ViewEdges that goes to or comes from
+ * this ViewVertex pointing to the first ViewEdge of the list.
+ * The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
+ * and to get the orientation for each ViewEdge (incoming/outgoing).
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() ;
+ /*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex,
+ * pointing after the last ViewEdge.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() ;
+ /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge
+ * given as argument.
+ */
+ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) ;
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+/* Geometry(normals...)
+ Nature of edges
+ 2D spaces (1or2, material, z...)
+ Parent Shape
+ 3D Shading, material
+ Importance
+ Occluders
+ */
+class ViewShape;
+
+namespace ViewEdgeInternal {
+ template<class Traits> class edge_iterator_base ;
+ template<class Traits> class fedge_iterator_base ;
+ template<class Traits> class vertex_iterator_base ;
+} // end of namespace ViewEdgeInternal
+
+/*! Class defining a ViewEdge. A ViewEdge in an edge
+ * of the image graph. it connnects two ViewVertex.
+ * It is made by connecting a set of FEdges.
+ */
+class LIB_VIEW_MAP_EXPORT ViewEdge : public Interface1D
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "ViewEdge" .*/
+ virtual string getExactTypeName() const {
+ return "ViewEdge";
+ }
+
+ // Data access methods
+ /*! Returns the Id of the vertex .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+
+ /*! Returns the nature of the ViewEdge. */
+ virtual Nature::EdgeNature getNature() const {
+ return _Nature;
+ }
+
+public:
+
+ typedef SVertex vertex_type;
+ friend class ViewShape;
+ // for ViewEdge iterator
+ typedef ViewEdgeInternal::edge_iterator_base<Nonconst_traits<ViewEdge*> > edge_iterator;
+ typedef ViewEdgeInternal::edge_iterator_base<Const_traits<ViewEdge*> > const_edge_iterator;
+ // for fedge iterator
+ typedef ViewEdgeInternal::fedge_iterator_base<Nonconst_traits<FEdge*> > fedge_iterator;
+ typedef ViewEdgeInternal::fedge_iterator_base<Const_traits<FEdge*> > const_fedge_iterator;
+ // for svertex iterator
+ typedef ViewEdgeInternal::vertex_iterator_base<Nonconst_traits<SVertex*> > vertex_iterator;
+ typedef ViewEdgeInternal::vertex_iterator_base<Const_traits<SVertex*> > const_vertex_iterator;
+private:
+
+ ViewVertex * __A; // edge starting vertex
+ ViewVertex * __B; // edge ending vertex
+ Nature::EdgeNature _Nature; // nature of view edge
+ ViewShape *_Shape; // shape to which the view edge belongs
+ FEdge * _FEdgeA; // first edge of the embedded fedges chain
+ FEdge * _FEdgeB; // last edge of the embedded fedges chain
+ Id _Id;
+ unsigned _ChainingTimeStamp;
+ ViewShape *_aShape; // The silhouette view edge separates 2 2D spaces. The one on the left is
+ // necessarly the Shape _Shape (the one to which this edge belongs to)
+ // and _aShape is the one on its right // NON GERE PAR LE COPY CONSTRUCTEUR
+ int _qi;
+ vector<ViewShape*> _Occluders;
+
+ // tmp
+ Id * _splittingId;
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void * userdata;
+ /*! Default constructor.*/
+ inline ViewEdge() {
+ __A=0;
+ __B=0;
+ _FEdgeA = 0;
+ _FEdgeB = 0;
+ _ChainingTimeStamp = 0;
+ _qi = 0;
+ _aShape=0;
+ userdata = 0;
+ _splittingId = 0;
+ }
+ inline ViewEdge(ViewVertex* iA, ViewVertex *iB)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = 0;
+ _FEdgeB = 0;
+ _Shape = 0;
+ _ChainingTimeStamp = 0;
+ _aShape = 0;
+ _qi = 0;
+ userdata = 0;
+ _splittingId = 0;
+ }
+ inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = iFEdgeA;
+ _FEdgeB = 0;
+ _Shape = 0;
+ _ChainingTimeStamp = 0;
+ _aShape = 0;
+ _qi = 0;
+ userdata = 0;
+ _splittingId = 0;
+ }
+ inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA, FEdge *iFEdgeB, ViewShape *iShape)
+ {
+ __A = iA;
+ __B = iB;
+ _FEdgeA = iFEdgeA;
+ _FEdgeB = iFEdgeB;
+ _Shape = iShape;
+ _ChainingTimeStamp = 0;
+ _aShape = 0;
+ _qi = 0;
+ userdata = 0;
+ _splittingId = 0;
+ UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge
+ }
+protected:
+ /*! Copy constructor. */
+ inline ViewEdge(ViewEdge& iBrother)
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _FEdgeA = iBrother._FEdgeA;
+ _FEdgeB = iBrother._FEdgeB;
+ _Nature = iBrother._Nature;
+ _Shape = 0;
+ _Id = iBrother._Id;
+ _ChainingTimeStamp = iBrother._ChainingTimeStamp;
+ _aShape = iBrother._aShape;
+ _qi = iBrother._qi;
+ _splittingId = 0;
+ iBrother.userdata = this;
+ userdata = 0;
+ }
+ /*! Cloning method. */
+ virtual ViewEdge * dupplicate()
+ {
+ ViewEdge *clone = new ViewEdge(*this);
+ return clone;
+ }
+
+public:
+ /*! Destructor. */
+ virtual ~ViewEdge()
+ {
+ // if(0 != _aFace)
+ // {
+ // delete _aFace;
+ // _aFace = 0;
+ // }
+ // only the last splitted deletes this id
+ if(_splittingId){
+ if(*_splittingId == _Id)
+ delete _splittingId;
+ }
+ }
+
+ /* accessors */
+ /*! Returns the first ViewVertex. */
+ inline ViewVertex* A() {return __A;}
+ /*! Returns the second ViewVertex. */
+ inline ViewVertex* B() {return __B;}
+ /*! Returns the first FEdge that constitues this ViewEdge. */
+ inline FEdge* fedgeA() {return _FEdgeA;}
+ /*! Returns the last FEdge that constitues this ViewEdge. */
+ inline FEdge* fedgeB() {return _FEdgeB;}
+ /*! Returns the ViewShape to which this ViewEdge belongs to .*/
+ inline ViewShape * viewShape() {return _Shape;}
+ /*! Returns the shape that is occluded by the ViewShape
+ * to which this ViewEdge belongs to. If no object is occluded,
+ * 0 is returned.
+ * \return The occluded ViewShape.
+ */
+ inline ViewShape * aShape() {return _aShape;}
+ /*! Tells whether this ViewEdge forms a closed loop
+ * or not.
+ */
+ inline bool isClosed()
+ {
+ if(__B == 0)
+ return true;
+ return false;
+ }
+ /*! Returns the time stamp of this ViewEdge. */
+ inline unsigned getChainingTimeStamp() {return _ChainingTimeStamp;}
+ inline const ViewShape * aShape() const {return _aShape;}
+ inline const ViewShape * bShape() const {return _Shape;}
+ inline vector<ViewShape*>& occluders() {return _Occluders;}
+ inline Id * splittingId() {return _splittingId;}
+
+ /* modifiers */
+ /*! Sets the first ViewVertex of the ViewEdge. */
+ inline void SetA(ViewVertex* iA) { __A = iA; }
+ /*! Sets the last ViewVertex of the ViewEdge. */
+ inline void SetB(ViewVertex* iB) { __B = iB; }
+ /*! Sets the nature of the ViewEdge. */
+ inline void SetNature(Nature::EdgeNature iNature) { _Nature = iNature; }
+ /*! Sets the first FEdge of the ViewEdge. */
+ inline void SetFEdgeA(FEdge* iFEdge) { _FEdgeA = iFEdge; }
+ /*! Sets the last FEdge of the ViewEdge. */
+ inline void SetFEdgeB(FEdge* iFEdge) { _FEdgeB = iFEdge; }
+ /*! Sets the ViewShape to which this ViewEdge belongs to.*/
+ inline void SetShape(ViewShape *iVShape)
+ {
+ _Shape = iVShape;
+ }
+ /*! Sets the ViewEdge id. */
+ inline void SetId(const Id& id) {_Id = id;}
+ /*! Sets Viewedge to this for all embedded fedges */
+ void UpdateFEdges();
+ /*! Sets the occluded ViewShape */
+ inline void SetaShape(ViewShape * iShape) {_aShape = iShape;}
+ /*! Sets the quantitative invisibility value. */
+ inline void SetQI(int qi) {_qi = qi;}
+ /*! Sets the time stamp value. */
+ inline void setChainingTimeStamp(unsigned ts) {_ChainingTimeStamp = ts;}
+ inline void AddOccluder(ViewShape *iShape) {_Occluders.push_back(iShape);}
+ inline void setSplittingId(Id * id) {_splittingId = id;}
+
+ /* stroke interface definition */
+ inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
+ {
+ // parse edges to check if one of them is intersection the region:
+ FEdge * current = _FEdgeA;
+ do
+ {
+ if(GeomUtils::intersect2dSeg2dArea(iMin,iMax,
+ Vec2r(current->vertexA()->point2D()[0],current->vertexA()->point2D()[1]),
+ Vec2r(current->vertexB()->point2D()[0],current->vertexB()->point2D()[1])))
+
+ return true;
+ current = current->nextEdge();
+ }while((current != 0) && (current != _FEdgeA));
+
+ return false;
+ }
+ inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
+ {
+ // parse edges to check if all of them are intersection the region:
+ FEdge * current = _FEdgeA;
+
+ do
+ {
+ if(!GeomUtils::include2dSeg2dArea(iMin,iMax,
+ Vec2r(current->vertexA()->point2D()[0],current->vertexA()->point2D()[1]),
+ Vec2r(current->vertexB()->point2D()[0],current->vertexB()->point2D()[1])))
+ return false;
+ current = current->nextEdge();
+ }while((current != 0) && (current != _FEdgeA));
+
+ return true;
+ }
+
+ /* Information access interface */
+
+ //inline Nature::EdgeNature viewedge_nature() const {return getNature();}
+ //float viewedge_length() const ;
+ /*! Returns the 2D length of the Viewedge. */
+ real getLength2D() const;
+ //inline Material material() const {return _FEdgeA->vertexA()->shape()->material();}
+ inline int qi() const {return _qi;}
+ inline occluder_container::const_iterator occluders_begin() const {return _Occluders.begin();}
+ inline occluder_container::const_iterator occluders_end() const {return _Occluders.end();}
+ inline int occluders_size() const {return _Occluders.size();}
+ inline bool occluders_empty() const {return _Occluders.empty();}
+ inline const Polygon3r& occludee() const {return (_FEdgeA->aFace());}
+ inline const SShape * occluded_shape() const ;
+ inline const bool occludee_empty() const {if(_aShape == 0) return true; return false;}
+ //inline real z_discontinuity(int iCombination = 0) const ;
+ inline Id shape_id() const {return _FEdgeA->vertexA()->shape()->getId();}
+ inline const SShape * shape() const {return _FEdgeA->vertexA()->shape();}
+ inline float shape_importance() const {return _FEdgeA->shape_importance();}
+
+ /* iterators access */
+ // view edge iterator
+ edge_iterator ViewEdge_iterator();
+ const_edge_iterator ViewEdge_iterator() const;
+ // feature edge iterator
+ fedge_iterator fedge_iterator_begin();
+ const_fedge_iterator fedge_iterator_begin() const;
+ fedge_iterator fedge_iterator_last();
+ const_fedge_iterator fedge_iterator_last() const;
+ fedge_iterator fedge_iterator_end();
+ const_fedge_iterator fedge_iterator_end() const;
+ // embedding vertex iterator
+ const_vertex_iterator vertices_begin() const;
+ vertex_iterator vertices_begin();
+ const_vertex_iterator vertices_last() const;
+ vertex_iterator vertices_last();
+ const_vertex_iterator vertices_end() const;
+ vertex_iterator vertices_end();
+
+ // Iterator access (Interface1D)
+ /*! Returns an Interface0DIterator to iterate over
+ * the SVertex constituing the embedding of this ViewEdge.
+ * The returned Interface0DIterator points to the first
+ * SVertex of the ViewEdge.
+ */
+ virtual Interface0DIterator verticesBegin();
+ /*! Returns an Interface0DIterator to iterate over
+ * the SVertex constituing the embedding of this ViewEdge.
+ * The returned Interface0DIterator points after the last
+ * SVertex of the ViewEdge.
+ */
+ virtual Interface0DIterator verticesEnd();
+
+ /*! Returns an Interface0DIterator to iterate over
+ * the points of this ViewEdge at a given resolution.
+ * The returned Interface0DIterator points on the first
+ * Point of the ViewEdge.
+ * \param t
+ * the sampling value.
+ */
+ virtual Interface0DIterator pointsBegin(float t=0.f);
+ /*! Returns an Interface0DIterator to iterate over
+ * the points of this ViewEdge at a given resolution.
+ * The returned Interface0DIterator points after the last
+ * Point of the ViewEdge.
+ * \param t
+ * the sampling value.
+ */
+ virtual Interface0DIterator pointsEnd(float t=0.f);
+};
+
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewShape */
+ /* */
+ /* */
+ /**********************************/
+
+/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge)
+ * that are issued from the same input shape.
+ */
+class LIB_VIEW_MAP_EXPORT ViewShape
+{
+private:
+ vector<ViewVertex*> _Vertices;
+ vector<ViewEdge*> _Edges;
+ SShape * _SShape;
+
+
+public:
+ /*! A field that can be used by the user to store any data.
+ * This field must be reseted afterwards using ResetUserData().
+ */
+ void* userdata;
+ /*! Default constructor.*/
+ inline ViewShape() { userdata = 0; _SShape = 0;}
+ /*! Builds a ViewShape from a SShape. */
+ inline ViewShape(SShape *iSShape) {userdata = 0; _SShape = iSShape;}//_SShape->SetViewShape(this);}
+ /*! Copy constructor. */
+ inline ViewShape(ViewShape& iBrother)
+ {
+ userdata = 0;
+ vector<ViewVertex*>::iterator vv,vvend;
+ vector<ViewEdge*>::iterator ve, veend;
+
+ _SShape = iBrother._SShape;
+
+ vector<ViewVertex*>& vvertices = iBrother.vertices();
+ // dupplicate vertices
+ for(vv=vvertices.begin(), vvend=vvertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ ViewVertex * newVertex = (*vv)->dupplicate();
+ AddVertex(newVertex);
+ }
+
+ vector<ViewEdge*>& vvedges = iBrother.edges();
+ // dupplicate edges
+ for(ve=vvedges.begin(), veend=vvedges.end();
+ ve!=veend;
+ ve++)
+ {
+ ViewEdge * newEdge = (*ve)->dupplicate();
+ AddEdge(newEdge); // here the shape is set as the edge's shape
+ }
+
+ //-------------------------
+ // remap edges in vertices:
+ //-------------------------
+ for(vv=_Vertices.begin(), vvend=_Vertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ switch((*vv)->getNature())
+ {
+ case Nature::T_VERTEX:
+ {
+ TVertex *v = (TVertex*)(*vv);
+ ViewEdge *veFrontA = (ViewEdge*)(v)->frontEdgeA().first->userdata;
+ ViewEdge *veFrontB = (ViewEdge*)(v)->frontEdgeB().first->userdata;
+ ViewEdge *veBackA = (ViewEdge*)(v)->backEdgeA().first->userdata;
+ ViewEdge *veBackB = (ViewEdge*)(v)->backEdgeB().first->userdata;
+
+ v->SetFrontEdgeA(veFrontA, v->frontEdgeA().second);
+ v->SetFrontEdgeB(veFrontB, v->frontEdgeB().second);
+ v->SetBackEdgeA(veBackA, v->backEdgeA().second);
+ v->SetBackEdgeB(veBackB, v->backEdgeB().second);
+ }
+ break;
+ case Nature::NON_T_VERTEX:
+ {
+ NonTVertex * v = (NonTVertex*)(*vv);
+ vector<ViewVertex::directedViewEdge>& vedges = (v)->viewedges();
+ vector<ViewVertex::directedViewEdge> newEdges;
+ for(vector<ViewVertex::directedViewEdge>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ ViewEdge *current = (ViewEdge*)((ve)->first)->userdata;
+ newEdges.push_back(ViewVertex::directedViewEdge(current, ve->second));
+ }
+ (v)->SetViewEdges(newEdges);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+
+ //-------------------------------------
+ // remap vertices in edges:
+ //-------------------------------------
+ for(ve=_Edges.begin(),veend=_Edges.end();
+ ve!=veend;
+ ve++)
+ {
+ (*ve)->SetA((ViewVertex*)((*ve)->A()->userdata));
+ (*ve)->SetB((ViewVertex*)((*ve)->B()->userdata));
+ //---------------------------------------
+ // Update all embedded FEdges
+ //---------------------------------------
+ (*ve)->UpdateFEdges();
+ }
+
+
+ // reset all brothers userdata to NULL:
+ //-------------------------------------
+ //---------
+ // vertices
+ //---------
+ for(vv=vvertices.begin(),vvend=vvertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ (*vv)->userdata = NULL;
+ }
+
+ //------
+ // edges
+ //------
+ for(ve=vvedges.begin(),veend=vvedges.end();
+ ve!=veend;
+ ve++)
+ {
+ (*ve)->userdata = NULL;
+ }
+ }
+
+ /*! Cloning method. */
+ virtual ViewShape * dupplicate()
+ {
+ ViewShape *clone = new ViewShape(*this);
+ return clone;
+ }
+
+ /*! Destructor. */
+ virtual ~ViewShape();
+
+ /* splits a view edge into several view edges.
+ * fe
+ * The FEdge that gets splitted
+ * iViewVertices
+ * The view vertices corresponding to the different intersections for the edge fe.
+ * This list need to be sorted such as the first view vertex is the
+ * farther away from fe->vertexA.
+ * ioNewEdges
+ * The feature edges that are newly created (the initial edges are not
+ * included) are added to this list.
+ * ioNewViewEdges
+ * The view edges that are newly created (the initial edges are not
+ * included) are added to this list.
+ */
+ inline void SplitEdge(FEdge *fe,
+ const vector<TVertex*>& iViewVertices,
+ vector<FEdge*>& ioNewEdges,
+ vector<ViewEdge*>& ioNewViewEdges);
+ /* accessors */
+ /*! Returns the SShape on top of which this ViewShape is built. */
+ inline SShape * sshape() {return _SShape;}
+ /*! Returns the SShape on top of which this ViewShape is built. */
+ inline const SShape * sshape() const {return _SShape;}
+ /*! Returns the list of ViewVertex contained in this ViewShape. */
+ inline vector<ViewVertex*>& vertices() {return _Vertices;}
+ /*! Returns the list of ViewEdge contained in this ViewShape. */
+ inline vector<ViewEdge*>& edges() {return _Edges;}
+ /*! Returns the ViewShape id. */
+ inline Id getId() const {return _SShape->getId();}
+
+ /* modifiers */
+ /*! Sets the SShape on top of which the ViewShape is built. */
+ inline void SetSShape(SShape* iSShape) {_SShape = iSShape;}
+ /*! Sets the list of ViewVertex contained in this ViewShape. */
+ inline void SetVertices(const vector<ViewVertex*>& iVertices) {_Vertices = iVertices;}
+ /*! Sets the list of ViewEdge contained in this ViewShape. */
+ inline void SetEdges(const vector<ViewEdge*>& iEdges) {_Edges = iEdges;}
+ /*! Adds a ViewVertex to the list. */
+ inline void AddVertex(ViewVertex *iVertex)
+ {
+ _Vertices.push_back(iVertex);
+ //_SShape->AddNewVertex(iVertex->svertex());
+ }
+ /*! Adds a ViewEdge to the list */
+ inline void AddEdge(ViewEdge *iEdge)
+ {
+ _Edges.push_back(iEdge);
+ iEdge->SetShape(this);
+ //_SShape->AddNewEdge(iEdge->fedge());
+ }
+
+ /* removes the view edge iViewEdge in the
+ * View Shape and the associated FEdge chain entry
+ * in the underlying SShape
+ */
+ void RemoveEdge(ViewEdge * iViewEdge);
+
+ /* removes the view vertex iViewVertex in the
+ * View Shape.
+ */
+ void RemoveVertex(ViewVertex * iViewVertex);
+};
+
+
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+/* for inline functions */
+
+void ViewShape::SplitEdge(FEdge *fe,
+ const vector<TVertex*>& iViewVertices,
+ vector<FEdge*>& ioNewEdges,
+ vector<ViewEdge*>& ioNewViewEdges)
+{
+ ViewEdge *vEdge = fe->viewedge();
+
+
+ // We first need to sort the view vertices from farther to closer to fe->vertexA
+
+ SVertex *sv, *sv2;
+ ViewVertex *vva, *vvb;
+ vector<TVertex*>::const_iterator vv, vvend;
+ for(vv=iViewVertices.begin(), vvend = iViewVertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ // Add the viewvertices to the ViewShape
+ AddVertex((*vv));
+
+ // retrieve the correct SVertex from the view vertex
+ //--------------------------------------------------
+ sv = (*vv)->frontSVertex();
+ sv2 = (*vv)->backSVertex();
+
+ if(sv->shape() != sv2->shape())
+ {
+ if(sv->shape() != _SShape)
+ sv = sv2;
+ }
+ else
+ {
+ // if the shape is the same we can safely differ
+ // the two vertices using their ids:
+ if(sv->getId() != fe->vertexA()->getId())
+ sv = sv2;
+ }
+
+ vva = vEdge->A();
+ vvb = vEdge->B();
+
+ // We split Fedge AB into AA' and A'B. A' and A'B are created.
+ // AB becomes (address speaking) AA'. B is updated.
+ //--------------------------------------------------
+ SShape * shape = fe->shape();
+
+ // a new edge, A'B is created.
+ FEdge *newEdge = shape->SplitEdgeIn2(fe, sv);
+
+ ioNewEdges.push_back(newEdge);
+ ViewEdge *newVEdge;
+
+ if((vva == 0) || (vvb == 0)) // that means we're dealing with a closed viewedge (loop)
+ {
+ // remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!)
+ shape->RemoveEdgeFromChain(vEdge->fedgeA());
+ // we set
+ vEdge->SetA(*vv);
+ vEdge->SetB(*vv);
+ vEdge->SetFEdgeA(newEdge);
+ //FEdge *previousEdge = newEdge->previousEdge();
+ vEdge->SetFEdgeB(fe);
+ newVEdge = vEdge;
+ vEdge->fedgeA()->SetViewEdge(newVEdge);
+ }
+ else
+ {
+
+ // while we create the view edge, it updates the "ViewEdge" pointer
+ // of every underlying FEdges to this.
+ newVEdge = new ViewEdge((*vv),vvb);//, newEdge, vEdge->fedgeB());
+ newVEdge->SetNature((fe)->getNature());
+ newVEdge->SetFEdgeA(newEdge);
+ //newVEdge->SetFEdgeB(fe);
+ // If our original viewedge is made of one FEdge,
+ // then
+ if((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB()))
+ newVEdge->SetFEdgeB(newEdge);
+ else
+ newVEdge->SetFEdgeB(vEdge->fedgeB()); //MODIF
+
+ Id * newId = vEdge->splittingId();
+ if(newId == 0){
+ newId = new Id(vEdge->getId());
+ vEdge->setSplittingId(newId);
+ }
+ newId->setSecond(newId->getSecond()+1);
+ newVEdge->SetId(*newId);
+ newVEdge->setSplittingId(newId);
+ // Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond()+1);
+ // newVEdge->SetId(vEdge->getId());
+ // vEdge->SetId(id);
+
+ AddEdge(newVEdge); // here this shape is set as the edge's shape
+
+ // add new edge to the list of new edges passed as argument:
+ ioNewViewEdges.push_back(newVEdge);
+
+
+
+ if(0 != vvb)
+ vvb->Replace((vEdge), newVEdge);
+
+ // we split the view edge:
+ vEdge->SetB((*vv));
+ vEdge->SetFEdgeB(fe); //MODIF
+
+ // Update fedges so that they point to the new viewedge:
+ newVEdge->UpdateFEdges();
+
+ }
+ // check whether this vertex is a front vertex or a back
+ // one
+
+ if(sv == (*vv)->frontSVertex())
+ {
+ // -- View Vertex A' --
+ (*vv)->SetFrontEdgeA(vEdge, true);
+ (*vv)->SetFrontEdgeB(newVEdge, false);
+ }
+ else
+ {
+ // -- View Vertex A' --
+ (*vv)->SetBackEdgeA(vEdge, true);
+ (*vv)->SetBackEdgeB(newVEdge, false);
+ }
+ }
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+
+// inline Vec3r ViewEdge::orientation2d(int iCombination) const
+// {
+// return edge_orientation2d_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline Vec3r ViewEdge::orientation3d(int iCombination) const
+// {
+// return edge_orientation3d_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline real ViewEdge::z_discontinuity(int iCombination) const
+// {
+// return z_discontinuity_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline float ViewEdge::local_average_depth(int iCombination ) const
+// {
+// return local_average_depth_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline float ViewEdge::local_depth_variance(int iCombination) const
+// {
+// return local_depth_variance_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline real ViewEdge::local_average_density(float sigma, int iCombination) const
+// {
+// return density_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+inline const SShape * ViewEdge::occluded_shape() const
+{
+ if(0 == _aShape)
+ return 0;
+ return _aShape->sshape();
+}
+
+// inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const
+// {
+// return curvature2d_as_vector_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+// inline real ViewEdge::curvature2d_as_angle(int iCombination) const
+// {
+// return curvature2d_as_angle_edge_function<ViewEdge>(*this, iCombination);
+// }
+
+
+#endif // VIEWMAP_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
new file mode 100755
index 00000000000..bb2d916f2df
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h
@@ -0,0 +1,691 @@
+//
+// Filename : ViewMapAdvancedIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the various elements of the ViewMap
+// These iterators can't be exported to python.
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPADVANCEDITERATORS_H
+# define VIEWMAPADVANCEDITERATORS_H
+
+#include "ViewMap.h"
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewVertex */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewVertexInternal{
+
+ class edge_const_traits : public Const_traits< ::ViewVertex::directedViewEdge> {
+ public:
+ typedef vector< ::ViewVertex::directedViewEdge> edges_container;
+ typedef edges_container::const_iterator edges_container_iterator ;
+ typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container;
+ typedef edge_pointers_container::const_iterator edge_pointers_container_iterator ;
+ };
+ class edge_nonconst_traits : public Nonconst_traits< ::ViewVertex::directedViewEdge> {
+ public:
+ typedef vector< ::ViewVertex::directedViewEdge> edges_container;
+ typedef edges_container::iterator edges_container_iterator ;
+ typedef vector< ::ViewVertex::directedViewEdge*> edge_pointers_container;
+ typedef edge_pointers_container::iterator edge_pointers_container_iterator ;
+ };
+
+template<class Traits>
+ class edge_iterator_base : public IteratorBase<Traits,InputIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef edge_iterator_base<Traits> Self;
+ typedef typename Traits::edges_container_iterator edges_container_iterator;
+ typedef typename Traits::edge_pointers_container_iterator edge_pointers_container_iterator;
+ typedef edge_iterator_base<edge_nonconst_traits> iterator;
+ typedef edge_iterator_base<edge_const_traits> const_iterator;
+ public:
+ friend class ViewVertex;
+ friend class TVertex;
+ friend class NonTVertex;
+ friend class ViewEdge;
+ friend class edge_iterator;
+ protected:
+ Nature::VertexNature _Nature; // the nature of the underlying vertex
+ // T vertex attributes
+ edge_pointers_container_iterator _tbegin;
+ edge_pointers_container_iterator _tend;
+ edge_pointers_container_iterator _tvertex_iter;
+
+ // mutable value_type _tvertex_iter;
+ // value_type _feA;
+ // value_type _feB;
+ // value_type _beA;
+ // value_type _beB;
+
+ // Non TVertex attributes
+ edges_container_iterator _begin;
+ edges_container_iterator _end;
+ edges_container_iterator _nontvertex_iter;
+
+ typedef IteratorBase<Traits,InputIteratorTag_Traits> parent_class;
+
+ public:
+ inline edge_iterator_base() : parent_class() {}
+ inline edge_iterator_base(Nature::VertexNature iNature)
+ : parent_class()
+ {_Nature = iNature;}
+ edge_iterator_base(const edge_iterator_base<edge_nonconst_traits>& iBrother)
+ : parent_class(iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if(_Nature & Nature::T_VERTEX)
+ {
+ // _feA = iBrother._feA;
+ // _feB = iBrother._feB;
+ // _beA = iBrother._beA;
+ // _beB = iBrother._beB;
+ // _tvertex_iter = iBrother._tvertex_iter;
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else
+ {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+ edge_iterator_base(const edge_iterator_base<edge_const_traits>& iBrother)
+ : parent_class(iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if(_Nature & Nature::T_VERTEX)
+ {
+ // _feA = iBrother._feA;
+ // _feB = iBrother._feB;
+ // _beA = iBrother._beA;
+ // _beB = iBrother._beB;
+ // _tvertex_iter = iBrother._tvertex_iter;
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else
+ {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+ virtual ~edge_iterator_base() {}
+ //protected://FIXME
+ public:
+ // inline edge_iterator_base(value_type ifeA,
+ // value_type ifeB,
+ // value_type ibeA,
+ // value_type ibeB,
+ // value_type iter)
+ // : parent_class()
+ // {
+ // _Nature = Nature::T_VERTEX;
+ // _feA = ifeA;
+ // _feB = ifeB;
+ // _beA = ibeA;
+ // _beB = ibeB;
+ // _tvertex_iter = iter;
+ // }
+ inline edge_iterator_base(edge_pointers_container_iterator begin,
+ edge_pointers_container_iterator end,
+ edge_pointers_container_iterator iter)
+ : parent_class()
+ {
+ _Nature = Nature::T_VERTEX;
+ _tbegin = begin;
+ _tend = end;
+ _tvertex_iter = iter;
+ }
+ inline edge_iterator_base(edges_container_iterator begin,
+ edges_container_iterator end,
+ edges_container_iterator iter)
+ : parent_class()
+ {
+ _Nature = Nature::NON_T_VERTEX;
+ _begin = begin;
+ _end = end;
+ _nontvertex_iter = iter;
+ }
+
+ public:
+
+
+ virtual bool begin() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tbegin);
+ //return (_tvertex_iter == _feA);
+ else
+ return (_nontvertex_iter == _begin);
+ }
+ virtual bool end() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ //return (_tvertex_iter.first == 0);
+ return (_tvertex_iter == _tend);
+ else
+ return (_nontvertex_iter == _end);
+ }
+
+ // operators
+ virtual Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ virtual Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter != b._tvertex_iter);
+ else
+ return (_nontvertex_iter != b._nontvertex_iter);
+ }
+
+ virtual bool operator==(const Self& b) const
+ {return !(*this != b);}
+
+ // dereferencing
+ virtual reference operator*() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ //return _tvertex_iter;
+ return **_tvertex_iter;
+ else
+ return (*_nontvertex_iter);
+ }
+ virtual pointer operator->() const { return &(operator*());}
+
+ protected:
+ inline void increment()
+ {
+ if(_Nature & Nature::T_VERTEX)
+ {
+ value_type tmp = (**_tvertex_iter);
+ ++_tvertex_iter;
+ value_type tmp2 = (**_tvertex_iter);
+ if(tmp2.first == tmp.first)
+ ++_tvertex_iter;
+ // // Hack to deal with cusp. the result of a cusp
+ // // is a TVertex having two identical viewedges.
+ // // In order to iterate properly, we chose to
+ // // to skip these last ones.
+ // if(_feB.first == _beA.first)
+ // {
+ // if(_feA.first == _beB.first)
+ // {
+ // _tvertex_iter.first = 0;
+ // return;
+ // }
+ //
+ // if(_tvertex_iter.first == _feA.first)
+ // _tvertex_iter.first = _beB.first;
+ // else if(_tvertex_iter.first == _beB.first)
+ // _tvertex_iter.first = 0;
+ // else
+ // _tvertex_iter.first = _feA.first;
+ // return;
+ // }
+ // if(_feA.first == _beB.first)
+ // {
+ // if(_feB.first == _beA.first)
+ // {
+ // _tvertex_iter.first = 0;
+ // return;
+ // }
+ //
+ // if(_tvertex_iter.first == _feB.first)
+ // _tvertex_iter.first = _beA.first;
+ // else if(_tvertex_iter.first == _beA.first)
+ // _tvertex_iter.first = 0;
+ // else
+ // _tvertex_iter.first = _feB.first;
+ // return;
+ // }
+ // // End of hack
+ //
+ // if(_tvertex_iter.first == _feA.first){
+ // // we return bea or beb
+ //
+ //
+ // // choose one of them
+ //
+ // _tvertex_iter.first = _feB.first;
+ // return;
+ // }
+ // if(_tvertex_iter.first == _feB.first)
+ // {
+ // _tvertex_iter.first = _beA.first;
+ // return;
+ // }
+ // if(_tvertex_iter.first == _beA.first)
+ // {
+ // _tvertex_iter.first = _beB.first;
+ // return;
+ // }
+ // if(_tvertex_iter.first == _beB.first)
+ // {
+ // _tvertex_iter.first = 0;
+ // return;
+ // }
+ }
+ else
+ ++_nontvertex_iter;
+ }
+ };
+
+ }
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewEdgeInternal {
+
+ /*!----------------------*/
+ /*! Iterators definition */
+ /*!----------------------*/
+ template<class Traits>
+ class edge_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef edge_iterator_base<Traits> Self;
+ public:
+ mutable value_type _ViewEdge;
+ //friend class edge_iterator_base<Nonconst_traits<ViewEdge*> >;
+ //friend class edge_iterator_base<Const_traits<ViewEdge*> >;
+ value_type _first;
+ bool _orientation;
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+
+ public:
+ friend class ViewEdge;
+ inline edge_iterator_base()
+ : parent_class()
+ {_orientation=true;_first=0;}
+
+ inline edge_iterator_base(const edge_iterator_base<Nonconst_traits< ::ViewEdge*> >& iBrother)
+ : parent_class()
+ {
+ _ViewEdge = iBrother._ViewEdge;
+ _first = iBrother._first;
+ _orientation = iBrother._orientation;
+ }
+
+ inline edge_iterator_base(const edge_iterator_base<Const_traits< ::ViewEdge*> >& iBrother)
+ : parent_class()
+ {
+ _ViewEdge = iBrother._ViewEdge;
+ _first = iBrother._first;
+ _orientation = iBrother._orientation;
+ }
+
+ //protected://FIXME
+ public:
+ inline edge_iterator_base(value_type iEdge, bool orientation = true)
+ : parent_class()
+ {
+ _ViewEdge = iEdge;
+ _first = iEdge;
+ _orientation = orientation;
+ }
+
+
+ public:
+ virtual Self* clone() const
+ {
+ return new edge_iterator_base(*this);
+ }
+ virtual ~edge_iterator_base() {}
+
+ public:
+
+ virtual bool orientation() {return _orientation;}
+ virtual void set_edge(value_type iVE) {_ViewEdge=iVE;}
+ virtual void set_orientation(bool iOrientation) {_orientation = iOrientation;}
+ virtual void change_orientation() {_orientation = !_orientation;}
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ //++_ViewEdge->getTimeStamp();
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ //++_ViewEdge->getTimeStamp();
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ //++_ViewEdge->getTimeStamp();
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ //++_ViewEdge->getTimeStamp();
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_ViewEdge != b._ViewEdge);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const {return (_ViewEdge);}
+ virtual pointer operator->() const { return &(operator*());}
+
+ public:
+ virtual bool begin() const {return _ViewEdge==_first ? true : false;}
+ virtual bool end() const {return _ViewEdge==0 ? true : false;}
+
+ protected:
+ virtual void increment() {}
+ virtual void decrement() {}
+ };
+
+ template<class Traits>
+ class fedge_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef fedge_iterator_base<Traits> Self;
+ public:
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ mutable value_type _FEdge;
+ value_type _first;
+ value_type _FEdgeB; // last fedge of the view edge
+
+ public:
+ friend class ::ViewEdge;
+ friend class fedge_iterator;
+ inline fedge_iterator_base()
+ : parent_class()
+ {}
+ inline fedge_iterator_base(const fedge_iterator_base<Nonconst_traits<FEdge*> >& iBrother)
+ : parent_class()
+ {
+ _FEdge = iBrother._FEdge;
+ _first = iBrother._first;
+ _FEdgeB = iBrother._FEdgeB;
+ }
+ inline fedge_iterator_base(const fedge_iterator_base<Const_traits<FEdge*> >& iBrother)
+ : parent_class()
+ {
+ _FEdge = iBrother._FEdge;
+ _first = iBrother._first;
+ _FEdgeB = iBrother._FEdgeB;
+ }
+ //protected://FIXME
+ public:
+ inline fedge_iterator_base(value_type iEdge, value_type iFEdgeB)
+ : parent_class()
+ {
+ _FEdge = iEdge;
+ _first = iEdge;
+ _FEdgeB = iFEdgeB;
+ }
+
+ public:
+ virtual ~fedge_iterator_base() {}
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_FEdge != b._FEdge);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const {return (_FEdge);}
+ virtual pointer operator->() const { return &(operator*());}
+
+
+ public:
+ virtual bool begin() const {return _FEdge==_first ? true : false;}
+ virtual bool end() const {return _FEdge==0 ? true : false;}
+ protected:
+ virtual void increment()
+ {
+ _FEdge = _FEdge->nextEdge(); // we don't change or
+ }
+
+ virtual void decrement()
+ {
+ if(0 == _FEdge)
+ {
+ _FEdge = _FEdgeB;
+ return;
+ }
+ _FEdge = _FEdge->previousEdge(); // we don't change or
+ }
+ };
+
+ template<class Traits>
+ class vertex_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+ typedef vertex_iterator_base<Traits> Self;
+ protected:
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ public:
+ mutable value_type _SVertex;
+ FEdge *_NextFEdge;
+ FEdge *_PreviousFEdge;
+ public:
+ friend class ViewEdge;
+ friend class vertex_iterator;
+ inline vertex_iterator_base()
+ : parent_class()
+ {}
+ inline vertex_iterator_base(const vertex_iterator_base<Const_traits<SVertex*> >& iBrother)
+ : parent_class()
+ {
+ _SVertex = iBrother._SVertex;
+ _NextFEdge = iBrother._NextFEdge;
+ _PreviousFEdge = iBrother._PreviousFEdge;
+ }
+ inline vertex_iterator_base(const vertex_iterator_base<Nonconst_traits<SVertex*> >& iBrother)
+ : parent_class()
+ {
+ _SVertex = iBrother._SVertex;
+ _NextFEdge = iBrother._NextFEdge;
+ _PreviousFEdge = iBrother._PreviousFEdge;
+ }
+
+ //protected://FIXME
+ public:
+
+ inline vertex_iterator_base(value_type iVertex, FEdge *iPreviousFEdge, FEdge *iNextFEdge)
+ : parent_class()
+ {
+ _SVertex = iVertex;
+ _NextFEdge = iNextFEdge;
+ _PreviousFEdge = iPreviousFEdge;
+ }
+
+ public:
+ virtual ~vertex_iterator_base() {}
+
+ virtual bool begin() const {return _PreviousFEdge==0? true : false;}
+ virtual bool end() const {return _SVertex==0 ? true : false;}
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+ inline Self operator--(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ decrement(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_SVertex != b._SVertex);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual reference operator*() const {return (_SVertex);}
+ virtual pointer operator->() const { return &(operator*());}
+
+ protected:
+ virtual void increment()
+ {
+ if(0 == _NextFEdge)
+ {
+ _SVertex = 0;
+ return;
+ }
+
+ _SVertex = _NextFEdge->vertexB();
+ _PreviousFEdge = _NextFEdge;
+ _NextFEdge = _NextFEdge->nextEdge();
+
+ }
+ virtual void decrement()
+ {
+ // if(0 == _SVertex)
+ // {
+ // _SVertex = _PreviousFEdge->vertexB();
+ // return;
+ // }
+ if(0 == _PreviousFEdge)
+ {
+ _SVertex = 0;
+ return;
+ }
+ _SVertex = _PreviousFEdge->vertexA();
+ _NextFEdge = _PreviousFEdge;
+ _PreviousFEdge = _PreviousFEdge->previousEdge();
+ }
+ };
+
+
+} // end of namespace ViewEdgeInternal
+
+#endif // VIEWMAPADVANCEDITERATORS_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
new file mode 100755
index 00000000000..32f5283a63c
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -0,0 +1,1027 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <algorithm>
+#include "ViewMapBuilder.h"
+
+using namespace std;
+
+ViewMap* ViewMapBuilder::BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon) {
+ _ViewMap = new ViewMap;
+ _currentId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+
+ // Builds initial view edges
+ computeInitialViewEdges(we);
+
+ // Detects cusps
+ computeCusps(_ViewMap);
+
+ // Compute intersections
+ ComputeIntersections(_ViewMap, sweep_line, epsilon);
+
+ // Compute visibility
+ ComputeEdgesVisibility(_ViewMap, iAlgo, _Grid, epsilon);
+
+ return _ViewMap;
+}
+
+void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we)
+{
+ vector<WShape*> wshapes = we.getWShapes();
+ SShape* psShape;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++) {
+ // create the embedding
+ psShape = new SShape;
+ psShape->SetId((*it)->GetId());
+ psShape->SetMaterials((*it)->materials()); // FIXME
+
+ // create the view shape
+ ViewShape * vshape = new ViewShape(psShape);
+ // add this view shape to the view map:
+ _ViewMap->AddViewShape(vshape);
+
+ _pViewEdgeBuilder->SetCurrentViewId(_currentId); // we want to number the view edges in a unique way for the while scene.
+ _pViewEdgeBuilder->SetCurrentFId(_currentFId); // we want to number the feature edges in a unique way for the while scene.
+ _pViewEdgeBuilder->SetCurrentSVertexId(_currentFId); // we want to number the SVertex in a unique way for the while scene.
+ _pViewEdgeBuilder->BuildViewEdges(dynamic_cast<WXShape*>(*it), vshape,
+ _ViewMap->ViewEdges(),
+ _ViewMap->ViewVertices(),
+ _ViewMap->FEdges(),
+ _ViewMap->SVertices());
+
+ _currentId = _pViewEdgeBuilder->currentViewId()+1;
+ _currentFId = _pViewEdgeBuilder->currentFId()+1;
+ _currentSVertexId = _pViewEdgeBuilder->currentSVertexId()+1;
+
+ psShape->ComputeBBox();
+ }
+}
+
+void ViewMapBuilder::computeCusps(ViewMap *ioViewMap){
+ vector<ViewVertex*> newVVertices;
+ vector<ViewEdge*> newVEdges;
+ ViewMap::viewedges_container& vedges = ioViewMap->ViewEdges();
+ ViewMap::viewedges_container::iterator ve=vedges.begin(), veend=vedges.end();
+ for(;
+ ve!=veend;
+ ++ve){
+ if((!((*ve)->getNature() & Nature::SILHOUETTE)) || (!((*ve)->fedgeA()->isSmooth())))
+ continue;
+ FEdge *fe = (*ve)->fedgeA();
+ FEdge * fefirst = fe;
+ bool first = true;
+ bool positive = true;
+ do{
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ Vec3r A((fes)->vertexA()->point3d());
+ Vec3r B((fes)->vertexB()->point3d());
+ Vec3r AB(B-A);
+ AB.normalize();
+ Vec3r m((A+B)/2.0);
+ Vec3r crossP(AB^(fes)->normal());
+ crossP.normalize();
+ Vec3r viewvector(m-_viewpoint);
+ viewvector.normalize();
+ if(first){
+ if(((crossP)*(viewvector)) > 0)
+ positive = true;
+ else
+ positive = false;
+ first = false;
+ }
+ // If we're in a positive part, we need
+ // a stronger negative value to change
+ NonTVertex *cusp = 0;
+ if(positive){
+ if(((crossP)*(viewvector)) < -0.1){
+ // state changes
+ positive = false;
+ // creates and insert cusp
+ cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges));
+ if(cusp!=0)
+ cusp->setNature(cusp->getNature()|Nature::CUSP);
+ }
+
+ }else{
+ // If we're in a negative part, we need
+ // a stronger negative value to change
+ if(((crossP)*(viewvector)) > 0.1){
+ positive = true;
+ cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges));
+ if(cusp!=0)
+ cusp->setNature(cusp->getNature()|Nature::CUSP);
+ }
+ }
+ fe = fe->nextEdge();
+ }while((fe!=0) && (fe!=fefirst));
+ }
+ for(ve=newVEdges.begin(), veend=newVEdges.end();
+ ve!=veend;
+ ++ve){
+ (*ve)->viewShape()->AddEdge(*ve);
+ vedges.push_back(*ve);
+ }
+}
+void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, visibility_algo iAlgo, Grid *iGrid, real epsilon)
+{
+ if((iAlgo == ray_casting ||
+ iAlgo == ray_casting_fast ||
+ iAlgo == ray_casting_very_fast) && (NULL == iGrid))
+ {
+ cerr << "Error: can't cast ray, no grid defined" << endl;
+ return;
+ }
+
+ switch(iAlgo)
+ {
+ case ray_casting:
+ ComputeRayCastingVisibility(ioViewMap, iGrid, epsilon);
+ break;
+ case ray_casting_fast:
+ ComputeFastRayCastingVisibility(ioViewMap, iGrid, epsilon);
+ break;
+ case ray_casting_very_fast:
+ ComputeVeryFastRayCastingVisibility(ioViewMap, iGrid, epsilon);
+ break;
+ default:
+ break;
+ }
+}
+
+static const unsigned gProgressBarMaxSteps = 10;
+static const unsigned gProgressBarMinSize = 2000;
+
+void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, Grid* iGrid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge * fe, *festart;
+ int nSamples = 0;
+ vector<Polygon3r*> aFaces;
+ Polygon3r *aFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ static unsigned timestamp = 1;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 1;
+ do {
+ qiMajority++;
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ qiMajority >>= 1;
+
+ tmpQI = 0;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ fe = (*ve)->fedgeA();
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ set<ViewShape*> occluders;
+ do
+ {
+ if((maxCard < qiMajority)) {
+ tmpQI = ComputeRayCastingVisibility(fe, iGrid, epsilon, occluders, &aFace, timestamp++);
+
+ if(tmpQI >= 256)
+ cerr << "Warning: too many occluding levels" << endl;
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else
+ FindOccludee(fe, iGrid, epsilon, &aFace, timestamp++);
+
+ if(aFace) {
+ fe->SetaFace(*aFace);
+ aFaces.push_back(aFace);
+ fe->SetOccludeeEmpty(false);
+ }
+ else
+ fe->SetOccludeeEmpty(true);
+
+ ++nSamples;
+ fe = fe->nextEdge();
+ }
+ while((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+
+ // ViewEdge
+ // qi --
+ (*ve)->SetQI(maxIndex);
+ // occluders --
+ for(set<ViewShape*>::iterator o=occluders.begin(), oend=occluders.end();
+ o!=oend;
+ ++o)
+ (*ve)->AddOccluder((*o));
+ // occludee --
+ if(!aFaces.empty())
+ {
+ if(aFaces.size() <= (float)nSamples/2.f)
+ {
+ (*ve)->SetaShape(0);
+ }
+ else
+ {
+ vector<Polygon3r*>::iterator p = aFaces.begin();
+ WFace * wface = (WFace*)((*p)->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ ++p;
+ (*ve)->SetaShape(vshape);
+ }
+ }
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ aFaces.clear();
+ }
+}
+
+void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, Grid* iGrid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge * fe, *festart;
+ unsigned nSamples = 0;
+ vector<Polygon3r*> aFaces;
+ Polygon3r *aFace = 0;
+ unsigned tmpQI = 0;
+ unsigned qiClasses[256];
+ unsigned maxIndex, maxCard;
+ unsigned qiMajority;
+ static unsigned timestamp = 1;
+ bool even_test;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ festart = (*ve)->fedgeA();
+ fe = (*ve)->fedgeA();
+ qiMajority = 1;
+ do {
+ qiMajority++;
+ fe = fe->nextEdge();
+ } while (fe && fe != festart);
+ if (qiMajority >= 4)
+ qiMajority >>= 2;
+ else
+ qiMajority = 1;
+
+ set<ViewShape*> occluders;
+
+ even_test = true;
+ maxIndex = 0;
+ maxCard = 0;
+ nSamples = 0;
+ memset(qiClasses, 0, 256 * sizeof(*qiClasses));
+ fe = (*ve)->fedgeA();
+ do
+ {
+ if (even_test)
+ {
+ if((maxCard < qiMajority)) {
+ tmpQI = ComputeRayCastingVisibility(fe, iGrid, epsilon, occluders, &aFace, timestamp++);
+
+ if(tmpQI >= 256)
+ cerr << "Warning: too many occluding levels" << endl;
+
+ if (++qiClasses[tmpQI] > maxCard) {
+ maxCard = qiClasses[tmpQI];
+ maxIndex = tmpQI;
+ }
+ }
+ else
+ FindOccludee(fe, iGrid, epsilon, &aFace, timestamp++);
+
+ if(aFace)
+ {
+ fe->SetaFace(*aFace);
+ aFaces.push_back(aFace);
+ }
+ ++nSamples;
+ even_test = false;
+ }
+ else
+ even_test = true;
+ fe = fe->nextEdge();
+ } while ((maxCard < qiMajority) && (0!=fe) && (fe!=festart));
+
+ (*ve)->SetQI(maxIndex);
+
+ if(!aFaces.empty())
+ {
+ if(aFaces.size() < nSamples / 2)
+ {
+ (*ve)->SetaShape(0);
+ }
+ else
+ {
+ vector<Polygon3r*>::iterator p = aFaces.begin();
+ WFace * wface = (WFace*)((*p)->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ ++p;
+ // for(;
+ // p!=pend;
+ // ++p)
+ // {
+ // WFace *f = (WFace*)((*p)->userdata);
+ // ViewShape *vs = ioViewMap->viewShape(f->GetVertex(0)->shape()->GetId());
+ // if(vs != vshape)
+ // {
+ // sameShape = false;
+ // break;
+ // }
+ // }
+ // if(sameShape)
+ (*ve)->SetaShape(vshape);
+ }
+ }
+
+ //(*ve)->SetaFace(aFace);
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ aFaces.clear();
+ }
+}
+
+void ViewMapBuilder::ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, Grid* iGrid, real epsilon)
+{
+ vector<ViewEdge*>& vedges = ioViewMap->ViewEdges();
+ bool progressBarDisplay = false;
+ unsigned progressBarStep = 0;
+ unsigned vEdgesSize = vedges.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize);
+ progressBarStep = vEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Ray casting Visibility");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+ FEdge* fe;
+ unsigned qi = 0;
+ Polygon3r *aFace = 0;
+ static unsigned timestamp = 1;
+ for(vector<ViewEdge*>::iterator ve=vedges.begin(), veend=vedges.end();
+ ve!=veend;
+ ve++)
+ {
+ set<ViewShape*> occluders;
+
+ fe = (*ve)->fedgeA();
+ qi = ComputeRayCastingVisibility(fe, iGrid, epsilon, occluders, &aFace, timestamp++);
+ if(aFace)
+ {
+ fe->SetaFace(*aFace);
+ WFace * wface = (WFace*)(aFace->userdata);
+ ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId());
+ (*ve)->SetaShape(vshape);
+ }
+ else
+ {
+ (*ve)->SetaShape(0);
+ }
+
+ (*ve)->SetQI(qi);
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ }
+}
+
+
+void ViewMapBuilder::FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices)
+{
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ OccludersSet occluders;
+ WFace * oface;
+ bool skipFace;
+
+ WVertex::incoming_edge_iterator ie;
+ OccludersSet::iterator p, pend;
+
+ *oaPolygon = 0;
+ if(((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER))
+ {
+ occluders.clear();
+ // we cast a ray from A in the same direction but looking behind
+ Vec3r v(-u[0],-u[1],-u[2]);
+ iGrid->castInfiniteRay(A, v, occluders, timestamp);
+
+ bool noIntersection = true;
+ real mint=FLT_MAX;
+ // we met some occluders, let us fill the aShape field
+ // with the first intersected occluder
+ for(p=occluders.begin(),pend=occluders.end();
+ p!=pend;
+ p++)
+ {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ oface = (WFace*)(*p)->userdata;
+ Vec3r v1(((*p)->getVertices())[0]);
+ Vec3r normal((*p)->getNormal());
+ real d = -(v1 * normal);
+ real t,t_u,t_v;
+
+ if(0 != face)
+ {
+ skipFace = false;
+
+ if(face == oface)
+ continue;
+
+ if(faceVertices.empty())
+ continue;
+
+ for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end();
+ fv!=fvend;
+ ++fv)
+ {
+ if((*fv)->isBoundary())
+ continue;
+ WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end();
+ for(ie=iebegin;ie!=ieend; ++ie)
+ {
+ if((*ie) == 0)
+ continue;
+
+ WFace * sface = (*ie)->GetbFace();
+ if(sface == oface)
+ {
+ skipFace = true;
+ break;
+ }
+ }
+ if(skipFace)
+ break;
+ }
+ if(skipFace)
+ continue;
+ }
+ else
+ {
+ if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon))
+ continue;
+ }
+ if((*p)->rayIntersect(A, v, t,t_u,t_v))
+ {
+ if (fabs(v * normal) > 0.0001)
+ if ((t>0.0)) // && (t<1.0))
+ {
+ if (t<mint)
+ {
+ *oaPolygon = (*p);
+ mint = t;
+ noIntersection = false;
+ fe->SetOccludeeIntersection(Vec3r(A+t*v));
+ }
+ }
+ }
+ }
+
+ if(noIntersection)
+ *oaPolygon = 0;
+ }
+}
+
+void ViewMapBuilder::FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp)
+{
+ OccludersSet occluders;
+
+ Vec3r A;
+ Vec3r edge;
+ Vec3r origin;
+ A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D())/2.0);
+ edge = Vec3r((fe)->vertexB()->point3D()-(fe)->vertexA()->point3D());
+ origin = Vec3r((fe)->vertexA()->point3D());
+ Vec3r u(_viewpoint-A);
+ u.normalize();
+ if(A < iGrid->getOrigin())
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId().getFirst() << "-" << fe->getId().getSecond() << endl;
+
+ vector<WVertex*> faceVertices;
+
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ if(0 != face)
+ face->RetrieveVertexList(faceVertices);
+
+ return FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp,
+ u, A, origin, edge, faceVertices);
+}
+
+int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set<ViewShape*>& oOccluders,
+ Polygon3r** oaPolygon, unsigned timestamp)
+{
+ OccludersSet occluders;
+ int qi = 0;
+
+ Vec3r center;
+ Vec3r edge;
+ Vec3r origin;
+
+ center = fe->center3d();
+ edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D());
+ origin = Vec3r(fe->vertexA()->point3D());
+ //
+ // // Is the edge outside the view frustum ?
+ Vec3r gridOrigin(iGrid->getOrigin());
+ Vec3r gridExtremity(iGrid->getOrigin()+iGrid->gridSize());
+
+ if( (center.x() < gridOrigin.x()) || (center.y() < gridOrigin.y()) || (center.z() < gridOrigin.z())
+ ||(center.x() > gridExtremity.x()) || (center.y() > gridExtremity.y()) || (center.z() > gridExtremity.z())){
+ cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl;
+ //return 0;
+ }
+
+
+ // Vec3r A(fe->vertexA()->point2d());
+ // Vec3r B(fe->vertexB()->point2d());
+ // int viewport[4];
+ // SilhouetteGeomEngine::retrieveViewport(viewport);
+ // if( (A.x() < viewport[0]) || (A.x() > viewport[2]) || (A.y() < viewport[1]) || (A.y() > viewport[3])
+ // ||(B.x() < viewport[0]) || (B.x() > viewport[2]) || (B.y() < viewport[1]) || (B.y() > viewport[3])){
+ // cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl;
+ // //return 0;
+ // }
+
+ Vec3r u(_viewpoint - center);
+ real raylength = u.norm();
+ u.normalize();
+ //cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," << iGrid->getOrigin().z() << endl;
+ //cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl;
+
+ iGrid->castRay(center, Vec3r(_viewpoint), occluders, timestamp);
+
+ WFace *face = 0;
+ if(fe->isSmooth()){
+ FEdgeSmooth * fes = dynamic_cast<FEdgeSmooth*>(fe);
+ face = (WFace*)fes->face();
+ }
+ vector<WVertex*> faceVertices;
+ WVertex::incoming_edge_iterator ie;
+
+ WFace * oface;
+ bool skipFace;
+ OccludersSet::iterator p, pend;
+ if(face)
+ face->RetrieveVertexList(faceVertices);
+
+ for(p=occluders.begin(),pend=occluders.end();
+ p!=pend;
+ p++)
+ {
+ // If we're dealing with an exact silhouette, check whether
+ // we must take care of this occluder of not.
+ // (Indeed, we don't consider the occluders that
+ // share at least one vertex with the face containing
+ // this edge).
+ //-----------
+ oface = (WFace*)(*p)->userdata;
+ Vec3r v1(((*p)->getVertices())[0]);
+ Vec3r normal((*p)->getNormal());
+ real d = -(v1 * normal);
+ real t, t_u, t_v;
+
+ if(0 != face)
+ {
+ skipFace = false;
+
+ if(face == oface)
+ continue;
+
+
+ for(vector<WVertex*>::iterator fv=faceVertices.begin(), fvend=faceVertices.end();
+ fv!=fvend;
+ ++fv)
+ {
+ if((*fv)->isBoundary())
+ continue;
+
+ WVertex::incoming_edge_iterator iebegin=(*fv)->incoming_edges_begin();
+ WVertex::incoming_edge_iterator ieend=(*fv)->incoming_edges_end();
+ for(ie=iebegin;ie!=ieend; ++ie)
+ {
+ if((*ie) == 0)
+ continue;
+
+ WFace * sface = (*ie)->GetbFace();
+ //WFace * sfacea = (*ie)->GetaFace();
+ //if((sface == oface) || (sfacea == oface))
+ if(sface == oface)
+ {
+ skipFace = true;
+ break;
+ }
+ }
+ if(skipFace)
+ break;
+ }
+ if(skipFace)
+ continue;
+ }
+ else
+ {
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+
+ if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon))
+ continue;
+ }
+
+ if((*p)->rayIntersect(center, u, t, t_u, t_v))
+ {
+ if (fabs(u * normal) > 0.0001)
+ if ((t>0.0) && (t<raylength))
+ {
+ WFace *f = (WFace*)((*p)->userdata);
+ ViewShape *vshape = _ViewMap->viewShape(f->GetVertex(0)->shape()->GetId());
+ oOccluders.insert(vshape);
+ ++qi;
+ if(!_EnableQI)
+ break;
+ }
+ }
+ }
+
+ // Find occludee
+ FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp,
+ u, center, edge, origin, faceVertices);
+
+ return qi;
+}
+
+void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo, real epsilon)
+{
+ switch(iAlgo)
+ {
+ case sweep_line:
+ ComputeSweepLineIntersections(ioViewMap, epsilon);
+ break;
+ default:
+ break;
+ }
+ ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices();
+ for(ViewMap::viewvertices_container::iterator vv=vvertices.begin(), vvend=vvertices.end();
+ vv!=vvend;
+ ++vv)
+ {
+ if((*vv)->getNature() == Nature::T_VERTEX)
+ {
+ TVertex *tvertex = (TVertex*)(*vv);
+ cout << "TVertex " << tvertex->getId() << " has :" << endl;
+ cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl;
+ cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl;
+ cout << "BackEdgeA: " << tvertex->backEdgeA().first << endl;
+ cout << "BackEdgeB: " << tvertex->backEdgeB().first << endl << endl;
+ }
+ }
+}
+
+struct less_SVertex2D : public binary_function<SVertex*, SVertex*, bool>
+{
+ real epsilon;
+ less_SVertex2D(real eps)
+ : binary_function<SVertex*,SVertex*,bool>()
+ {
+ epsilon = eps;
+ }
+ bool operator()(SVertex* x, SVertex* y)
+ {
+ Vec3r A = x->point2D();
+ Vec3r B = y->point2D();
+ for(unsigned int i=0; i<3; i++)
+ {
+ if((fabs(A[i] - B[i])) < epsilon)
+ continue;
+ if(A[i] < B[i])
+ return true;
+ if(A[i] > B[i])
+ return false;
+ }
+
+ return false;
+ }
+};
+
+typedef Segment<FEdge*,Vec3r > segment;
+typedef Intersection<segment> intersection;
+
+struct less_Intersection : public binary_function<intersection*, intersection*, bool>
+{
+ segment *edge;
+ less_Intersection(segment *iEdge)
+ : binary_function<intersection*,intersection*,bool>()
+ {
+ edge = iEdge;
+ }
+ bool operator()(intersection* x, intersection* y)
+ {
+ real tx = x->getParameter(edge);
+ real ty = y->getParameter(edge);
+ if(tx > ty)
+ return true;
+ return false;
+ }
+};
+
+struct silhouette_binary_rule : public binary_rule<segment,segment>
+{
+ silhouette_binary_rule() : binary_rule<segment,segment>() {}
+ virtual bool operator() (segment& s1, segment& s2)
+ {
+ FEdge * f1 = s1.edge();
+ FEdge * f2 = s2.edge();
+
+ if((!(((f1)->getNature() & Nature::SILHOUETTE) || ((f1)->getNature() & Nature::BORDER))) && (!(((f2)->getNature() & Nature::SILHOUETTE) || ((f2)->getNature() & Nature::BORDER))))
+ return false;
+
+ return true;
+ }
+};
+
+void ViewMapBuilder::ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon)
+{
+ vector<SVertex*>& svertices = ioViewMap->SVertices();
+ bool progressBarDisplay = false;
+ unsigned sVerticesSize = svertices.size();
+ unsigned fEdgesSize = ioViewMap->FEdges().size();
+ // ViewMap::fedges_container& fedges = ioViewMap->FEdges();
+ // for(ViewMap::fedges_container::const_iterator f=fedges.begin(), end=fedges.end();
+ // f!=end;
+ // ++f){
+ // cout << (*f)->aMaterialIndex() << "-" << (*f)->bMaterialIndex() << endl;
+ // }
+
+ unsigned progressBarStep = 0;
+
+ if(_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) {
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, sVerticesSize);
+ progressBarStep = sVerticesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Computing Sweep Line Intersections");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ progressBarDisplay = true;
+ }
+
+ unsigned counter = progressBarStep;
+
+ sort(svertices.begin(), svertices.end(), less_SVertex2D(epsilon));
+
+ SweepLine<FEdge*,Vec3r> SL;
+
+ vector<FEdge*>& ioEdges = ioViewMap->FEdges();
+
+ vector<segment* > segments;
+
+ vector<FEdge*>::iterator fe,fend;
+
+ for(fe=ioEdges.begin(), fend=ioEdges.end();
+ fe!=fend;
+ fe++)
+ {
+ segment * s = new segment((*fe), (*fe)->vertexA()->point2D(), (*fe)->vertexB()->point2D());
+ (*fe)->userdata = s;
+ segments.push_back(s);
+ }
+
+ vector<segment*> vsegments;
+ for(vector<SVertex*>::iterator sv=svertices.begin(),svend=svertices.end();
+ sv!=svend;
+ sv++)
+ {
+ const vector<FEdge*>& vedges = (*sv)->fedges();
+
+ for(vector<FEdge*>::const_iterator sve=vedges.begin(), sveend=vedges.end();
+ sve!=sveend;
+ sve++)
+ {
+ vsegments.push_back((segment*)((*sve)->userdata));
+ }
+
+ Vec3r evt((*sv)->point2D());
+ silhouette_binary_rule sbr;
+ SL.process(evt, vsegments, sbr);
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ vsegments.clear();
+ }
+
+ // reset userdata:
+ for(fe=ioEdges.begin(), fend=ioEdges.end();
+ fe!=fend;
+ fe++)
+ (*fe)->userdata = NULL;
+
+ // list containing the new edges resulting from splitting operations.
+ vector<FEdge*> newEdges;
+
+ // retrieve the intersected edges:
+ vector<segment* >& iedges = SL.intersectedEdges();
+ // retrieve the intersections:
+ vector<intersection*>& intersections = SL.intersections();
+
+ int id=0;
+ // create a view vertex for each intersection and linked this one
+ // with the intersection object
+ vector<intersection*>::iterator i, iend;
+ for(i=intersections.begin(),iend=intersections.end();
+ i!=iend;
+ i++)
+ {
+ FEdge *fA = (*i)->EdgeA->edge();
+ FEdge *fB = (*i)->EdgeB->edge();
+
+ Vec3r A1 = fA->vertexA()->point3D();
+ Vec3r A2 = fA->vertexB()->point3D();
+ Vec3r B1 = fB->vertexA()->point3D();
+ Vec3r B2 = fB->vertexB()->point3D();
+
+ Vec3r a1 = fA->vertexA()->point2D();
+ Vec3r a2 = fA->vertexB()->point2D();
+ Vec3r b1 = fB->vertexA()->point2D();
+ Vec3r b2 = fB->vertexB()->point2D();
+
+ real ta = (*i)->tA;
+ real tb = (*i)->tB;
+
+ if((ta < -epsilon) || (ta > 1+epsilon))
+ cerr << "Warning: intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl;
+
+ if((tb < -epsilon) || (tb > 1+epsilon))
+ cerr << "Warning: intersection out of range for edge " << fB->vertexA()->getId() << " - " << fB->vertexB()->getId() << endl;
+
+ real Ta = SilhouetteGeomEngine::ImageToWorldParameter(fA, ta);
+ real Tb = SilhouetteGeomEngine::ImageToWorldParameter(fB, tb);
+
+ TVertex * tvertex = ioViewMap->CreateTVertex(Vec3r(A1 + Ta*(A2-A1)), Vec3r(a1 + ta*(a2-a1)), fA,
+ Vec3r(B1 + Tb*(B2-B1)), Vec3r(b1 + tb*(b2-b1)), fB, id);
+
+ (*i)->userdata = tvertex;
+ ++id;
+ }
+
+ progressBarStep = 0;
+
+ if(progressBarDisplay) {
+ unsigned iEdgesSize = iedges.size();
+ unsigned progressBarSteps = min(gProgressBarMaxSteps, iEdgesSize);
+ progressBarStep = iEdgesSize / progressBarSteps;
+ _pProgressBar->reset();
+ _pProgressBar->setLabelText("Splitting intersected edges");
+ _pProgressBar->setTotalSteps(progressBarSteps);
+ _pProgressBar->setProgress(0);
+ }
+
+ counter = progressBarStep;
+
+ vector<TVertex*> edgeVVertices;
+ vector<ViewEdge*> newVEdges;
+ vector<segment* >::iterator s, send;
+ for(s=iedges.begin(),send=iedges.end();
+ s!=send;
+ s++)
+ {
+ edgeVVertices.clear();
+ newEdges.clear();
+ newVEdges.clear();
+
+ FEdge* fedge = (*s)->edge();
+ ViewEdge *vEdge = fedge->viewedge();
+ ViewShape *shape = vEdge->viewShape();
+
+ vector<intersection*>& eIntersections = (*s)->intersections();
+ // we first need to sort these intersections from farther to closer to A
+ sort(eIntersections.begin(), eIntersections.end(), less_Intersection(*s));
+ for(i=eIntersections.begin(),iend=eIntersections.end();
+ i!=iend;
+ i++)
+ edgeVVertices.push_back((TVertex*)(*i)->userdata);
+
+ shape->SplitEdge(fedge, edgeVVertices, ioViewMap->FEdges(), ioViewMap->ViewEdges());
+
+ if(progressBarDisplay) {
+ counter--;
+ if (counter <= 0) {
+ counter = progressBarStep;
+ _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
+ }
+ }
+ }
+
+ // reset userdata:
+ for(fe=ioEdges.begin(), fend=ioEdges.end();
+ fe!=fend;
+ fe++)
+ (*fe)->userdata = NULL;
+
+ // delete segments
+ // if(!segments.empty()){
+ // for(s=segments.begin(),send=segments.end();
+ // s!=send;
+ // s++){
+ // delete *s;
+ // }
+ // segments.clear();
+ // }
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
new file mode 100755
index 00000000000..ec52d4fdd7e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
@@ -0,0 +1,224 @@
+//
+// Filename : ViewMapBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build silhouette edges from a
+// Winged-Edge structure
+// Date of creation : 25/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPBUILDER_H
+# define VIEWMAPBUILDER_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../winged_edge/WXEdge.h"
+# include "Silhouette.h"
+# include "../geometry/GeomUtils.h"
+# include "../geometry/Grid.h"
+# include "../system/ProgressBar.h"
+# include "../geometry/SweepLine.h"
+# include "ViewMap.h"
+# include "SilhouetteGeomEngine.h"
+# include "../scene_graph/TriangleRep.h"
+# include "../winged_edge/WEdge.h"
+# include "ViewEdgeXBuilder.h"
+
+
+using namespace Geometry;
+
+class LIB_VIEW_MAP_EXPORT ViewMapBuilder
+{
+private:
+
+ ViewMap * _ViewMap; // result
+ //SilhouetteGeomEngine _GeomEngine;
+ ProgressBar *_pProgressBar;
+ Vec3r _viewpoint;
+ Grid* _Grid;
+ ViewEdgeXBuilder *_pViewEdgeBuilder;
+ bool _EnableQI;
+ double _epsilon;
+
+ // tmp values:
+ int _currentId;
+ int _currentFId;
+ int _currentSVertexId;
+
+
+public:
+
+ typedef enum {
+ sweep_line
+ } intersection_algo;
+
+ typedef enum {
+ ray_casting,
+ ray_casting_fast,
+ ray_casting_very_fast
+ } visibility_algo;
+
+ inline ViewMapBuilder()
+ {
+ _pProgressBar = 0;
+ _Grid = 0;
+ _currentId = 1;
+ _currentFId = 0;
+ _currentSVertexId = 0;
+ _pViewEdgeBuilder = new ViewEdgeXBuilder;
+ _EnableQI = true;
+ }
+
+ inline ~ViewMapBuilder()
+ {
+ if(_pViewEdgeBuilder){
+ delete _pViewEdgeBuilder;
+ _pViewEdgeBuilder = 0;
+ }
+ }
+
+ /*! Compute Shapes from a WingedEdge containing a list of WShapes */
+ void computeInitialViewEdges(WingedEdge&);
+
+ /*! Compute Cusps */
+ void computeCusps(ViewMap *ioViewMap);
+ /*! Detects cusps (for a single ViewEdge) among SVertices and builds a ViewVertex on top of
+ * each cusp SVertex
+ * We use a hysteresis approach to avoid noise.
+ */
+ void DetectCusps(ViewEdge *ioEdge);
+
+
+ /*! Sets the current viewpoint */
+ inline void SetViewpoint(const Vec3r& ivp) {_viewpoint = ivp; SilhouetteGeomEngine::SetViewpoint(ivp);}
+
+ /*! Sets the current transformation
+ * iModelViewMatrix
+ * The 4x4 model view matrix, in column major order (openGL like).
+ * iProjection matrix
+ * The 4x4 projection matrix, in column major order (openGL like).
+ * iViewport
+ * The viewport. 4 real array: origin.x, origin.y, width, length
+ */
+ inline void SetTransform(const real iModelViewMatrix[4][4],
+ const real iProjectionMatrix[4][4],
+ const int iViewport[4],
+ real iFocalLength,
+ real iAspect,
+ real iFovy) {
+ SilhouetteGeomEngine::SetTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength);
+ }
+
+ inline void SetFrustum(real iZnear, real iZfar) {
+ SilhouetteGeomEngine::SetFrustum(iZnear, iZfar);
+ }
+
+ /*! Builds the scene view map
+ * returns the list the view map
+ * it is up to the caller to delete this ViewMap
+ * iWRoot
+ * The root group node containing the WEdge structured scene
+ */
+
+ ViewMap* BuildViewMap(WingedEdge& we, visibility_algo iAlgo = ray_casting, real epsilon=1e-06) ;
+ /*! computes the intersection between all 2D
+ * feature edges of the scene.
+ * ioViewMap
+ * The view map. It is modified by the method.
+ * The list of all features edges of the scene.
+ * Each time an intersection is found, the 2 intersecting
+ * edges are splitted (creating 2 new vertices)
+ * At the end, this list is updated with the adding
+ * of all new created edges (resulting from splitting).
+ * iAlgo
+ * The algo to use for computing the intersections
+ */
+ void ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo = sweep_line, real epsilon=1e-06);
+
+ /*! Computes the 2D scene silhouette edges visibility
+ * iGrid
+ * For the Ray Casting algorithm.
+ */
+ void ComputeEdgesVisibility(ViewMap *ioViewMap, visibility_algo iAlgo= ray_casting, Grid* iGrid = 0, real epsilon=1e-6);
+
+ void SetGrid(Grid *iGrid) {_Grid = iGrid;}
+
+ /*! accessors */
+
+ /*! Modifiers */
+ inline void SetProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;}
+ inline void SetEnableQI(bool iBool) {_EnableQI = iBool;}
+
+protected:
+
+ /*! Computes intersections on all edges of the scene using a sweep line
+ * algorithm*/
+ void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1e-6);
+
+ /*! Computes the 2D scene silhouette edges visibility
+ * using a ray casting. On each edge, a ray is cast
+ * to check its quantitative invisibility. The list
+ * of occluders are each time stored in the tested edge.
+ * ioViewMap
+ * The view map.
+ * The 2D scene silhouette edges as FEdges.
+ * These edges have already been splitted at their intersections points.
+ * Thus, these edges do not intersect anymore.
+ * The visibility corresponding to each edge of ioScene is set is this
+ * edge.
+ */
+ void ComputeRayCastingVisibility(ViewMap *ioViewMap, Grid *iGrid, real epsilon=1e-6);
+ void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, Grid *iGrid, real epsilon=1e-6);
+ void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, Grid *iGrid, real epsilon=1e-6);
+
+ /*! Compute the visibility for the FEdge fe.
+ * The occluders are added to fe occluders list.
+ * fe
+ * The FEdge
+ * iGrid
+ * The grid used to compute the ray casting visibility
+ * epsilon
+ * The epsilon used for computation
+ * oShapeId
+ * fe is the border (in 2D) between 2 2D spaces.
+ * if fe is a silhouette,
+ * One of these 2D spaces is occupied by the shape
+ * to which fe belongs (on its left) and the other one is either occupied
+ * by another shape or empty or occupied by the same shape.
+ * We use this ray csating operation to determine which shape
+ * lies on fe's right.
+ * The result is the shape id stored in oShapeId
+ */
+ int ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set<ViewShape*>& oOccluders,
+ Polygon3r** oaPolygon, unsigned timestamp);
+ // FIXME
+ void FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp);
+ void FindOccludee(FEdge *fe, Grid* iGrid, real epsilon, Polygon3r** oaPolygon, unsigned timestamp,
+ Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector<WVertex*>& faceVertices);
+
+};
+
+#endif // VIEWMAPBUILDER_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
new file mode 100755
index 00000000000..d68164973a1
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp
@@ -0,0 +1,1245 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMapIO.h"
+
+#ifdef IRIX
+# define WRITE(n) Internal::write<sizeof((n))>(out, (const char*)(&(n)))
+# define READ(n) Internal::read<sizeof((n))>(in, (char*)(&(n)))
+#else
+# define WRITE(n) out.write((const char*)(&(n)), sizeof((n)))
+# define READ(n) in.read((char*)(&(n)), sizeof((n)))
+#endif
+
+#define WRITE_IF_NON_NULL(ptr) if ((ptr) == NULL) { WRITE(ZERO); } else { WRITE((ptr)->userdata); }
+#define READ_IF_NON_NULL(ptr, array) READ(tmp); if (tmp == ZERO) { (ptr) = NULL; } else { (ptr) = (array)[tmp]; }
+
+namespace ViewMapIO {
+
+ namespace Internal {
+
+ ViewMap* g_vm;
+
+ //////////////////// 'load' Functions ////////////////////
+
+ inline
+ int load(istream& in, Vec3r& v) {
+
+ if (Options::getFlags() & Options::FLOAT_VECTORS) {
+ float tmp;
+ READ(tmp);
+ v[0] = tmp;
+ READ(tmp);
+ v[1] = tmp;
+ READ(tmp);
+ v[2] = tmp;
+ } else {
+ Vec3r::value_type tmp;
+ READ(tmp);
+ v[0] = tmp;
+ READ(tmp);
+ v[1] = tmp;
+ READ(tmp);
+ v[2] = tmp;
+ }
+ return 0;
+ }
+
+
+ inline
+ int load(istream& in, Polygon3r& p) {
+
+ unsigned tmp;
+
+ // Id
+ READ(tmp);
+ p.setId(tmp);
+
+ // vertices (List)
+ vector<Vec3r> tmp_vec;
+ Vec3r v;
+ READ(tmp);
+ for (unsigned i = 0; i < tmp; i++) {
+ load(in, v);
+ tmp_vec.push_back(v);
+ }
+ p.setVertices(tmp_vec);
+
+ // min & max
+ // Already computed (in the SetVertices() method)
+
+ return 0;
+ }
+
+
+ inline
+ int load(istream& in, Material& m) {
+
+ float tmp_array[4];
+ int i;
+
+ // Diffuse
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.SetDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Specular
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.SetSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Ambient
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.SetAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Emission
+ for (i = 0; i < 4; i++)
+ READ(tmp_array[i]);
+ m.SetEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
+
+ // Shininess
+ READ(tmp_array[0]);
+ m.SetShininess(tmp_array[0]);
+
+ return 0;
+ }
+
+
+ int load(istream& in, ViewShape* vs) {
+
+ if (!vs || !vs->sshape())
+ return 1;
+
+ // SShape
+
+ // -> Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ vs->sshape()->SetId(Id(id1, id2));
+
+ // -> Importance
+ float importance;
+ READ(importance);
+ vs->sshape()->SetImportance(importance);
+
+ // -> BBox
+ // Not necessary (only used during view map computatiom)
+
+ unsigned i, size, tmp;
+
+ // -> Material
+ READ(size);
+ vector<Material> materials;
+ Material m;
+ for(i=0; i<size; ++i){
+ load(in, m);
+ materials.push_back(m);
+ }
+ vs->sshape()->SetMaterials(materials);
+
+
+
+ // -> VerticesList (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ SVertex* sv;
+ READ_IF_NON_NULL(sv, g_vm->SVertices());
+ vs->sshape()->AddNewVertex(sv);
+ }
+
+ // -> Chains (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ FEdge* fe;
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ vs->sshape()->AddChain(fe);
+ }
+
+ // -> EdgesList (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ FEdge* fe;
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ vs->sshape()->AddEdge(fe);
+ }
+
+ // ViewEdges (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ ViewEdge* ve;
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ vs->AddEdge(ve);
+ }
+
+ // ViewVertices (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ ViewVertex* vv;
+ READ_IF_NON_NULL(vv, g_vm->ViewVertices());
+ vs->AddVertex(vv);
+ }
+
+ return 0;
+ }
+
+
+ int load(istream& in, FEdge* fe) {
+
+ if (!fe)
+ return 1;
+
+ bool b;
+
+ FEdgeSmooth *fesmooth = 0;
+ FEdgeSharp * fesharp = 0;
+ if(fe->isSmooth()){
+ fesmooth = dynamic_cast<FEdgeSmooth*>(fe);
+ }else{
+ fesharp = dynamic_cast<FEdgeSharp*>(fe);
+ }
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ fe->SetId(Id(id1, id2));
+
+ // Nature
+ Nature::EdgeNature nature;
+ READ(nature);
+ fe->SetNature(nature);
+
+ // hasVisibilityPoint
+ // bool b;
+ // READ(b);
+ // fe->SetHasVisibilityPoint(b);
+
+ Vec3r v;
+ unsigned int matindex;
+
+ // VisibilityPointA
+ // load(in, v);
+ // fe->SetVisibilityPointA(v);
+
+ // VisibilityPointB
+ // load(in, v);
+ // fe->SetVisibilityPointB(v);
+
+ if(fe->isSmooth()){
+ // Normal
+ load(in, v);
+ fesmooth->SetNormal(v);
+
+ // Material
+ READ(matindex);
+ fesmooth->SetMaterialIndex(matindex);
+ }else{
+ // aNormal
+ load(in, v);
+ fesharp->SetNormalA(v);
+
+ // bNormal
+ load(in, v);
+ fesharp->SetNormalB(v);
+
+ // Materials
+ READ(matindex);
+ fesharp->SetaMaterialIndex(matindex);
+ READ(matindex);
+ fesharp->SetbMaterialIndex(matindex);
+ }
+
+ unsigned tmp;
+
+ // VertexA
+ SVertex* sva;
+ READ_IF_NON_NULL(sva, g_vm->SVertices());
+ fe->SetVertexA(sva);
+
+ // VertexB
+ SVertex* svb;
+ READ_IF_NON_NULL(svb, g_vm->SVertices());
+ fe->SetVertexB(svb);
+
+ // NextEdge
+ FEdge* nfe;
+ READ_IF_NON_NULL(nfe, g_vm->FEdges());
+ fe->SetNextEdge(nfe);
+
+ // PreviousEdge
+ FEdge* pfe;
+ READ_IF_NON_NULL(pfe, g_vm->FEdges());
+ fe->SetPreviousEdge(pfe);
+
+ // ViewEdge
+ ViewEdge* ve;
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ fe->SetViewEdge(ve);
+
+ // Face
+ // Not necessary (only used during view map computatiom)
+
+ Polygon3r p;
+
+ // aFace
+ load(in, p);
+ fe->SetaFace(p);
+
+ // occludeeEmpty
+ READ(b);
+ fe->SetOccludeeEmpty(b);
+
+ // occludeeIntersection
+ load(in, v);
+ fe->SetOccludeeIntersection(v);
+
+ return 0;
+ }
+
+
+ int load(istream& in, SVertex* sv) {
+
+ if (!sv)
+ return 1;
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ sv->SetId(Id(id1, id2));
+
+ Vec3r v;
+
+ // Point3D
+ load(in, v);
+ sv->SetPoint3D(v);
+
+ // Point2D
+ load(in, v);
+ sv->SetPoint2D(v);
+
+ unsigned tmp;
+
+ // Shape
+ ViewShape* vs;
+ READ_IF_NON_NULL(vs, g_vm->ViewShapes());
+ sv->SetShape(vs->sshape());
+
+ // pViewVertex
+ ViewVertex* vv;
+ READ_IF_NON_NULL(vv, g_vm->ViewVertices());
+ sv->SetViewVertex(vv);
+
+ unsigned i, size;
+
+ // Normals (List)
+ READ(size);
+ for (i = 0; i < size; i++) {
+ load(in, v);
+ sv->AddNormal(v);
+ }
+
+ // FEdges (List)
+ READ(size);
+ FEdge* fe;
+ for (i = 0; i < size; i++) {
+ READ_IF_NON_NULL(fe, g_vm->FEdges());
+ sv->AddFEdge(fe);
+ }
+
+ return 0;
+ }
+
+
+ int load(istream& in, ViewEdge* ve) {
+
+ if (!ve)
+ return 1;
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ ve->SetId(Id(id1, id2));
+
+ // Nature
+ Nature::EdgeNature nature;
+ READ(nature);
+ ve->SetNature(nature);
+
+ // QI
+ READ(tmp);
+ ve->SetQI(tmp);
+
+ // Shape
+ ViewShape* vs;
+ READ_IF_NON_NULL(vs, g_vm->ViewShapes());
+ ve->SetShape(vs);
+
+ // aShape
+ ViewShape* avs;
+ READ_IF_NON_NULL(avs, g_vm->ViewShapes());
+ ve->SetaShape(avs);
+
+ // FEdgeA
+ FEdge* fea;
+ READ_IF_NON_NULL(fea, g_vm->FEdges());
+ ve->SetFEdgeA(fea);
+
+ // FEdgeB
+ FEdge* feb;
+ READ_IF_NON_NULL(feb, g_vm->FEdges());
+ ve->SetFEdgeB(feb);
+
+ // A
+ ViewVertex* vva;
+ READ_IF_NON_NULL(vva, g_vm->ViewVertices());
+ ve->SetA(vva);
+
+ // B
+ ViewVertex* vvb;
+ READ_IF_NON_NULL(vvb, g_vm->ViewVertices());
+ ve->SetB(vvb);
+
+ // Occluders (List)
+ if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
+ unsigned size;
+ READ(size);
+ ViewShape* vso;
+ for (unsigned i = 0; i < size; i++) {
+ READ_IF_NON_NULL(vso, g_vm->ViewShapes());
+ ve->AddOccluder(vso);
+ }
+ }
+
+ return 0;
+ }
+
+
+ int load(istream& in, ViewVertex* vv) {
+
+ if (!vv)
+ return 1;
+
+ unsigned tmp;
+ bool b;
+
+ // Nature
+ Nature::VertexNature nature;
+ READ(nature);
+ vv->setNature(nature);
+
+ if (vv->getNature() & Nature::T_VERTEX) {
+ TVertex* tv = dynamic_cast<TVertex*>(vv);
+
+ // Id
+ Id::id_type id1, id2;
+ READ(id1);
+ READ(id2);
+ tv->SetId(Id(id1, id2));
+
+ // FrontSVertex
+ SVertex* fsv;
+ READ_IF_NON_NULL(fsv, g_vm->SVertices());
+ tv->SetFrontVertex(fsv);
+
+ // BackSVertex
+ SVertex* bsv;
+ READ_IF_NON_NULL(bsv, g_vm->SVertices());
+ tv->SetBackSVertex(bsv);
+
+ // FrontEdgeA
+ ViewEdge* fea;
+ READ_IF_NON_NULL(fea, g_vm->ViewEdges());
+ READ(b);
+ tv->SetFrontEdgeA(fea, b);
+
+ // FrontEdgeB
+ ViewEdge* feb;
+ READ_IF_NON_NULL(feb, g_vm->ViewEdges());
+ READ(b);
+ tv->SetFrontEdgeB(feb, b);
+
+ // BackEdgeA
+ ViewEdge* bea;
+ READ_IF_NON_NULL(bea, g_vm->ViewEdges());
+ READ(b);
+ tv->SetBackEdgeA(bea, b);
+
+ // BackEdgeB
+ ViewEdge* beb;
+ READ_IF_NON_NULL(beb, g_vm->ViewEdges());
+ READ(b);
+ tv->SetBackEdgeB(beb, b);
+ }
+ else if (vv->getNature() & Nature::NON_T_VERTEX) {
+ NonTVertex* ntv = dynamic_cast<NonTVertex*>(vv);
+
+ // SVertex
+ SVertex* sv;
+ READ_IF_NON_NULL(sv, g_vm->SVertices());
+ ntv->SetSVertex(sv);
+
+ // ViewEdges (List)
+ unsigned size;
+ READ(size);
+ ViewEdge* ve;
+ for (unsigned i = 0; i < size; i++) {
+ READ_IF_NON_NULL(ve, g_vm->ViewEdges());
+ READ(b);
+ ntv->AddViewEdge(ve, b);
+ }
+ }
+
+ return 0;
+ }
+
+ //////////////////// 'save' Functions ////////////////////
+
+ inline
+ int save(ostream& out, const Vec3r& v) {
+
+ if (Options::getFlags() & Options::FLOAT_VECTORS) {
+ float tmp;
+
+ tmp = v[0];
+ WRITE(tmp);
+ tmp = v[1];
+ WRITE(tmp);
+ tmp = v[2];
+ WRITE(tmp);
+ } else {
+ Vec3r::value_type tmp;
+
+ tmp = v[0];
+ WRITE(tmp);
+ tmp = v[1];
+ WRITE(tmp);
+ tmp = v[2];
+ WRITE(tmp);
+ }
+ return 0;
+ }
+
+
+ inline
+ int save(ostream& out, const Polygon3r& p) {
+
+ unsigned tmp;
+
+ // Id
+ tmp = p.getId();
+ WRITE(tmp);
+
+ // vertices (List)
+ tmp = p.getVertices().size();
+ WRITE(tmp);
+ for (vector<Vec3r>::const_iterator i = p.getVertices().begin();
+ i != p.getVertices().end(); i++) {
+ save(out, *i);
+ }
+
+ // min & max
+ // Do not need to be saved
+
+ return 0;
+ }
+
+
+ inline
+ int save(ostream& out, const Material& m) {
+
+ unsigned i;
+
+ // Diffuse
+ for (i = 0; i < 4; i++)
+ WRITE(m.diffuse()[i]);
+
+ // Specular
+ for (i = 0; i < 4; i++)
+ WRITE(m.specular()[i]);
+
+ // Ambient
+ for (i = 0; i < 4; i++)
+ WRITE(m.ambient()[i]);
+
+ // Emission
+ for (i = 0; i < 4; i++)
+ WRITE(m.emission()[i]);
+
+ // Shininess
+ float shininess = m.shininess();
+ WRITE(shininess);
+
+ return 0;
+ }
+
+
+ int save(ostream& out, ViewShape* vs) {
+
+ if (!vs || !vs->sshape()) {
+ cerr << "Warning: null ViewShape" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // SShape
+
+ // -> Id
+ Id::id_type id = vs->sshape()->getId().getFirst();
+ WRITE(id);
+ id = vs->sshape()->getId().getSecond();
+ WRITE(id);
+
+ // -> Importance
+ float importance = vs->sshape()->importance();
+ WRITE(importance);
+
+ // -> BBox
+ // Not necessary (only used during view map computatiom)
+
+ // -> Material
+ unsigned size = vs->sshape()->materials().size();
+ WRITE(size);
+ for(unsigned i=0; i<size; ++i)
+ save(out, vs->sshape()->material(i));
+
+ // -> VerticesList (List)
+ tmp = vs->sshape()->GetVertexList().size();
+ WRITE(tmp);
+ for (vector<SVertex*>::const_iterator i1 = vs->sshape()->GetVertexList().begin();
+ i1 != vs->sshape()->GetVertexList().end(); i1++)
+ WRITE_IF_NON_NULL(*i1);
+
+ // -> Chains (List)
+ tmp = vs->sshape()->GetChains().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator i2 = vs->sshape()->GetChains().begin();
+ i2 != vs->sshape()->GetChains().end(); i2++)
+ WRITE_IF_NON_NULL(*i2);
+
+ // -> EdgesList (List)
+ tmp = vs->sshape()->GetEdgeList().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator i3 = vs->sshape()->GetEdgeList().begin();
+ i3 != vs->sshape()->GetEdgeList().end(); i3++)
+ WRITE_IF_NON_NULL(*i3);
+
+ // ViewEdges (List)
+ tmp = vs->edges().size();
+ WRITE(tmp);
+ for (vector<ViewEdge*>::const_iterator i4 = vs->edges().begin();
+ i4 != vs->edges().end(); i4++)
+ WRITE_IF_NON_NULL(*i4);
+
+ // ViewVertices (List)
+ tmp = vs->vertices().size();
+ WRITE(tmp);
+ for (vector<ViewVertex*>::const_iterator i5 = vs->vertices().begin();
+ i5 != vs->vertices().end(); i5++)
+ WRITE_IF_NON_NULL(*i5);
+
+
+ return 0;
+ }
+
+
+ int save(ostream& out, FEdge* fe) {
+
+ if (!fe) {
+ cerr << "Warning: null FEdge" << endl;
+ return 1;
+ }
+
+ FEdgeSmooth * fesmooth = dynamic_cast<FEdgeSmooth*>(fe);
+ FEdgeSharp * fesharp = dynamic_cast<FEdgeSharp*>(fe);
+
+ // Id
+ Id::id_type id = fe->getId().getFirst();
+ WRITE(id);
+ id = fe->getId().getSecond();
+ WRITE(id);
+
+ // Nature
+ Nature::EdgeNature nature = fe->getNature();
+ WRITE(nature);
+
+ bool b;
+
+ // hasVisibilityPoint
+ // b = fe->hasVisibilityPoint();
+ // WRITE(b);
+
+ // VisibilityPointA
+ // save(out, fe->visibilityPointA());
+ //
+ // // VisibilityPointB
+ // save(out, fe->visibilityPointB());
+
+ unsigned index;
+ if(fe->isSmooth()){
+ // normal
+ save(out, fesmooth->normal());
+ // material
+ index = fesmooth->materialIndex();
+ WRITE(index);
+ }else{
+ // aNormal
+ save(out, fesharp->normalA());
+ // bNormal
+ save(out, fesharp->normalB());
+ // aMaterial
+ index = fesharp->aMaterialIndex();
+ WRITE(index);
+ // bMaterial
+ index = fesharp->bMaterialIndex();
+ WRITE(index);
+ }
+
+
+ // VertexA
+ WRITE_IF_NON_NULL(fe->vertexA());
+
+ // VertexB
+ WRITE_IF_NON_NULL(fe->vertexB());
+
+ // NextEdge
+ WRITE_IF_NON_NULL(fe->nextEdge());
+
+ // PreviousEdge
+ WRITE_IF_NON_NULL(fe->previousEdge());
+
+ // ViewEdge
+ WRITE_IF_NON_NULL(fe->viewedge());
+
+ // Face
+ // Not necessary (only used during view map computatiom)
+
+ // aFace
+ save(out, (Polygon3r&)fe->aFace());
+
+ // occludeeEmpty
+ b = fe->getOccludeeEmpty();
+ WRITE(b);
+
+ // occludeeIntersection
+ save(out, fe->getOccludeeIntersection());
+
+ return 0;
+ }
+
+
+ int save(ostream& out, SVertex* sv) {
+
+ if (!sv) {
+ cerr << "Warning: null SVertex" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id = sv->getId().getFirst();
+ WRITE(id);
+ id = sv->getId().getSecond();
+ WRITE(id);
+
+ Vec3r v;
+
+ // Point3D
+ v = sv->point3D();
+ save(out, sv->point3D());
+
+ // Point2D
+ v = sv->point2D();
+ save(out, v);
+
+ // Shape
+ WRITE_IF_NON_NULL(sv->shape());
+
+ // pViewVertex
+ WRITE_IF_NON_NULL(sv->viewvertex());
+
+ // Normals (List)
+ // Note: the 'size()' method of a set doesn't seem to return the
+ // actual size of the given set, so we have to hack it...
+ set<Vec3r>::const_iterator i;
+ for (i = sv->normals().begin(), tmp = 0;
+ i != sv->normals().end();
+ i++, tmp++);
+ WRITE(tmp);
+ for (i = sv->normals().begin(); i != sv->normals().end(); i++)
+ save(out, *i);
+
+ // FEdges (List)
+ tmp = sv->fedges().size();
+ WRITE(tmp);
+ for (vector<FEdge*>::const_iterator j = sv->fedges_begin();
+ j != sv->fedges_end(); j++)
+ WRITE_IF_NON_NULL(*j);
+
+ return 0;
+ }
+
+
+ int save(ostream& out, ViewEdge* ve) {
+
+ if (!ve) {
+ cerr << "Warning: null ViewEdge" << endl;
+ return 1;
+ }
+
+ unsigned tmp;
+
+ // Id
+ Id::id_type id = ve->getId().getFirst();
+ WRITE(id);
+ id = ve->getId().getSecond();
+ WRITE(id);
+
+ // Nature
+ Nature::EdgeNature nature = ve->getNature();
+ WRITE(nature);
+
+ // QI
+ unsigned qi = ve->qi();
+ WRITE(qi);
+
+ // Shape
+ WRITE_IF_NON_NULL(ve->shape());
+
+ // aShape
+ WRITE_IF_NON_NULL(ve->aShape());
+
+ // FEdgeA
+ WRITE_IF_NON_NULL(ve->fedgeA());
+
+ // FEdgeB
+ WRITE_IF_NON_NULL(ve->fedgeB());
+
+ // A
+ WRITE_IF_NON_NULL(ve->A());
+
+ // B
+ WRITE_IF_NON_NULL(ve->B());
+
+ // Occluders (List)
+ if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
+ tmp = ve->occluders().size();
+ WRITE(tmp);
+ for (vector<ViewShape*>::const_iterator i = ve->occluders().begin();
+ i != ve->occluders().end(); i++)
+ WRITE_IF_NON_NULL((*i));
+ }
+
+ return 0;
+ }
+
+
+ int save(ostream& out, ViewVertex* vv) {
+
+ if (!vv) {
+ cerr << "Warning: null ViewVertex" << endl;
+ return 1;
+ }
+
+ // Nature
+ Nature::VertexNature nature = vv->getNature();
+ WRITE(nature);
+
+ if (vv->getNature() & Nature::T_VERTEX) {
+ TVertex* tv = dynamic_cast<TVertex*>(vv);
+
+ // Id
+ Id::id_type id = tv->getId().getFirst();
+ WRITE(id);
+ id = tv->getId().getSecond();
+ WRITE(id);
+
+ // FrontSVertex
+ WRITE_IF_NON_NULL(tv->frontSVertex());
+
+ // BackSVertex
+ WRITE_IF_NON_NULL(tv->backSVertex());
+
+ // FrontEdgeA
+ WRITE_IF_NON_NULL(tv->frontEdgeA().first);
+ WRITE(tv->frontEdgeA().second);
+
+ // FrontEdgeB
+ WRITE_IF_NON_NULL(tv->frontEdgeB().first);
+ WRITE(tv->frontEdgeB().second);
+
+ // BackEdgeA
+ WRITE_IF_NON_NULL(tv->backEdgeA().first);
+ WRITE(tv->backEdgeA().second);
+
+ // BackEdgeB
+ WRITE_IF_NON_NULL(tv->backEdgeB().first);
+ WRITE(tv->backEdgeB().second);
+
+ }
+ else if (vv->getNature() & Nature::NON_T_VERTEX) {
+ NonTVertex* ntv = dynamic_cast<NonTVertex*>(vv);
+
+ // SVertex
+ WRITE_IF_NON_NULL(ntv->svertex());
+
+ // ViewEdges (List)
+ unsigned size = ntv->viewedges().size();
+ WRITE(size);
+ vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin();
+ for ( ; i != ntv->viewedges().end(); i++){
+ WRITE_IF_NON_NULL(i->first);
+ WRITE(i->second);
+ }
+
+ } else {
+ cerr << "Warning: unexpected ViewVertex nature" << endl;
+ return 1;
+ }
+
+ return 0;
+ }
+
+ } // End of namespace Internal
+
+
+ //////////////////// "Public" 'load' and 'save' functions ////////////////////
+
+#define SET_PROGRESS(n) if (pb) pb->setProgress((n))
+
+ int load(istream& in, ViewMap* vm, ProgressBar* pb) {
+
+ if (!vm)
+ return 1;
+
+ unsigned tmp;
+
+ int err = 0;
+
+ Internal::g_vm = vm;
+
+ // Management of the progress bar (if present)
+ if (pb) {
+ pb->reset();
+ pb->setLabelText("Loading View Map...");
+ pb->setTotalSteps(6);
+ pb->setProgress(0);
+ }
+
+ // Read and set the options
+ unsigned char flags;
+ READ(flags);
+ Options::setFlags(flags);
+
+ // Read the size of the five ViewMap's lists (with some extra informations for the ViewVertices)
+ // and instantiate them (with default costructors)
+ unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2;
+ READ(vs_s);
+ READ(fe_s);
+
+ if (fe_s) {
+ bool b;
+ READ(b);
+ for (READ(fe_rle1), fe_rle2 = 0;
+ fe_rle1 < fe_s+1;
+ fe_rle2 = fe_rle1, READ(fe_rle1)) {
+ if (b) {
+ for (unsigned i = fe_rle2; i < fe_rle1; i++) {
+ FEdgeSmooth * fes = new FEdgeSmooth;
+ vm->AddFEdge(fes);
+ }
+ b = !b;
+ }
+ else if (!b) {
+ for (unsigned i = fe_rle2; i < fe_rle1; i++) {
+ FEdgeSharp * fes = new FEdgeSharp;
+ vm->AddFEdge(fes);
+ }
+ b = !b;
+ }
+ }
+ }
+
+ READ(sv_s);
+ READ(ve_s);
+ READ(vv_s);
+
+ if (vv_s) {
+ Nature::VertexNature nature;
+ READ(nature);
+ for (READ(vv_rle1), vv_rle2 = 0;
+ vv_rle1 < vv_s+1;
+ vv_rle2 = vv_rle1, READ(vv_rle1)) {
+ if (nature & Nature::T_VERTEX) {
+ for (unsigned i = vv_rle2; i < vv_rle1; i++) {
+ TVertex* tv = new TVertex();
+ vm->AddViewVertex(tv);
+ }
+ nature = Nature::NON_T_VERTEX;
+ }
+ else if (nature & Nature::NON_T_VERTEX) {
+ for (unsigned i = vv_rle2; i < vv_rle1; i++) {
+ NonTVertex* ntv = new NonTVertex();
+ vm->AddViewVertex(ntv);
+ }
+ nature = Nature::T_VERTEX;
+ }
+ }
+ }
+
+ for (unsigned i0 = 0; i0 < vs_s; i0++) {
+ SShape* ss = new SShape();
+ ViewShape* vs = new ViewShape();
+ vs->SetSShape(ss);
+ ss->SetViewShape(vs);
+ vm->AddViewShape(vs);
+ }
+ // for (unsigned i1 = 0; i1 < fe_s; i1++) {
+ // FEdge* fe = new FEdge();
+ // vm->AddFEdge(fe);
+ // }
+ for (unsigned i2 = 0; i2 < sv_s; i2++) {
+ SVertex* sv = new SVertex();
+ vm->AddSVertex(sv);
+ }
+ for (unsigned i3 = 0; i3 < ve_s; i3++) {
+ ViewEdge* ve = new ViewEdge();
+ vm->AddViewEdge(ve);
+ }
+
+
+ // Read the values for all the objects created above
+ SET_PROGRESS(1);
+ for (vector<ViewShape*>::const_iterator i4 = vm->ViewShapes().begin();
+ i4 != vm->ViewShapes().end(); i4++)
+ err += Internal::load(in, *i4);
+ SET_PROGRESS(2);
+ for (vector<FEdge*>::const_iterator i5 = vm->FEdges().begin();
+ i5 != vm->FEdges().end(); i5++)
+ err += Internal::load(in, *i5);
+ SET_PROGRESS(3);
+ for (vector<SVertex*>::const_iterator i6 = vm->SVertices().begin();
+ i6 != vm->SVertices().end(); i6++)
+ err += Internal::load(in, *i6);
+ SET_PROGRESS(4);
+ for (vector<ViewEdge*>::const_iterator i7 = vm->ViewEdges().begin();
+ i7 != vm->ViewEdges().end(); i7++)
+ err += Internal::load(in, *i7);
+ SET_PROGRESS(5);
+ for (vector<ViewVertex*>::const_iterator i8 = vm->ViewVertices().begin();
+ i8 != vm->ViewVertices().end(); i8++)
+ err += Internal::load(in, *i8);
+ SET_PROGRESS(6);
+
+ // Read the shape id to index mapping
+ unsigned map_s;
+ READ(map_s);
+ unsigned id,index;
+ for(unsigned i4=0;i4<map_s;++i4){
+ READ(id);
+ READ(index);
+ vm->shapeIdToIndexMap()[id] = index;
+ }
+
+ return err;
+ }
+
+
+ int save(ostream& out, ViewMap* vm, ProgressBar* pb) {
+
+ if (!vm)
+ return 1;
+
+ int err = 0;
+
+ // Management of the progress bar (if present)
+ if (pb) {
+ pb->reset();
+ pb->setLabelText("Saving View Map...");
+ pb->setTotalSteps(6);
+ pb->setProgress(0);
+ }
+
+ // For every object, initialize its userdata member to its index in the ViewMap list
+ for (unsigned i0 = 0; i0 < vm->ViewShapes().size(); i0++) {
+ vm->ViewShapes()[i0]->userdata = (void*)i0;
+ vm->ViewShapes()[i0]->sshape()->userdata = (void*)i0;
+ }
+ for (unsigned i1 = 0; i1 < vm->FEdges().size(); i1++)
+ vm->FEdges()[i1]->userdata = (void*)i1;
+ for (unsigned i2 = 0; i2 < vm->SVertices().size(); i2++)
+ vm->SVertices()[i2]->userdata = (void*)i2;
+ for (unsigned i3 = 0; i3 < vm->ViewEdges().size(); i3++)
+ vm->ViewEdges()[i3]->userdata = (void*)i3;
+ for (unsigned i4 = 0; i4 < vm->ViewVertices().size(); i4++)
+ vm->ViewVertices()[i4]->userdata = (void*)i4;
+
+ // Write the current options
+ unsigned char flags = Options::getFlags();
+ WRITE(flags);
+
+ // Write the size of the five lists (with some extra informations for the ViewVertices)
+ unsigned size;
+ size = vm->ViewShapes().size();
+ WRITE(size);
+ size = vm->FEdges().size();
+ WRITE(size);
+ if (size) {
+ bool b = vm->FEdges()[0]->isSmooth();
+ WRITE(b);
+ for (unsigned i = 0; i < size; i++) {
+ while (i < size && (vm->FEdges()[i]->isSmooth() == b))
+ i++;
+ if (i < size) {
+ WRITE(i);
+ b = !b;
+ }
+ }
+ WRITE(size);
+ size++;
+ WRITE(size);
+ }
+ size = vm->SVertices().size();
+ WRITE(size);
+ size = vm->ViewEdges().size();
+ WRITE(size);
+ size = vm->ViewVertices().size();
+ WRITE(size);
+ if (size) {
+ Nature::VertexNature nature = vm->ViewVertices()[0]->getNature();
+ WRITE(nature);
+ nature &= ~Nature::VIEW_VERTEX;
+ for (unsigned i = 0; i < size; i++) {
+ while (i < size && (vm->ViewVertices()[i]->getNature() & nature))
+ i++;
+ if (i < size) {
+ WRITE(i);
+ nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX;
+ }
+ }
+ WRITE(size);
+ size++;
+ WRITE(size);
+ }
+
+
+ // Write all the elts of the ViewShapes List
+ SET_PROGRESS(1);
+ for (vector<ViewShape*>::const_iterator i5 = vm->ViewShapes().begin();
+ i5 != vm->ViewShapes().end(); i5++)
+ err += Internal::save(out, *i5);
+ SET_PROGRESS(2);
+ for (vector<FEdge*>::const_iterator i6 = vm->FEdges().begin();
+ i6 != vm->FEdges().end(); i6++)
+ err += Internal::save(out, *i6);
+ SET_PROGRESS(3);
+ for (vector<SVertex*>::const_iterator i7 = vm->SVertices().begin();
+ i7 != vm->SVertices().end(); i7++)
+ err += Internal::save(out, *i7);
+ SET_PROGRESS(4);
+ for (vector<ViewEdge*>::const_iterator i8 = vm->ViewEdges().begin();
+ i8 != vm->ViewEdges().end(); i8++)
+ err += Internal::save(out, *i8);
+ SET_PROGRESS(5);
+ for (vector<ViewVertex*>::const_iterator i9 = vm->ViewVertices().begin();
+ i9 != vm->ViewVertices().end(); i9++)
+ err += Internal::save(out, *i9);
+
+ // Write the shape id to index mapping
+ size = vm->shapeIdToIndexMap().size();
+ WRITE(size);
+ unsigned id,index;
+ for(ViewMap::id_to_index_map::iterator mit=vm->shapeIdToIndexMap().begin(), mitend=vm->shapeIdToIndexMap().end(); mit!=mitend; ++mit){
+ id = mit->first;
+ index = mit->second;
+ WRITE(id);
+ WRITE(index);
+ }
+
+ // Reset 'userdata' members
+ for (vector<ViewShape*>::const_iterator j0 = vm->ViewShapes().begin();
+ j0 != vm->ViewShapes().end(); j0++) {
+ (*j0)->userdata = 0;
+ (*j0)->sshape()->userdata = 0;
+ }
+ for (vector<FEdge*>::const_iterator j1 = vm->FEdges().begin();
+ j1 != vm->FEdges().end(); j1++)
+ (*j1)->userdata = 0;
+ for (vector<SVertex*>::const_iterator j2 = vm->SVertices().begin();
+ j2 != vm->SVertices().end(); j2++)
+ (*j2)->userdata = 0;
+ for (vector<ViewEdge*>::const_iterator j3 = vm->ViewEdges().begin();
+ j3 != vm->ViewEdges().end(); j3++)
+ (*j3)->userdata = 0;
+ for (vector<ViewVertex*>::const_iterator j4 = vm->ViewVertices().begin();
+ j4 != vm->ViewVertices().end(); j4++)
+ (*j4)->userdata = 0;
+ SET_PROGRESS(6);
+
+ return err;
+ }
+
+
+ //////////////////// Options ////////////////////
+
+ namespace Options {
+
+ namespace Internal {
+
+ static unsigned char g_flags = 0;
+ static string g_models_path;
+
+ } // End of namespace Internal
+
+ void setFlags(const unsigned char flags) {
+ Internal::g_flags = flags;
+ }
+
+ void addFlags(const unsigned char flags) {
+ Internal::g_flags |= flags;
+ }
+
+ void rmFlags(const unsigned char flags) {
+ Internal::g_flags &= ~flags;
+ }
+
+ unsigned char getFlags() {
+ return Internal::g_flags;
+ }
+
+ void setModelsPath(const string& path) {
+ Internal::g_models_path = path;
+ }
+
+ string getModelsPath() {
+ return Internal::g_models_path;
+ }
+
+ }; // End of namepace Options
+
+} // End of namespace ViewMapIO
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.h b/source/blender/freestyle/intern/view_map/ViewMapIO.h
new file mode 100755
index 00000000000..33e168b537b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIO.h
@@ -0,0 +1,116 @@
+//
+// Filename : ViewMapIO.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Functions to manage I/O for the view map
+// Date of creation : 09/01/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPIO_H
+# define VIEWMAPIO_H
+
+# include <fstream>
+# include <string>
+# include "../system/FreestyleConfig.h"
+# include "../system/ProgressBar.h"
+# include "ViewMap.h"
+
+namespace ViewMapIO {
+
+ static const unsigned ZERO = UINT_MAX;
+
+ LIB_VIEW_MAP_EXPORT
+ int load(istream& in, ViewMap* vm, ProgressBar* pb = NULL);
+
+ LIB_VIEW_MAP_EXPORT
+ int save(ostream& out, ViewMap* vm, ProgressBar* pb = NULL);
+
+ namespace Options {
+
+ static const unsigned char FLOAT_VECTORS = 1;
+ static const unsigned char NO_OCCLUDERS = 2;
+
+ LIB_VIEW_MAP_EXPORT
+ void setFlags(const unsigned char flags);
+
+ LIB_VIEW_MAP_EXPORT
+ void addFlags(const unsigned char flags);
+
+ LIB_VIEW_MAP_EXPORT
+ void rmFlags(const unsigned char flags);
+
+ LIB_VIEW_MAP_EXPORT
+ unsigned char getFlags();
+
+ LIB_VIEW_MAP_EXPORT
+ void setModelsPath(const string& path);
+
+ LIB_VIEW_MAP_EXPORT
+ string getModelsPath();
+
+ }; // End of namepace Options
+
+# ifdef IRIX
+
+ namespace Internal {
+
+ template <unsigned S>
+ ostream& write(ostream& out, const char* str) {
+ out.put(str[S - 1]);
+ return write<S - 1>(out, str);
+ }
+
+ template<>
+ ostream& write<1>(ostream& out, const char* str) {
+ return out.put(str[0]);
+ }
+
+ template<>
+ ostream& write<0>(ostream& out, const char*) {
+ return out;
+ }
+
+ template <unsigned S>
+ istream& read(istream& in, char* str) {
+ in.get(str[S - 1]);
+ return read<S - 1>(in, str);
+ }
+
+ template<>
+ istream& read<1>(istream& in, char* str) {
+ return in.get(str[0]);
+ }
+
+ template<>
+ istream& read<0>(istream& in, char*) {
+ return in;
+ }
+
+ } // End of namespace Internal
+
+# endif // IRIX
+
+} // End of namespace ViewMapIO
+
+#endif // VIEWMAPIO_H
diff --git a/source/blender/freestyle/intern/view_map/ViewMapIterators.h b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
new file mode 100755
index 00000000000..004674ba758
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
@@ -0,0 +1,542 @@
+//
+// Filename : ViewMapIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the various elements
+// of the ViewMap
+// Date of creation : 01/07/2003
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPITERATORS_H
+# define VIEWMAPITERATORS_H
+
+#include "ViewMap.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewMap */
+ /* */
+ /* */
+ /**********************************/
+
+ /**********************************/
+ /* */
+ /* */
+ /* ViewVertex */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewVertexInternal{
+
+ /*! Class representing an iterator over oriented ViewEdges
+ * around a ViewVertex. This iterator allows a CCW iteration
+ * (in the image plane).
+ * An instance of an orientedViewEdgeIterator can only
+ * be obtained from a ViewVertex by calling edgesBegin() or edgesEnd().
+ */
+ class orientedViewEdgeIterator
+ {
+ public:
+ friend class ViewVertex;
+ friend class TVertex;
+ friend class NonTVertex;
+ friend class ViewEdge;
+
+ // FIXME
+ typedef ::TVertex::edge_pointers_container edge_pointers_container;
+ typedef ::NonTVertex::edges_container edges_container;
+ protected:
+
+ Nature::VertexNature _Nature; // the nature of the underlying vertex
+ // T vertex attributes
+ edge_pointers_container::iterator _tbegin;
+ edge_pointers_container::iterator _tend;
+ edge_pointers_container::iterator _tvertex_iter;
+
+ // Non TVertex attributes
+ edges_container::iterator _begin;
+ edges_container::iterator _end;
+ edges_container::iterator _nontvertex_iter;
+
+ public:
+ /*! Default constructor */
+ inline orientedViewEdgeIterator() {}
+ inline orientedViewEdgeIterator(Nature::VertexNature iNature)
+ {_Nature = iNature;}
+ /*! Copy constructor */
+ orientedViewEdgeIterator(const orientedViewEdgeIterator& iBrother)
+ {
+ _Nature = iBrother._Nature;
+ if(_Nature & Nature::T_VERTEX)
+ {
+ _tbegin = iBrother._tbegin;
+ _tend = iBrother._tend;
+ _tvertex_iter = iBrother._tvertex_iter;
+ }
+ else
+ {
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _nontvertex_iter = iBrother._nontvertex_iter;
+ }
+ }
+ virtual ~orientedViewEdgeIterator() {}
+
+ public:
+ inline orientedViewEdgeIterator(edge_pointers_container::iterator begin,
+ edge_pointers_container::iterator end,
+ edge_pointers_container::iterator iter)
+ {
+ _Nature = Nature::T_VERTEX;
+ _tbegin = begin;
+ _tend = end;
+ _tvertex_iter = iter;
+ }
+ inline orientedViewEdgeIterator(edges_container::iterator begin,
+ edges_container::iterator end,
+ edges_container::iterator iter)
+ {
+ _Nature = Nature::NON_T_VERTEX;
+ _begin = begin;
+ _end = end;
+ _nontvertex_iter = iter;
+ }
+
+ public:
+
+
+ /*! Tells whether the ViewEdge pointed
+ * by this iterator is the first one of the
+ * iteration list or not.
+ */
+ virtual bool isBegin() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tbegin);
+ else
+ return (_nontvertex_iter == _begin);
+ }
+ /*! Tells whether the ViewEdge pointed
+ * by this iterator is after the last one of the
+ * iteration list or not.
+ */
+ virtual bool isEnd() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter == _tend);
+ else
+ return (_nontvertex_iter == _end);
+ }
+
+ // operators
+ /*! Increments.In the scripting language, call
+ * "increment()".
+ */
+ virtual orientedViewEdgeIterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ /*! Increments.In the scripting language, call
+ * "increment()".
+ */
+ virtual orientedViewEdgeIterator operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ orientedViewEdgeIterator tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ /*! operator != */
+ virtual bool operator!=(const orientedViewEdgeIterator& b) const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ return (_tvertex_iter != b._tvertex_iter);
+ else
+ return (_nontvertex_iter != b._nontvertex_iter);
+ }
+
+ /*! operator == */
+ virtual bool operator==(const orientedViewEdgeIterator& b) const
+ {return !(*this != b);}
+
+ // dereferencing
+ /*! Returns a reference to the pointed orientedViewEdge.
+ * In the scripting language, you must call
+ * "getObject()"instead.
+ */
+ virtual ::ViewVertex::directedViewEdge& operator*() const
+ {
+ if(_Nature & Nature::T_VERTEX)
+ //return _tvertex_iter;
+ return **_tvertex_iter;
+ else
+ return (*_nontvertex_iter);
+ }
+ /*! Returns a pointer to the pointed orientedViewEdge.
+ * Can't be called in the scripting language.
+ */
+ virtual ::ViewVertex::directedViewEdge* operator->() const { return &(operator*());}
+
+ public:
+ /*! increments.*/
+ inline void increment()
+ {
+ if(_Nature & Nature::T_VERTEX)
+ {
+ ::ViewVertex::directedViewEdge tmp = (**_tvertex_iter);
+ ++_tvertex_iter;
+ if(_tvertex_iter != _tend){
+ // FIXME : pquoi deja ?
+ ::ViewVertex::directedViewEdge tmp2 = (**_tvertex_iter);
+ if(tmp2.first == tmp.first)
+ ++_tvertex_iter;
+ }
+ }
+ else
+ ++_nontvertex_iter;
+ }
+ };
+
+ }
+ /**********************************/
+ /* */
+ /* */
+ /* ViewEdge */
+ /* */
+ /* */
+ /**********************************/
+
+namespace ViewEdgeInternal {
+//
+// SVertexIterator
+//
+/////////////////////////////////////////////////
+
+ class SVertexIterator : public Interface0DIteratorNested
+ {
+ public:
+
+ SVertexIterator() {
+ _vertex = NULL;
+ _begin = NULL;
+ _previous_edge = NULL;
+ _next_edge = NULL;
+ _t = 0;
+ }
+
+ SVertexIterator(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _begin = vi._begin;
+ _previous_edge = vi._previous_edge;
+ _next_edge = vi._next_edge;
+ _t = vi._t;
+ }
+
+ SVertexIterator(SVertex* v, SVertex* begin, FEdge* prev, FEdge* next, float t) {
+ _vertex = v;
+ _begin = begin;
+ _previous_edge = prev;
+ _next_edge = next;
+ _t = t;
+ }
+
+ SVertexIterator& operator=(const SVertexIterator& vi) {
+ _vertex = vi._vertex;
+ _begin = vi._begin;
+ _previous_edge = vi._previous_edge;
+ _next_edge = vi._next_edge;
+ _t = vi._t;
+ return *this;
+ }
+
+ virtual ~SVertexIterator() {}
+
+ virtual string getExactTypeName() const {
+ return "SVertexIterator";
+ }
+
+ virtual SVertex& operator*() {
+ return *_vertex;
+ }
+
+ virtual SVertex* operator->() {
+ return &(operator*());
+ }
+
+ virtual SVertexIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ virtual SVertexIterator operator++(int) {
+ SVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ virtual SVertexIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ virtual SVertexIterator operator--(int) {
+ SVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ virtual void increment(){
+ if (!_next_edge) {
+ _vertex = 0;
+ return;
+ }
+ _t += (float)_next_edge->getLength2D();
+ _vertex = _next_edge->vertexB();
+ _previous_edge = _next_edge;
+ _next_edge = _next_edge->nextEdge();
+
+ }
+ virtual void decrement(){
+ if (!_previous_edge) {
+ _vertex = 0;
+ return;
+ }
+ if((!_next_edge) && (!_vertex)){
+ _vertex = _previous_edge->vertexB();
+ return;
+ }
+ _t -= (float)_previous_edge->getLength2D();
+ _vertex = _previous_edge->vertexA();
+ _next_edge = _previous_edge;
+ _previous_edge = _previous_edge->previousEdge();
+ }
+
+ bool isBegin() const {
+ return _vertex == _begin;
+ }
+
+ bool isEnd() const {
+ return (!_vertex) || (_vertex == _begin && _previous_edge);
+ }
+
+ virtual float t() const {
+ return _t;
+ }
+ virtual float u() const {
+ return _t/(float)_next_edge->viewedge()->getLength2D();
+ }
+
+ virtual bool operator==(const Interface0DIteratorNested& it) const {
+ const SVertexIterator* it_exact = dynamic_cast<const SVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return (_vertex == it_exact->_vertex);
+ }
+
+ virtual SVertexIterator* copy() const {
+ return new SVertexIterator(*this);
+ }
+
+ private:
+
+ SVertex* _vertex;
+ SVertex* _begin;
+ FEdge* _previous_edge;
+ FEdge* _next_edge;
+ float _t; // curvilinear abscissa
+ };
+
+
+
+//
+// ViewEdgeIterator (base class)
+//
+///////////////////////////////////////////////////////////
+
+ /*! Base class for iterators over ViewEdges of the ViewMap Graph.
+ * Basically the "increment()" operator of this class should
+ * be able to take the decision of "where" (on which ViewEdge) to go
+ * when pointing on a given ViewEdge.
+ * ::Caution::: the dereferencing operator returns a *pointer* to
+ * the pointed ViewEdge.
+ */
+class ViewEdgeIterator
+{
+public:
+
+ /*! Builds a ViewEdgeIterator from a starting ViewEdge and its orientation.
+ * \param begin
+ * The ViewEdge from where to start the iteration.
+ * \param orientation
+ * If true, we'll look for the next ViewEdge among the
+ * ViewEdges that surround the ending ViewVertex of begin.
+ * If false, we'll search over the ViewEdges surrounding
+ * the ending ViewVertex of begin.
+ */
+ ViewEdgeIterator(ViewEdge* begin = 0, bool orientation = true) {
+ _orientation = orientation;
+ _edge = begin;
+ _begin = begin;
+ }
+
+ /*! Copy constructor */
+ ViewEdgeIterator(const ViewEdgeIterator& it) {
+ _orientation = it._orientation;
+ _edge = it._edge;
+ _begin = it._begin;
+ }
+
+ virtual ~ViewEdgeIterator() {}
+
+ /*! Returns the string "ViewEdgeIterator" */
+ virtual string getExactTypeName() const {
+ return "ViewEdgeIterator";
+ }
+
+ /*! Returns the current pointed ViewEdge. */
+ ViewEdge* getCurrentEdge() {
+ return _edge;
+ }
+
+ /*! Sets the current pointed ViewEdge. */
+ void setCurrentEdge(ViewEdge* edge) {
+ _edge = edge;
+ }
+
+ /*! Returns the first ViewEdge used for the iteration. */
+ ViewEdge* getBegin() {
+ return _begin;
+ }
+
+ /*! Sets the first ViewEdge used for the iteration. */
+ void setBegin(ViewEdge* begin) {
+ _begin = begin;
+ }
+
+ /*! Gets the orientation of the pointed ViewEdge in the iteration. */
+ bool getOrientation() const {
+ return _orientation;
+ }
+
+ /*! Sets the orientation of the pointed ViewEdge in the iteration. */
+ void setOrientation(bool orientation) {
+ _orientation = orientation;
+ }
+
+ /*! Changes the current orientation. */
+ void changeOrientation() {
+ _orientation = !_orientation;
+ }
+
+ /*! Returns a *pointer* to the pointed ViewEdge. */
+ virtual ViewEdge* operator*() {
+ return _edge;
+ }
+
+ virtual ViewEdge* operator->() {
+ return operator*();
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual ViewEdgeIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual ViewEdgeIterator operator++(int) {
+ ViewEdgeIterator tmp(*this);
+ increment();
+ return tmp;
+ }
+
+ /*! increments. */
+ virtual void increment() {
+ cerr << "Warning: method increment() not implemented" << endl;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual ViewEdgeIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual ViewEdgeIterator operator--(int) {
+ ViewEdgeIterator tmp(*this);
+ decrement();
+ return tmp;
+ }
+
+ /*! decrements. */
+ virtual void decrement(){
+ cerr << "Warning: method decrement() not implemented" << endl;
+ }
+
+ /*! Returns true if the pointed ViewEdge is the
+ * first one used for the iteration.
+ */
+ virtual bool isBegin() const {
+ return _edge == _begin;
+ }
+
+ /*! Returns true if the pointed ViewEdge* equals 0.
+ */
+ virtual bool isEnd() const {
+ return !_edge;
+ }
+
+ /*! operator == */
+ virtual bool operator==(ViewEdgeIterator& it) const {
+ return _edge == it._edge;
+ }
+
+ /*! operator != */
+ virtual bool operator!=(ViewEdgeIterator& it) const {
+ return !(*this == it);
+ }
+
+protected:
+
+ bool _orientation;
+ ViewEdge* _edge;
+ ViewEdge* _begin;
+};
+
+} // end of namespace ViewEdgeInternal
+
+#endif // VIEWMAPITERATORS_H
+
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp
new file mode 100755
index 00000000000..6041f527d17
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp
@@ -0,0 +1,36 @@
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ViewMapTesselator.h"
+
+NodeGroup* ViewMapTesselator::Tesselate(ViewMap *iViewMap)
+{
+ if(0 == iViewMap->ViewEdges().size())
+ return NULL;
+
+ const vector<ViewEdge*>& viewedges = iViewMap->ViewEdges();
+ return Tesselate(viewedges.begin(), viewedges.end());
+}
+
+NodeGroup* ViewMapTesselator::Tesselate(WShape *)
+{
+ return NULL;
+}
diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
new file mode 100755
index 00000000000..fc1ec8e373e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h
@@ -0,0 +1,196 @@
+//
+// Filename : ViewMapTesselator.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build a Node Tree designed to be displayed
+// from a Silhouette View Map structure.
+// Date of creation : 26/03/2002
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// Copyright (C) : Please refer to the COPYRIGHT file distributed
+// with this source distribution.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef VIEWMAPTESSELATOR_H
+# define VIEWMAPTESSELATOR_H
+
+# include "../scene_graph/NodeShape.h"
+# include "../winged_edge/WEdge.h"
+# include "Silhouette.h"
+# include "ViewMap.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../scene_graph/LineRep.h"
+# include "../scene_graph/OrientedLineRep.h"
+# include "../scene_graph/VertexRep.h"
+
+class NodeShape;
+class NodeGroup;
+class SShape;
+class WShape;
+
+class LIB_VIEW_MAP_EXPORT ViewMapTesselator
+{
+public:
+
+ inline ViewMapTesselator() {_nature = Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE;_Material.SetDiffuse(0,0,0,1);_overloadMaterial=false;}
+ virtual ~ViewMapTesselator() {}
+
+ /*! Builds a set of lines rep contained under a
+ * a NodeShape, itself contained under a NodeGroup from a ViewMap
+ */
+ NodeGroup* Tesselate(ViewMap* iViewMap) ;
+
+ /*! Builds a set of lines rep contained under a
+ * a NodeShape, itself contained under a NodeGroup from a
+ * set of view edges
+ */
+ template<class ViewEdgesIterator>
+ NodeGroup* Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) ;
+
+ /*! Builds a set of lines rep contained among a
+ * a NodeShape, from a WShape
+ */
+ NodeGroup* Tesselate(WShape* iWShape);
+
+
+ inline void SetNature(Nature::EdgeNature iNature) {_nature = iNature;}
+ inline void SetMaterial(const Material& iMaterial) {_Material=iMaterial;_overloadMaterial=true;}
+ inline Nature::EdgeNature nature() {return _nature;}
+ inline const Material& material() const {return _Material;}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0;
+
+private:
+ Nature::EdgeNature _nature;
+ Material _Material;
+ bool _overloadMaterial;
+};
+
+/*! Class to tesselate the 2D projected silhouette */
+class ViewMapTesselator2D : public ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator2D() : ViewMapTesselator() {}
+ virtual ~ViewMapTesselator2D() {}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v)
+ {
+ iLine->AddVertex(v->point2D());
+ }
+};
+
+/*! Class to tesselate the 3D silhouette */
+class ViewMapTesselator3D : public ViewMapTesselator
+{
+public:
+ inline ViewMapTesselator3D() : ViewMapTesselator() {}
+ virtual ~ViewMapTesselator3D() {}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v)
+ {
+ iLine->AddVertex(v->point3D());
+ }
+};
+
+//
+// Implementation
+//
+///////////////////////////////////////////////
+
+template<class ViewEdgesIterator>
+NodeGroup * ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end)
+{
+ NodeGroup *group = new NodeGroup;
+ NodeShape *tshape = new NodeShape;
+ group->AddChild(tshape);
+ //tshape->material().SetDiffuse(0.f, 0.f, 0.f, 1.f);
+ tshape->SetMaterial(_Material);
+
+ LineRep* line;
+
+
+ FEdge *firstEdge;
+ FEdge *nextFEdge, *currentEdge;
+
+ int id=0;
+ // for(vector<ViewEdge*>::const_iterator c=viewedges.begin(),cend=viewedges.end();
+ // c!=cend;
+ // c++)
+ for(ViewEdgesIterator c=begin, cend=end;
+ c!=cend;
+ c++)
+ {
+ // if((*c)->qi() > 0){
+ // continue;
+ // }
+ // if(!((*c)->nature() & (_nature)))
+ // continue;
+ //
+ firstEdge = (*c)->fedgeA();
+
+ // if(firstEdge->invisibility() > 0)
+ // continue;
+
+ line = new OrientedLineRep();
+ if(_overloadMaterial)
+ line->SetMaterial(_Material);
+
+ // there might be chains containing a single element
+ if(0 == (firstEdge)->nextEdge())
+ {
+ line->SetStyle(LineRep::LINES);
+ // line->AddVertex((*c)->vertexA()->point3D());
+ // line->AddVertex((*c)->vertexB()->point3D());
+ AddVertexToLine(line, firstEdge->vertexA());
+ AddVertexToLine(line, firstEdge->vertexB());
+ }
+ else
+ {
+ line->SetStyle(LineRep::LINE_STRIP);
+
+ //firstEdge = (*c);
+ nextFEdge = firstEdge;
+ currentEdge = firstEdge;
+ do
+ {
+ //line->AddVertex(nextFEdge->vertexA()->point3D());
+ AddVertexToLine(line, nextFEdge->vertexA());
+ currentEdge = nextFEdge;
+ nextFEdge = nextFEdge->nextEdge();
+ }while((nextFEdge != NULL) && (nextFEdge != firstEdge));
+ // Add the last vertex
+ //line->AddVertex(currentEdge->vertexB()->point3D());
+ AddVertexToLine(line, currentEdge->vertexB());
+
+ }
+
+ line->SetId((*c)->getId().getFirst());
+ line->ComputeBBox();
+ tshape->AddRep(line);
+ id++;
+ }
+
+ return group;
+}
+
+#endif // VIEWMAPTESSELATOR_H
diff --git a/source/blender/freestyle/intern/view_map/src.pri b/source/blender/freestyle/intern/view_map/src.pri
new file mode 100755
index 00000000000..2faf6a81fea
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/src.pri
@@ -0,0 +1,34 @@
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# W A R N I N G ! ! ! #
+# a u t h o r i z e d p e r s o n a l o n l y #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+VIEW_MAP_DIR = ../view_map
+
+SOURCES *= $${VIEW_MAP_DIR}/Functions0D.cpp \
+ $${VIEW_MAP_DIR}/Functions1D.cpp \
+ $${VIEW_MAP_DIR}/Silhouette.cpp \
+ $${VIEW_MAP_DIR}/SilhouetteGeomEngine.cpp \
+ $${VIEW_MAP_DIR}/ViewMap.cpp \
+ $${VIEW_MAP_DIR}/ViewMapBuilder.cpp \
+ $${VIEW_MAP_DIR}/ViewMapIO.cpp \
+ $${VIEW_MAP_DIR}/ViewMapTesselator.cpp \
+ $${VIEW_MAP_DIR}/FEdgeXDetector.cpp \
+ $${VIEW_MAP_DIR}/ViewEdgeXBuilder.cpp \
+ $${VIEW_MAP_DIR}/SteerableViewMap.cpp
+
+HEADERS *= $${VIEW_MAP_DIR}/Functions0D.h \
+ $${VIEW_MAP_DIR}/Functions1D.h \
+ $${VIEW_MAP_DIR}/Interface0D.h \
+ $${VIEW_MAP_DIR}/Interface1D.h \
+ $${VIEW_MAP_DIR}/Silhouette.h \
+ $${VIEW_MAP_DIR}/SilhouetteGeomEngine.h \
+ $${VIEW_MAP_DIR}/ViewMap.h \
+ $${VIEW_MAP_DIR}/ViewMapAdvancedIterators.h \
+ $${VIEW_MAP_DIR}/ViewMapBuilder.h \
+ $${VIEW_MAP_DIR}/ViewMapIO.h \
+ $${VIEW_MAP_DIR}/ViewMapIterators.h \
+ $${VIEW_MAP_DIR}/ViewMapTesselator.h \
+ $${VIEW_MAP_DIR}/FEdgeXDetector.h \
+ $${VIEW_MAP_DIR}/ViewEdgeXBuilder.h \
+ $${VIEW_MAP_DIR}/SteerableViewMap.h
diff --git a/source/blender/freestyle/intern/view_map/view_map.pro b/source/blender/freestyle/intern/view_map/view_map.pro
new file mode 100755
index 00000000000..ef629bcf6a7
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/view_map.pro
@@ -0,0 +1,89 @@
+# This file should be viewed as a -*- mode: Makefile -*-
+
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+# W A R N I N G ! ! ! #
+# a u t h o r i z e d p e r s o n a l o n l y #
+# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
+
+include(../Config.pri)
+
+TEMPLATE = lib
+
+TARGET = $${LIB_VIEW_MAP}
+VERSION = $${APPVERSION}
+TARGET_VERSION_EXT = $${APPVERSION_MAJ}.$${APPVERSION_MID}
+
+#
+# CONFIG
+#
+#######################################
+
+CONFIG *= dll
+
+#
+# DEFINES
+#
+#######################################
+
+win32:DEFINES *= MAKE_LIB_VIEW_MAP_DLL
+
+#
+# INCLUDE PATH
+#
+#######################################
+
+#INCLUDEPATH *= ../geometry ../image ../scene_graph ../system ../winged_edge
+
+#
+# BUILD DIRECTORIES
+#
+#######################################
+
+BUILD_DIR = ../../build
+
+OBJECTS_DIR = $${BUILD_DIR}/$${REL_OBJECTS_DIR}
+!win32:DESTDIR = $${BUILD_DIR}/$${REL_DESTDIR}/lib
+win32:DESTDIR = $${BUILD_DIR}/$${REL_DESTDIR}
+
+#
+# LIBS
+#
+#######################################
+
+win32:LIBS *= $${DESTDIR}/$${LIB_GEOMETRY}$${LIBVERSION}.lib \
+ $${DESTDIR}/$${LIB_IMAGE}$${LIBVERSION}.lib \
+ $${DESTDIR}/$${LIB_SCENE_GRAPH}$${LIBVERSION}.lib \
+ $${DESTDIR}/$${LIB_SYSTEM}$${LIBVERSION}.lib \
+ $${DESTDIR}/$${LIB_WINGED_EDGE}$${LIBVERSION}.lib
+
+!win32 {
+ lib_bundle {
+ LIBS += -F$${DESTDIR} -framework $${LIB_GEOMETRY} \
+ -framework $${LIB_IMAGE} -framework $${LIB_SCENE_GRAPH} \
+ -framework $${LIB_SYSTEM} -framework $${LIB_WINGED_EDGE}
+ } else {
+ LIBS *= -L$${DESTDIR} -l$${LIB_GEOMETRY} -l$${LIB_IMAGE} -l$${LIB_SCENE_GRAPH} \
+ -l$${LIB_SYSTEM} -l$${LIB_WINGED_EDGE}
+ }
+}
+
+
+#
+# INSTALL
+#
+#######################################
+
+LIB_DIR = ../../lib
+# install library
+target.path = $$LIB_DIR
+# "make install" configuration options
+INSTALLS += target
+
+#
+# SOURCES & HEADERS
+#
+#######################################
+
+!static {
+ include(src.pri)
+}