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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/SConscript1
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/SConscript2
-rw-r--r--source/blender/blenkernel/intern/material.c1
-rw-r--r--source/blender/blenkernel/intern/scene.c10
-rw-r--r--source/blender/blenloader/intern/readfile.c5
-rw-r--r--source/blender/blenloader/intern/writefile.c9
-rw-r--r--source/blender/editors/CMakeLists.txt1
-rw-r--r--source/blender/editors/render/SConscript2
-rw-r--r--source/blender/editors/render/render_intern.h4
-rw-r--r--source/blender/editors/render/render_ops.c5
-rw-r--r--source/blender/editors/render/render_shading.c122
-rw-r--r--source/blender/editors/space_outliner/outliner.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c4
-rw-r--r--source/blender/editors/transform/transform.c6
-rw-r--r--source/blender/editors/transform/transform_orientations.c1
-rw-r--r--source/blender/freestyle/CMakeLists.txt42
-rw-r--r--source/blender/freestyle/FRS_freestyle.h38
-rw-r--r--source/blender/freestyle/FRS_freestyle_config.h17
-rw-r--r--source/blender/freestyle/SConscript86
-rwxr-xr-xsource/blender/freestyle/intern/application/AppCanvas.cpp190
-rwxr-xr-xsource/blender/freestyle/intern/application/AppCanvas.h70
-rwxr-xr-xsource/blender/freestyle/intern/application/AppConfig.cpp92
-rwxr-xr-xsource/blender/freestyle/intern/application/AppConfig.h105
-rw-r--r--source/blender/freestyle/intern/application/AppView.cpp180
-rw-r--r--source/blender/freestyle/intern/application/AppView.h226
-rwxr-xr-xsource/blender/freestyle/intern/application/Controller.cpp882
-rwxr-xr-xsource/blender/freestyle/intern/application/Controller.h235
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp427
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h84
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp336
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h44
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp71
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h23
-rw-r--r--source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp349
-rwxr-xr-xsource/blender/freestyle/intern/geometry/BBox.h141
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Bezier.cpp118
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Bezier.h73
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FastGrid.cpp62
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FastGrid.h85
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FitCurve.cpp603
-rwxr-xr-xsource/blender/freestyle/intern/geometry/FitCurve.h101
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Geom.h78
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomCleaner.cpp240
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomCleaner.h219
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomUtils.cpp753
-rwxr-xr-xsource/blender/freestyle/intern/geometry/GeomUtils.h310
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Grid.cpp388
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Grid.h363
-rwxr-xr-xsource/blender/freestyle/intern/geometry/HashGrid.cpp41
-rwxr-xr-xsource/blender/freestyle/intern/geometry/HashGrid.h109
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Noise.cpp264
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Noise.h77
-rwxr-xr-xsource/blender/freestyle/intern/geometry/Polygon.h215
-rwxr-xr-xsource/blender/freestyle/intern/geometry/SweepLine.h336
-rwxr-xr-xsource/blender/freestyle/intern/geometry/VecMat.h899
-rwxr-xr-xsource/blender/freestyle/intern/geometry/matrix_util.cpp265
-rwxr-xr-xsource/blender/freestyle/intern/geometry/matrix_util.h69
-rwxr-xr-xsource/blender/freestyle/intern/geometry/normal_cycle.cpp103
-rwxr-xr-xsource/blender/freestyle/intern/geometry/normal_cycle.h97
-rwxr-xr-xsource/blender/freestyle/intern/image/GaussianFilter.cpp96
-rwxr-xr-xsource/blender/freestyle/intern/image/GaussianFilter.h146
-rwxr-xr-xsource/blender/freestyle/intern/image/Image.h389
-rwxr-xr-xsource/blender/freestyle/intern/image/ImagePyramid.cpp166
-rwxr-xr-xsource/blender/freestyle/intern/image/ImagePyramid.h92
-rw-r--r--source/blender/freestyle/intern/python/BPy_BBox.cpp100
-rw-r--r--source/blender/freestyle/intern/python/BPy_BBox.h38
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp166
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp193
-rw-r--r--source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp262
-rw-r--r--source/blender/freestyle/intern/python/BPy_ContextFunctions.h18
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.cpp609
-rw-r--r--source/blender/freestyle/intern/python/BPy_Convert.h147
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.cpp125
-rw-r--r--source/blender/freestyle/intern/python/BPy_Freestyle.h22
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp599
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsMaterial.h37
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.cpp274
-rw-r--r--source/blender/freestyle/intern/python/BPy_FrsNoise.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.cpp222
-rw-r--r--source/blender/freestyle/intern/python/BPy_Id.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.cpp248
-rw-r--r--source/blender/freestyle/intern/python/BPy_IntegrationType.h28
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface0D.cpp354
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface0D.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface1D.cpp337
-rw-r--r--source/blender/freestyle/intern/python/BPy_Interface1D.h36
-rw-r--r--source/blender/freestyle/intern/python/BPy_Iterator.cpp229
-rw-r--r--source/blender/freestyle/intern/python/BPy_Iterator.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_MediumType.cpp97
-rw-r--r--source/blender/freestyle/intern/python/BPy_MediumType.h42
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.cpp296
-rw-r--r--source/blender/freestyle/intern/python/BPy_Nature.h33
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.cpp612
-rw-r--r--source/blender/freestyle/intern/python/BPy_Operators.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.cpp297
-rw-r--r--source/blender/freestyle/intern/python/BPy_SShape.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp658
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeAttribute.h35
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.cpp297
-rw-r--r--source/blender/freestyle/intern/python/BPy_StrokeShader.h40
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp126
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp117
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp184
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp230
-rw-r--r--source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewMap.cpp195
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewMap.h34
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.cpp340
-rw-r--r--source/blender/freestyle/intern/python/BPy_ViewShape.h35
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp77
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp79
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp78
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp78
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp90
-rw-r--r--source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/Director.cpp304
-rw-r--r--source/blender/freestyle/intern/python/Director.h49
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp289
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp314
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h32
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp193
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp399
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp152
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp248
-rw-r--r--source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp428
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp200
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp490
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp461
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h32
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp169
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp303
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h31
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp205
-rw-r--r--source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h31
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp165
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h32
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp203
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h35
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp129
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp234
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp169
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h32
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp149
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp179
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp194
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp264
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h33
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp138
-rw-r--r--source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h34
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp89
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp91
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp111
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp90
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp96
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp94
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp88
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp94
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp96
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp104
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp94
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp95
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp88
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp106
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp100
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp115
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp104
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp90
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp101
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp89
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp88
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h31
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp82
-rw-r--r--source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h31
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp213
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp157
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp187
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp156
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp158
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp157
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp163
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp157
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp162
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp163
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp90
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp85
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp90
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp85
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp91
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp89
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp93
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp90
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp85
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp287
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp208
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h36
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp201
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp208
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp214
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp208
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp225
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h37
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp220
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h34
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp97
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp94
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp107
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp108
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp112
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp93
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp105
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp105
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp93
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp91
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp92
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp99
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp97
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp97
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp84
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp82
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp82
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp82
-rw-r--r--source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h30
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp76
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp76
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp77
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp93
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp87
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp79
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp76
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp90
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp90
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h29
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp76
-rw-r--r--source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h29
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLBBoxRenderer.cpp108
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLBBoxRenderer.h59
-rw-r--r--source/blender/freestyle/intern/rendering/GLBlendEquation.cpp9
-rw-r--r--source/blender/freestyle/intern/rendering/GLBlendEquation.h16
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLDebugRenderer.cpp201
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLDebugRenderer.h182
-rw-r--r--source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.cpp27
-rw-r--r--source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.h23
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLMonoColorRenderer.cpp43
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLMonoColorRenderer.h60
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLRenderer.cpp467
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLRenderer.h204
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLSelectRenderer.cpp159
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLSelectRenderer.h85
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp474
-rwxr-xr-xsource/blender/freestyle/intern/rendering/GLStrokeRenderer.h88
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/DrawingStyle.h82
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/FrsMaterial.h304
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp321
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/IndexedFaceSet.h222
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/LineRep.cpp58
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/LineRep.h130
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/Node.h97
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.cpp120
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeCamera.h192
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp34
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h70
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeGroup.cpp122
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeGroup.h84
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeLight.cpp80
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeLight.h86
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeShape.cpp51
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeShape.h89
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeTransform.cpp166
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/NodeTransform.h107
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp31
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/OrientedLineRep.h67
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/Rep.cpp1
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/Rep.h127
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp86
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h105
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/SceneVisitor.cpp1
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/SceneVisitor.h98
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/TriangleRep.cpp59
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/TriangleRep.h106
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/VertexRep.cpp29
-rwxr-xr-xsource/blender/freestyle/intern/scene_graph/VertexRep.h87
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp92
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions0D.h209
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp110
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedFunctions1D.h288
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedPredicates1D.h84
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp431
-rwxr-xr-xsource/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h222
-rwxr-xr-xsource/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp1160
-rwxr-xr-xsource/blender/freestyle/intern/stroke/BasicStrokeShaders.h890
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Canvas.cpp454
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Canvas.h196
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Chain.cpp126
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Chain.h86
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ChainingIterators.cpp170
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ChainingIterators.h394
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ContextFunctions.cpp60
-rwxr-xr-xsource/blender/freestyle/intern/stroke/ContextFunctions.h124
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Curve.cpp818
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Curve.h467
-rwxr-xr-xsource/blender/freestyle/intern/stroke/CurveAdvancedIterators.h378
-rwxr-xr-xsource/blender/freestyle/intern/stroke/CurveIterators.h299
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Modifiers.h71
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Module.h72
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Operators.cpp1024
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Operators.h311
-rwxr-xr-xsource/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp89
-rwxr-xr-xsource/blender/freestyle/intern/stroke/PSStrokeRenderer.h63
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Predicates0D.h172
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Predicates1D.h483
-rwxr-xr-xsource/blender/freestyle/intern/stroke/QInformationMap.h58
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Stroke.cpp953
-rwxr-xr-xsource/blender/freestyle/intern/stroke/Stroke.h588
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h142
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeIO.cpp55
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeIO.h47
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeIterators.h229
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeLayer.cpp55
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeLayer.h75
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRenderer.cpp121
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRenderer.h132
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRep.cpp820
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeRep.h138
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeShader.h124
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeTesselator.cpp88
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StrokeTesselator.h67
-rwxr-xr-xsource/blender/freestyle/intern/stroke/StyleModule.h157
-rwxr-xr-xsource/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp73
-rwxr-xr-xsource/blender/freestyle/intern/stroke/TextStrokeRenderer.h68
-rwxr-xr-xsource/blender/freestyle/intern/system/BaseIterator.h90
-rwxr-xr-xsource/blender/freestyle/intern/system/BaseObject.cpp1
-rwxr-xr-xsource/blender/freestyle/intern/system/BaseObject.h73
-rwxr-xr-xsource/blender/freestyle/intern/system/Cast.h44
-rwxr-xr-xsource/blender/freestyle/intern/system/Exception.cpp24
-rwxr-xr-xsource/blender/freestyle/intern/system/Exception.h64
-rwxr-xr-xsource/blender/freestyle/intern/system/FreestyleConfig.h90
-rwxr-xr-xsource/blender/freestyle/intern/system/Id.h126
-rwxr-xr-xsource/blender/freestyle/intern/system/Interpreter.h56
-rw-r--r--source/blender/freestyle/intern/system/Iterator.cpp1
-rw-r--r--source/blender/freestyle/intern/system/Iterator.h41
-rwxr-xr-xsource/blender/freestyle/intern/system/Precision.h39
-rwxr-xr-xsource/blender/freestyle/intern/system/ProgressBar.h85
-rwxr-xr-xsource/blender/freestyle/intern/system/PseudoNoise.cpp108
-rwxr-xr-xsource/blender/freestyle/intern/system/PseudoNoise.h58
-rwxr-xr-xsource/blender/freestyle/intern/system/PythonInterpreter.cpp25
-rwxr-xr-xsource/blender/freestyle/intern/system/PythonInterpreter.h158
-rwxr-xr-xsource/blender/freestyle/intern/system/RandGen.cpp86
-rwxr-xr-xsource/blender/freestyle/intern/system/RandGen.h48
-rwxr-xr-xsource/blender/freestyle/intern/system/StringUtils.cpp74
-rwxr-xr-xsource/blender/freestyle/intern/system/StringUtils.h62
-rwxr-xr-xsource/blender/freestyle/intern/system/TimeStamp.cpp25
-rwxr-xr-xsource/blender/freestyle/intern/system/TimeStamp.h71
-rwxr-xr-xsource/blender/freestyle/intern/system/TimeUtils.h58
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.cpp700
-rwxr-xr-xsource/blender/freestyle/intern/view_map/FEdgeXDetector.h153
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions0D.cpp365
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions0D.h500
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions1D.cpp231
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Functions1D.h555
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Interface0D.h360
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Interface1D.h226
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.cpp370
-rwxr-xr-xsource/blender/freestyle/intern/view_map/Silhouette.h1429
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp266
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h123
-rwxr-xr-xsource/blender/freestyle/intern/view_map/SteerableViewMap.cpp268
-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.h215
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMap.cpp703
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMap.h1492
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h691
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapBuilder.cpp1064
-rwxr-xr-xsource/blender/freestyle/intern/view_map/ViewMapBuilder.h226
-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.h549
-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/winged_edge/Curvature.cpp648
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/Curvature.h156
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/Nature.h75
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WEdge.cpp732
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WEdge.h955
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WFillGrid.cpp60
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WFillGrid.h80
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WSFillGrid.cpp60
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WSFillGrid.h79
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdge.cpp296
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdge.h582
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp43
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h51
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp362
-rwxr-xr-xsource/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h160
-rw-r--r--source/blender/makesdna/DNA_freestyle_types.h31
-rw-r--r--source/blender/makesdna/DNA_material_types.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h6
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c80
-rw-r--r--source/blender/python/CMakeLists.txt1
-rw-r--r--source/blender/python/SConscript1
-rw-r--r--source/blender/python/doc/sphinx_doc_gen.py14
-rw-r--r--source/blender/python/intern/bpy.c3
-rw-r--r--source/blender/render/CMakeLists.txt2
-rw-r--r--source/blender/render/SConscript2
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h1
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/source/pipeline.c88
-rw-r--r--source/blender/render/intern/source/shadeinput.c5
-rw-r--r--source/blender/render/intern/source/shadeoutput.c2
555 files changed, 77974 insertions, 25 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 16437737302..5e1ea753ace 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -42,6 +42,7 @@ ADD_SUBDIRECTORY(readblenfile)
ADD_SUBDIRECTORY(render)
ADD_SUBDIRECTORY(blenfont)
ADD_SUBDIRECTORY(ikplugin)
+ADD_SUBDIRECTORY(freestyle)
IF(WITH_OPENEXR)
ADD_SUBDIRECTORY(imbuf/intern/openexr)
diff --git a/source/blender/SConscript b/source/blender/SConscript
index 98e8ad73199..834e83ec0e1 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -9,6 +9,7 @@ SConscript(['avi/SConscript',
'blenpluginapi/SConscript',
'gpu/SConscript',
'editors/SConscript',
+ 'freestyle/SConscript',
'imbuf/SConscript',
'imbuf/intern/cineon/SConscript',
'makesdna/SConscript',
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index afb29fbcd62..1ad0ddf0520 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -30,7 +30,7 @@ SET(INC
. ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../modifiers
../render/extern/include ../../../intern/decimation/extern
../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern
- ../../../intern/iksolver/extern ../blenloader ../ikplugin
+ ../../../intern/iksolver/extern ../blenloader ../ikplugin ../freestyle
../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern
../../../intern/bsp/extern ../blenfont
../../../intern/audaspace/intern
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 57d7e45d986..ac10889f36a 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -7,7 +7,7 @@ incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include'
incs += ' ../blenlib ../blenfont ../makesdna ../windowmanager'
incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna'
incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
-incs += ' #/intern/iksolver/extern ../blenloader'
+incs += ' #/intern/iksolver/extern ../blenloader ../freestyle'
incs += ' #/extern/bullet2/src'
incs += ' #/intern/opennl/extern #/intern/bsp/extern'
incs += ' ../gpu #/extern/glew/include'
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index f3096cdf8f2..cf02f49a6f3 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -140,6 +140,7 @@ void init_material(Material *ma)
ma->tx_limit= 0.0;
ma->tx_falloff= 1.0;
ma->shad_alpha= 1.0f;
+ ma->vcol_alpha= 0;
ma->gloss_mir = ma->gloss_tra= 1.0;
ma->samp_gloss_mir = ma->samp_gloss_tra= 18;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index e5d9686a18d..58a778e8c6e 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -77,6 +77,8 @@
#include "BLI_math.h"
#include "BLI_blenlib.h"
+#include "FRS_freestyle_config.h"
+
//XXX #include "nla.h"
#ifdef WIN32
@@ -226,7 +228,8 @@ Scene *copy_scene(Main *bmain, Scene *sce, int type)
void free_scene(Scene *sce)
{
Base *base;
-
+ SceneRenderLayer *srl;
+
base= sce->base.first;
while(base) {
base->object->id.us--;
@@ -266,6 +269,10 @@ void free_scene(Scene *sce)
sce->r.ffcodecdata.properties = NULL;
}
+ for(srl= sce->r.layers.first; srl; srl= srl->next) {
+ BLI_freelistN( &srl->freestyleConfig.modules);
+ }
+
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->transform_spaces);
BLI_freelistN(&sce->r.layers);
@@ -1018,6 +1025,7 @@ void scene_add_render_layer(Scene *sce)
srl->lay= (1<<20) -1;
srl->layflag= 0x7FFF; /* solid ztra halo edge strand */
srl->passflag= SCE_PASS_COMBINED|SCE_PASS_Z;
+ FRS_add_freestyle_config( srl );
}
/* render simplification */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 60d4ce4994f..ef33c0aa859 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4228,6 +4228,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
Editing *ed;
Sequence *seq;
MetaStack *ms;
+ SceneRenderLayer *srl;
sce->theDag = NULL;
sce->dagisvalid = 0;
@@ -4401,6 +4402,10 @@ static void direct_link_scene(FileData *fd, Scene *sce)
link_list(fd, &(sce->transform_spaces));
link_list(fd, &(sce->r.layers));
+ for(srl= sce->r.layers.first; srl; srl= srl->next) {
+ link_list(fd, &(srl->freestyleConfig.modules));
+ }
+
sce->nodetree= newdataadr(fd, sce->nodetree);
if(sce->nodetree)
direct_link_nodetree(fd, sce->nodetree);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 2b32bbdf0c1..f164a44c10b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1781,6 +1781,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
TimeMarker *marker;
TransformOrientation *ts;
SceneRenderLayer *srl;
+ FreestyleModuleConfig *fmc;
ToolSettings *tos;
sce= scebase->first;
@@ -1905,8 +1906,14 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
for(ts = sce->transform_spaces.first; ts; ts = ts->next)
writestruct(wd, DATA, "TransformOrientation", 1, ts);
- for(srl= sce->r.layers.first; srl; srl= srl->next)
+ for(srl= sce->r.layers.first; srl; srl= srl->next) {
writestruct(wd, DATA, "SceneRenderLayer", 1, srl);
+
+ for(fmc= srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ writestruct(wd, DATA, "FreestyleModuleConfig", 1, fmc);
+ }
+
+ }
if(sce->nodetree) {
writestruct(wd, DATA, "bNodeTree", 1, sce->nodetree);
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 86085aa0573..58a52f7041d 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -39,6 +39,7 @@ SET(INC ../windowmanager
../../../intern/audaspace/intern
../nodes
../gpu
+ ../freestyle
../blenfont
../ikplugin
)
diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript
index 2b9737557cd..5526194eab4 100644
--- a/source/blender/editors/render/SConscript
+++ b/source/blender/editors/render/SConscript
@@ -5,7 +5,7 @@ sources = env.Glob('*.c')
incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf'
incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include'
-incs += ' ../../gpu'
+incs += ' ../../gpu ../../freestyle'
incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern'
incs += ' ../../blenloader'
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index a0441155629..11c2ff6e6f4 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -50,6 +50,10 @@ void MATERIAL_OT_paste(struct wmOperatorType *ot);
void SCENE_OT_render_layer_add(struct wmOperatorType *ot);
void SCENE_OT_render_layer_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_add(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_remove(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_move_up(struct wmOperatorType *ot);
+void SCENE_OT_freestyle_module_move_down(struct wmOperatorType *ot);
void TEXTURE_OT_slot_copy(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_ops.c b/source/blender/editors/render/render_ops.c
index b1cb1d9c2f1..b3375bcc371 100644
--- a/source/blender/editors/render/render_ops.c
+++ b/source/blender/editors/render/render_ops.c
@@ -57,6 +57,11 @@ void ED_operatortypes_render(void)
WM_operatortype_append(SCENE_OT_render_layer_add);
WM_operatortype_append(SCENE_OT_render_layer_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_module_add);
+ WM_operatortype_append(SCENE_OT_freestyle_module_remove);
+ WM_operatortype_append(SCENE_OT_freestyle_module_move_up);
+ WM_operatortype_append(SCENE_OT_freestyle_module_move_down);
+
#if (defined(WITH_QUICKTIME) && !defined(USE_QTKIT))
WM_operatortype_append(SCENE_OT_render_data_set_quicktime_codec);
#endif
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index efd579735e0..75a220d0e50 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -65,6 +65,8 @@
#include "GPU_material.h"
+#include "FRS_freestyle.h"
+
#include "RNA_access.h"
#include "WM_api.h"
@@ -705,6 +707,126 @@ void SCENE_OT_render_layer_remove(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+static int freestyle_module_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+
+ FRS_add_module(&srl->freestyleConfig);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Add Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_add";
+ ot->description="Add a style module into the list of modules.";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_add_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_module_remove_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module= ptr.data;
+
+ FRS_delete_module(&srl->freestyleConfig, module);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_remove";
+ ot->description="Remove the style module from the stack.";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_remove_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int freestyle_module_move_up_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module= ptr.data;
+ int active = RNA_boolean_get(op->ptr, "active");
+
+ if(active)
+ FRS_move_up_module(&srl->freestyleConfig, module);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_move_up(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Up Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_move_up";
+ ot->description="Move the style module up in the stack.";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_move_up_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "active", 0, "Active", "True if the operator is enabled.");
+}
+
+static int freestyle_module_move_down_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ SceneRenderLayer *srl = (SceneRenderLayer*) BLI_findlink(&scene->r.layers, scene->r.actlay);
+ PointerRNA ptr= CTX_data_pointer_get_type(C, "freestyle_module", &RNA_FreestyleModuleSettings);
+ FreestyleModuleConfig *module= ptr.data;
+ int active = RNA_boolean_get(op->ptr, "active");
+
+ if(active)
+ FRS_move_down_module(&srl->freestyleConfig, module);
+
+ WM_event_add_notifier(C, NC_SCENE|ND_RENDER_OPTIONS, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_freestyle_module_move_down(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Move Down Freestyle Module";
+ ot->idname= "SCENE_OT_freestyle_module_move_down";
+ ot->description="Move the style module down in the stack.";
+
+ /* api callbacks */
+ ot->exec= freestyle_module_move_down_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* props */
+ RNA_def_boolean(ot->srna, "active", 0, "Active", "True if the operator is enabled.");
+}
+
static int texture_slot_move(bContext *C, wmOperator *op)
{
ID *id= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index 291c67d22ff..40a671c1306 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -4352,11 +4352,6 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa
int active;
for(te= lb->first; te; te= te->next) {
-
- /* exit drawing early */
- if((*offsx) - OL_X > xmax)
- break;
-
tselem= TREESTORE(te);
/* object hierarchy always, further constrained on level */
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 6f97bc04395..4e41314ef20 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -747,7 +747,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
/* api callbacks */
ot->invoke= viewrotate_invoke;
ot->modal= viewrotate_modal;
- ot->poll= ED_operator_view3d_rotate;
+ ot->poll= ED_operator_view3d_active;
/* flags */
ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER;
@@ -1992,7 +1992,7 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
/* api callbacks */
ot->exec= vieworbit_exec;
- ot->poll= ED_operator_view3d_rotate;
+ ot->poll= ED_operator_view3d_active;
/* flags */
ot->flag= 0;
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index e4061a30af1..df024a4b3d9 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -537,9 +537,6 @@ int transformEvent(TransInfo *t, wmEvent *event)
if (event->type == MOUSEMOVE)
{
- if (t->modifiers & MOD_CONSTRAINT_SELECT)
- t->con.mode |= CON_SELECT;
-
t->mval[0] = event->x - t->ar->winrct.xmin;
t->mval[1] = event->y - t->ar->winrct.ymin;
@@ -1670,6 +1667,9 @@ void transformApply(const bContext *C, TransInfo *t)
{
if ((t->redraw & TREDRAW_HARD) || (t->draw_handle_apply == NULL && (t->redraw & TREDRAW_SOFT)))
{
+ if (t->modifiers & MOD_CONSTRAINT_SELECT)
+ t->con.mode |= CON_SELECT;
+
selectConstraint(t);
if (t->transform) {
t->transform(t, t->mval); // calls recalcData()
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index d509ce97015..253f6689e1d 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -510,7 +510,6 @@ void initTransformOrientation(bContext *C, TransInfo *t)
switch(t->current_orientation) {
case V3D_MANIP_GLOBAL:
- unit_m3(t->spacemtx);
strcpy(t->spacename, "global");
break;
diff --git a/source/blender/freestyle/CMakeLists.txt b/source/blender/freestyle/CMakeLists.txt
new file mode 100644
index 00000000000..18f721ccfdc
--- /dev/null
+++ b/source/blender/freestyle/CMakeLists.txt
@@ -0,0 +1,42 @@
+# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# 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.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Jacques Beaurain.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+FILE(GLOB_RECURSE SRC *.cpp)
+
+SET(INC
+ ../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna
+ ../python ../python/intern
+ ../render/extern/include ../render/intern/include ../include ../src
+ ../../../extern/glew/include ../../../intern/guardedalloc ../freestyle
+ ${PYTHON_INC}
+ ${PNG_INC}
+)
+
+IF(WIN32)
+ SET(INC ${INC} ${PTHREADS_INC})
+ENDIF(WIN32)
+
+BLENDERLIB(bf_freestyle "${SRC}" "${INC}")
diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h
new file mode 100644
index 00000000000..cd07d2dfc11
--- /dev/null
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -0,0 +1,38 @@
+#ifndef FRS_FREESTYLE_H
+#define FRS_FREESTYLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "DNA_listBase.h"
+ #include "DNA_scene_types.h"
+
+ #include "BKE_context.h"
+
+ extern Scene *freestyle_scene;
+ extern float freestyle_viewpoint[3];
+ extern float freestyle_mv[4][4];
+ extern float freestyle_proj[4][4];
+ extern int freestyle_viewport[4];
+
+ // Rendering
+ void FRS_initialize();
+ void FRS_set_context(bContext* C);
+ int FRS_is_freestyle_enabled(struct SceneRenderLayer* srl);
+ void FRS_init_stroke_rendering(struct Render* re);
+ struct Render* FRS_do_stroke_rendering(struct Render* re, struct SceneRenderLayer* srl);
+ void FRS_composite_result(struct Render* re, struct SceneRenderLayer* srl, struct Render* freestyle_render);
+ void FRS_exit();
+
+ // Panel configuration
+ void FRS_add_module(FreestyleConfig *config);
+ void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+ void FRS_move_up_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+ void FRS_move_down_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/freestyle/FRS_freestyle_config.h b/source/blender/freestyle/FRS_freestyle_config.h
new file mode 100644
index 00000000000..86a05d1aa22
--- /dev/null
+++ b/source/blender/freestyle/FRS_freestyle_config.h
@@ -0,0 +1,17 @@
+#ifndef FRS_FREESTYLE_CONFIG_H
+#define FRS_FREESTYLE_CONFIG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "DNA_scene_types.h"
+
+ void FRS_add_freestyle_config( SceneRenderLayer* srl );
+ void FRS_free_freestyle_config( SceneRenderLayer* srl );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/source/blender/freestyle/SConscript b/source/blender/freestyle/SConscript
new file mode 100644
index 00000000000..eefee0cc2c4
--- /dev/null
+++ b/source/blender/freestyle/SConscript
@@ -0,0 +1,86 @@
+#!/usr/bin/python
+import sys
+Import ('env')
+
+sources = []
+defs = []
+incs = ''
+
+incs += '../blenkernel ../blenloader ../blenlib ../imbuf ../makesdna ../makesrna'
+incs += ' ../python ../python/intern'
+incs += ' ../render/extern/include ../render/intern/include ../include ../src'
+incs += ' #/extern/glew/include #/intern/guardedalloc ../freestyle'
+incs += ' ' + env['BF_PYTHON_INC']
+incs += ' ' + env['BF_PNG_INC']
+
+
+if env['OURPLATFORM'] == 'linux2':
+ cflags='-pthread'
+ incs += ' ../../../extern/binreloc/include'
+
+if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
+ incs += ' ' + env['BF_PTHREADS_INC']
+
+########################################################
+# folders sources
+########################################################
+
+# system
+prefix = 'intern/system'
+system_sources = env.Glob(prefix + '/*.cpp')
+
+# image
+prefix = 'intern/image'
+image_sources = env.Glob(prefix + '/*.cpp')
+
+# geometry
+prefix = 'intern/geometry'
+geometry_sources = env.Glob(prefix + '/*.cpp')
+
+# scene_graph
+prefix = 'intern/scene_graph'
+scene_graph_sources = env.Glob(prefix + '/*.cpp')
+
+# winged_edge
+prefix = 'intern/winged_edge'
+winged_edge_sources = env.Glob(prefix + '/*.cpp')
+
+# view_map
+prefix = 'intern/view_map'
+view_map_sources = env.Glob(prefix + '/*.cpp')
+
+# stroke
+prefix = 'intern/stroke'
+stroke_sources = env.Glob(prefix + '/*.cpp')
+
+# rendering
+prefix = 'intern/rendering'
+rendering_sources = env.Glob(prefix + '/GL*.cpp')
+
+# application
+prefix = 'intern/application'
+application_sources = env.Glob(prefix + '/*.cpp')
+
+# blender_interface
+prefix = 'intern/blender_interface'
+interface_sources = env.Glob(prefix + '/*.cpp')
+
+# Python
+prefix = 'intern/python'
+python_sources = env.Glob(prefix + '/*.cpp') \
+ + env.Glob(prefix + '/*/*.cpp') \
+ + env.Glob(prefix + '/*/*/*.cpp') \
+ + env.Glob(prefix + '/*/*/*/*.cpp')
+
+sources = system_sources + image_sources + geometry_sources + scene_graph_sources \
+ + winged_edge_sources + view_map_sources + stroke_sources + rendering_sources \
+ + application_sources + interface_sources + python_sources
+
+env.BlenderLib (libname="bf_freestyle",
+ sources=sources,
+ includes=Split(incs),
+ defines=defs,
+ libtype=['core'],
+ priority = [370] # bf_python is 361
+ )
+
diff --git a/source/blender/freestyle/intern/application/AppCanvas.cpp b/source/blender/freestyle/intern/application/AppCanvas.cpp
new file mode 100755
index 00000000000..3844cf2195a
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppCanvas.cpp
@@ -0,0 +1,190 @@
+
+//
+// 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 "Controller.h"
+#include "../rendering/GLBlendEquation.h"
+#include "AppView.h"
+#include "../image/Image.h"
+#include "../system/TimeStamp.h"
+#include "../stroke/StrokeRenderer.h"
+#include "AppCanvas.h"
+#include "../rendering/GLRenderer.h"
+#include "../rendering/GLStrokeRenderer.h"
+#include "AppConfig.h"
+
+#include "../system/StringUtils.h"
+
+AppCanvas::AppCanvas()
+:Canvas()
+{
+ _pViewer = 0;
+ _MapsPath = StringUtils::toAscii( Config::Path::getInstance()->getMapsDir() ).c_str();
+}
+
+AppCanvas::AppCanvas(AppView* iViewer)
+:Canvas()
+{
+ _pViewer = iViewer;
+}
+
+AppCanvas::AppCanvas(const AppCanvas& iBrother)
+:Canvas(iBrother)
+{
+ _pViewer = iBrother._pViewer;
+}
+
+AppCanvas::~AppCanvas()
+{
+ _pViewer = 0;
+}
+
+void AppCanvas::setViewer(AppView *iViewer)
+{
+ _pViewer = iViewer;
+}
+
+int AppCanvas::width() const
+{
+ return _pViewer->width();
+}
+
+int AppCanvas::height() const
+{
+ return _pViewer->height();
+}
+
+BBox<Vec2i> AppCanvas::border() const
+{
+ return _pViewer->border();
+}
+
+BBox<Vec3r> AppCanvas::scene3DBBox() const
+{
+ return _pViewer->scene3DBBox();
+}
+
+void AppCanvas::preDraw()
+{
+ Canvas::preDraw();
+}
+
+void AppCanvas::init()
+{
+
+ // static bool firsttime = true;
+ // if (firsttime) {
+ //
+ // _Renderer = new BlenderStrokeRenderer;
+ // if(!StrokeRenderer::loadTextures())
+ // {
+ // cerr << "unable to load stroke textures" << endl;
+ // return;
+ // }
+ // }
+}
+
+void AppCanvas::postDraw()
+{
+ Canvas::postDraw();
+}
+
+void AppCanvas::Erase()
+{
+ Canvas::Erase();
+}
+
+// Abstract
+
+void AppCanvas::readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const
+{
+ float *rgb = new float[3*w*h];
+ memset(rgb, 0, sizeof(float) * 3 * w * h);
+ int xsch = width();
+ int ysch = height();
+ if (_pass_diffuse.buf) {
+ int xmin = border().getMin().x();
+ int ymin = border().getMin().y();
+ int xmax = border().getMax().x();
+ int ymax = border().getMax().y();
+ int rectx = _pass_z.width;
+ int recty = _pass_z.height;
+ float xfac = ((float)rectx) / ((float)(xmax - xmin));
+ float yfac = ((float)recty) / ((float)(ymax - ymin));
+ //printf("readColorPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y, xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f));
+ int ii, jj;
+ for (int j = 0; j < h; j++) {
+ jj = (int)((y - ymin + j) * yfac);
+ if (jj < 0 || jj >= recty)
+ continue;
+ for (int i = 0; i < w; i++) {
+ ii = (int)((x - xmin + i) * xfac);
+ if (ii < 0 || ii >= rectx)
+ continue;
+ memcpy(rgb + (w * j + i) * 3, _pass_diffuse.buf + (rectx * jj + ii) * 3, sizeof(float) * 3);
+ }
+ }
+ }
+ oImage.setArray(rgb, xsch, ysch, w, h, x, y, false);
+}
+
+void AppCanvas::readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const
+{
+ float *z = new float[w*h];
+ memset(z, 0, sizeof(float) * w * h);
+ int xsch = width();
+ int ysch = height();
+ if (_pass_z.buf) {
+ int xmin = border().getMin().x();
+ int ymin = border().getMin().y();
+ int xmax = border().getMax().x();
+ int ymax = border().getMax().y();
+ int rectx = _pass_z.width;
+ int recty = _pass_z.height;
+ float xfac = ((float)rectx) / ((float)(xmax - xmin));
+ float yfac = ((float)recty) / ((float)(ymax - ymin));
+ //printf("readDepthPixels %d x %d @ (%d, %d) in %d x %d [%d x %d] -- %d x %d @ %d%%\n", w, h, x, y, xsch, ysch, xmax - xmin, ymax - ymin, rectx, recty, (int)(xfac * 100.0f));
+ int ii, jj;
+ for (int j = 0; j < h; j++) {
+ jj = (int)((y - ymin + j) * yfac);
+ if (jj < 0 || jj >= recty)
+ continue;
+ for (int i = 0; i < w; i++) {
+ ii = (int)((x - xmin + i) * xfac);
+ if (ii < 0 || ii >= rectx)
+ continue;
+ z[w * j + i] = _pass_z.buf[rectx * jj + ii];
+ }
+ }
+ }
+ oImage.setArray(z, xsch, ysch, w, h, x, y, false);
+}
+
+void AppCanvas::RenderStroke(Stroke *iStroke) {
+
+ if(_basic)
+ iStroke->RenderBasic(_Renderer);
+ else
+ iStroke->Render(_Renderer);
+}
+
+
+void AppCanvas::update() {}
+
diff --git a/source/blender/freestyle/intern/application/AppCanvas.h b/source/blender/freestyle/intern/application/AppCanvas.h
new file mode 100755
index 00000000000..42b3c7fdb50
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppCanvas.h
@@ -0,0 +1,70 @@
+#ifndef ARTCANVAS_H
+#define ARTCANVAS_H
+
+#include "../stroke/Canvas.h"
+#include "AppView.h"
+
+class AppCanvas : public Canvas
+{
+
+public:
+ AppCanvas();
+ AppCanvas(AppView *iViewer);
+ AppCanvas(const AppCanvas& iBrother);
+ virtual ~AppCanvas();
+
+ /*! operations that need to be done before a draw */
+ virtual void preDraw();
+
+ /*! operations that need to be done after a draw */
+ virtual void postDraw();
+
+ /*! Erases the layers and clears the canvas */
+ virtual void Erase();
+
+ /* init the canvas */
+ virtual void init();
+
+ /*! Reads a pixel area from the canvas */
+ virtual void readColorPixels(int x,int y,int w, int h, RGBImage& oImage) const;
+ /*! Reads a depth pixel area from the canvas */
+ virtual void readDepthPixels(int x,int y,int w, int h, GrayImage& oImage) const;
+
+ virtual BBox<Vec3r> scene3DBBox() const ;
+
+ // abstract
+ virtual void RenderStroke(Stroke*);
+ virtual void update();
+
+
+ /*! accessors */
+ virtual int width() const ;
+ virtual int height() const ;
+ virtual BBox<Vec2i> border() const ;
+
+ AppView *_pViewer;
+ inline const AppView * viewer() const {return _pViewer;}
+
+ /*! modifiers */
+ void setViewer(AppView *iViewer) ;
+
+ // soc
+ void setPassDiffuse(float *buf, int width, int height) {
+ _pass_diffuse.buf = buf;
+ _pass_diffuse.width = width;
+ _pass_diffuse.height = height;
+ }
+ void setPassZ(float *buf, int width, int height) {
+ _pass_z.buf = buf;
+ _pass_z.width = width;
+ _pass_z.height = height;
+ }
+private:
+ struct {
+ float *buf;
+ int width, height;
+ } _pass_diffuse, _pass_z;
+};
+
+
+#endif
diff --git a/source/blender/freestyle/intern/application/AppConfig.cpp b/source/blender/freestyle/intern/application/AppConfig.cpp
new file mode 100755
index 00000000000..761f0104dd1
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppConfig.cpp
@@ -0,0 +1,92 @@
+//
+// 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 "AppConfig.h"
+#include <iostream>
+
+#include "../system/StringUtils.h"
+using namespace std;
+
+extern "C" {
+ #include "BLI_path_util.h"
+}
+
+namespace Config {
+Path* Path::_pInstance = 0;
+Path::Path() {
+ // get the root directory
+ //soc
+ setRootDir( BLI_gethome_folder("scripts", BLI_GETHOME_ALL) );
+
+ _pInstance = this;
+}
+void Path::setRootDir(const string& iRootDir) {
+ _ProjectDir = iRootDir + string(DIR_SEP.c_str()) + "freestyle";
+ _ModelsPath = "";
+ _PatternsPath = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str())
+ + "variation_patterns" + string(DIR_SEP.c_str());
+ _BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "textures" + string(DIR_SEP.c_str())
+ + "brushes" + string(DIR_SEP.c_str());
+ _PythonPath = _ProjectDir + string(DIR_SEP.c_str())
++ "style_modules" + string(DIR_SEP.c_str()) ;
+ if (getenv("PYTHONPATH")) {
+ _PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH"));
+ }
+#ifdef WIN32
+ _BrowserCmd = "C:\\Program Files\\Internet Explorer\\iexplore.exe %s";
+#else
+ _BrowserCmd = "mozilla %s";
+#endif
+ _HelpIndexPath = _ProjectDir + string(DIR_SEP.c_str()) + "doc"
+ + string(DIR_SEP.c_str()) + "html" + string(DIR_SEP.c_str())
+ + "index.html";
+ _EnvMapDir = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "env_map" + string(DIR_SEP.c_str());
+ _MapsDir = _ProjectDir + string(DIR_SEP.c_str()) + "data"
+ + string(DIR_SEP.c_str()) + "maps" + string(DIR_SEP.c_str());
+}
+void Path::setHomeDir(const string& iHomeDir) {
+ _HomeDir = iHomeDir;
+}
+Path::~Path() {
+ _pInstance = 0;
+}
+Path* Path::getInstance() {
+ return _pInstance;
+}
+string Path::getEnvVar(const string& iEnvVarName) {
+ string value;
+ if (!getenv(StringUtils::toAscii(iEnvVarName).c_str() ) ) {
+ cerr << "Warning: You may want to set the $"
+ << StringUtils::toAscii(iEnvVarName)
+ << " environment variable to use Freestyle." << endl
+ << " Otherwise, the current directory will be used instead."
+ << endl;
+ value = ".";
+ } else {
+ value = getenv(StringUtils::toAscii(iEnvVarName).c_str() );
+ }
+ return value;
+}
+
+} // End of namepace Config
+
diff --git a/source/blender/freestyle/intern/application/AppConfig.h b/source/blender/freestyle/intern/application/AppConfig.h
new file mode 100755
index 00000000000..59e85ca2e17
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppConfig.h
@@ -0,0 +1,105 @@
+//
+// Filename : AppConfig.h
+// Author : Emmanuel Turquin
+// Purpose : Configuration file
+// Date of creation : 26/02/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 APP_CONFIG_H
+# define APP_CONFIG_H
+
+# include <string>
+# include "../system/FreestyleConfig.h"
+# include "../system/Precision.h"
+
+using namespace std;
+
+namespace Config {
+
+ class Path{
+ protected:
+ static Path * _pInstance;
+ string _ProjectDir;
+ string _ModelsPath;
+ string _PatternsPath;
+ string _BrushesPath;
+ string _PythonPath;
+ string _BrowserCmd;
+ string _HelpIndexPath;
+ string _EnvMapDir;
+ string _MapsDir;
+ string _HomeDir;
+ public:
+ Path();
+ virtual ~Path();
+ static Path* getInstance();
+
+ void setRootDir(const string& iRootDir) ;
+ void setHomeDir(const string& iHomeDir) ;
+
+ const string& getProjectDir() const {return _ProjectDir;}
+ const string& getModelsPath() const {return _ModelsPath;}
+ const string& getPatternsPath() const {return _PatternsPath;}
+ const string& getBrushesPath() const {return _BrushesPath;}
+ const string& getPythonPath() const {return _PythonPath;}
+ const string& getBrowserCmd() const {return _BrowserCmd;}
+ const string& getHelpIndexpath() const {return _HelpIndexPath;}
+ const string& getEnvMapDir() const {return _EnvMapDir;}
+ const string& getMapsDir() const {return _MapsDir;}
+ const string& getHomeDir() const {return _HomeDir;}
+
+ static string getEnvVar(const string& iEnvVarName);
+
+ };
+
+ //
+ // Configuration, default values
+ //
+ //////////////////////////////////////////////////////////////
+
+ // Application
+ static const string APPLICATION_NAME("APPNAME");
+ static const string APPLICATION_VERSION("APPVERSION");
+
+ // ViewMap
+ static const string VIEWMAP_EXTENSION("vm");
+ static const string VIEWMAP_MAGIC("ViewMap File");
+ static const string VIEWMAP_VERSION("1.9");
+
+ // Style modules
+ static const string STYLE_MODULE_EXTENSION("py");
+ static const string STYLE_MODULES_LIST_EXTENSION("sml");
+
+ // Options
+ static const string OPTIONS_DIR("." + APPLICATION_NAME);
+ static const string OPTIONS_FILE("options.xml");
+ static const string OPTIONS_CURRENT_DIRS_FILE("current_dirs.xml");
+ static const string OPTIONS_QGLVIEWER_FILE("qglviewer.xml");
+
+ // Default options
+ static const real DEFAULT_SPHERE_RADIUS = 1.0;
+ static const real DEFAULT_DKR_EPSILON = 0.0;
+
+} // End of namepace Config
+
+#endif // APP_CONFIG_H
diff --git a/source/blender/freestyle/intern/application/AppView.cpp b/source/blender/freestyle/intern/application/AppView.cpp
new file mode 100644
index 00000000000..e523a89b445
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppView.cpp
@@ -0,0 +1,180 @@
+
+//
+// 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 "Controller.h"
+
+extern "C" {
+#include "BLI_jitter.h"
+}
+
+#include <iostream>
+#include "../stroke/Canvas.h"
+#include "AppView.h"
+#include "../scene_graph/NodeLight.h"
+#include "../view_map/Silhouette.h"
+#include "../view_map/ViewMap.h"
+#include "../scene_graph/LineRep.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/VertexRep.h"
+#include "AppConfig.h"
+
+#include "../system/StringUtils.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#if 1 // FRS_antialiasing
+#include "BKE_global.h"
+#include "DNA_scene_types.h"
+#endif
+
+#include "../../FRS_freestyle.h"
+
+}
+
+AppView::AppView(const char *iName)
+{
+ _Fovy = 30.f * M_PI / 180.0;
+ _ModelRootNode = new NodeDrawingStyle;
+ _SilhouetteRootNode = new NodeDrawingStyle;
+ _DebugRootNode = new NodeDrawingStyle;
+
+ _RootNode.AddChild(_ModelRootNode);
+ _SilhouetteRootNode->setStyle(DrawingStyle::LINES);
+ _SilhouetteRootNode->setLightingEnabled(false);
+ _SilhouetteRootNode->setLineWidth(2.f);
+ _SilhouetteRootNode->setPointSize(3.f);
+
+ _RootNode.AddChild(_SilhouetteRootNode);
+
+ _DebugRootNode->setStyle(DrawingStyle::LINES);
+ _DebugRootNode->setLightingEnabled(false);
+ _DebugRootNode->setLineWidth(1.f);
+
+ _RootNode.AddChild(_DebugRootNode);
+
+ _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0],
+ _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0],
+ _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = __min(rabs(_minBBox), rabs(_maxBBox));
+
+ _p2DSelectionNode = new NodeDrawingStyle;
+ _p2DSelectionNode->setLightingEnabled(false);
+ _p2DSelectionNode->setStyle(DrawingStyle::LINES);
+ _p2DSelectionNode->setLineWidth(5.f);
+
+ _p2DNode.AddChild(_p2DSelectionNode);
+
+
+ NodeLight *light = new NodeLight;
+ _Light.AddChild(light);
+}
+
+AppView::~AppView()
+{
+ int ref = _RootNode.destroy();
+
+ _Light.destroy();
+ ref = _p2DNode.destroy();
+
+}
+
+real AppView::distanceToSceneCenter() {
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+
+ Vec3r v( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+ v -= 0.5 * (bbox.getMin() + bbox.getMax());
+
+ return v.norm();
+}
+
+
+real AppView::znear() {
+
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+ Vec3r u = bbox.getMin();
+ Vec3r v = bbox.getMax();
+ Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ Vec3r w1( u[0], u[1], u[2] );
+ Vec3r w2( v[0], u[1], u[2] );
+ Vec3r w3( u[0], v[1], u[2] );
+ Vec3r w4( v[0], v[1], u[2] );
+ Vec3r w5( u[0], u[1], v[2] );
+ Vec3r w6( v[0], u[1], v[2] );
+ Vec3r w7( u[0], v[1], v[2] );
+ Vec3r w8( v[0], v[1], v[2] );
+
+ real _znear = __min( (w1-cameraCenter).norm(),
+ __min( (w2-cameraCenter).norm(),
+ __min( (w3-cameraCenter).norm(),
+ __min( (w4-cameraCenter).norm(),
+ __min( (w5-cameraCenter).norm(),
+ __min( (w6-cameraCenter).norm(),
+ __min( (w7-cameraCenter).norm(),
+ (w8-cameraCenter).norm() )))))));
+
+ return __max(_znear, 0.001);
+
+ }
+
+ real AppView::zfar() {
+
+ BBox<Vec3r> bbox = _ModelRootNode->bbox();
+ Vec3r u = bbox.getMin();
+ Vec3r v = bbox.getMax();
+ Vec3r cameraCenter( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ Vec3r w1( u[0], u[1], u[2] );
+ Vec3r w2( v[0], u[1], u[2] );
+ Vec3r w3( u[0], v[1], u[2] );
+ Vec3r w4( v[0], v[1], u[2] );
+ Vec3r w5( u[0], u[1], v[2] );
+ Vec3r w6( v[0], u[1], v[2] );
+ Vec3r w7( u[0], v[1], v[2] );
+ Vec3r w8( v[0], v[1], v[2] );
+
+ real _zfar = __max( (w1-cameraCenter).norm(),
+ __max( (w2-cameraCenter).norm(),
+ __max( (w3-cameraCenter).norm(),
+ __max( (w4-cameraCenter).norm(),
+ __max( (w5-cameraCenter).norm(),
+ __max( (w6-cameraCenter).norm(),
+ __max( (w7-cameraCenter).norm(),
+ (w8-cameraCenter).norm() )))))));
+
+ return _zfar;
+
+ }
+
+ real AppView::GetFocalLength()
+ {
+ real Near = __max(0.1,(real)(-2.f*_maxAbs+ distanceToSceneCenter() ));
+ return Near;
+ }
+
+
diff --git a/source/blender/freestyle/intern/application/AppView.h b/source/blender/freestyle/intern/application/AppView.h
new file mode 100644
index 00000000000..d23172c9f8d
--- /dev/null
+++ b/source/blender/freestyle/intern/application/AppView.h
@@ -0,0 +1,226 @@
+#ifndef APPVIEW_H
+# define APPVIEW_H
+
+# if !defined(WIN32) || defined(__GNUC__)
+# include <algorithm>
+using namespace std;
+# define __min(x,y) (min(x,y))
+# define __max(x,y) (max(x,y))
+# endif // WIN32
+
+# include "../geometry/Geom.h"
+# include "../geometry/BBox.h"
+# include "../scene_graph/NodeDrawingStyle.h"
+# include "../system/Precision.h"
+# include "AppConfig.h"
+
+using namespace Geometry;
+
+class AppView
+{
+
+public:
+
+ AppView(const char *iName = 0);
+ virtual ~AppView();
+
+public:
+
+ //inherited
+ inline unsigned int width() { return _width; }
+ inline unsigned int height() { return _height; }
+ inline BBox<Vec2i> border() { return _border; }
+ inline void setWidth( unsigned int width ) { _width = width; }
+ inline void setHeight( unsigned int height ) { _height = height; }
+ inline void setBorder( int xmin, int ymin, int xmax, int ymax ) {
+ _border = BBox<Vec2i>(Vec2i(xmin, ymin), Vec2i(xmax, ymax));
+ }
+
+protected:
+ unsigned int _width, _height;
+ BBox<Vec2i> _border;
+
+public:
+
+ /*! Sets the model to draw in the viewer
+ * iModel
+ * The Root Node of the model
+ */
+ inline void setModel(NodeGroup *iModel)
+ {
+ if(0 != _ModelRootNode->numberOfChildren())
+ {
+ _ModelRootNode->DetachChildren();
+ _ModelRootNode->clearBBox();
+ }
+
+ AddModel(iModel);
+ }
+
+ /*! Adds a model for displaying in the viewer */
+ inline void AddModel(NodeGroup *iModel)
+ {
+ _ModelRootNode->AddChild(iModel);
+
+ _ModelRootNode->UpdateBBox();
+
+ _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0],
+ _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0],
+ _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox));
+
+ _minAbs = __min(rabs(_minBBox), rabs(_maxBBox));
+
+ }
+
+ inline void AddSilhouette(NodeGroup* iSilhouette)
+ {
+ _SilhouetteRootNode->AddChild(iSilhouette);
+ }
+
+ inline void Add2DSilhouette(NodeGroup *iSilhouette)
+ {
+ //_pFENode->AddChild(iSilhouette);
+ }
+
+ inline void Add2DVisibleSilhouette(NodeGroup *iVSilhouette)
+ {
+ //_pVisibleSilhouetteNode->AddChild(iVSilhouette);
+ }
+
+ inline void setDebug(NodeGroup* iDebug)
+ {
+ if(0 != _DebugRootNode->numberOfChildren())
+ {
+ _DebugRootNode->DetachChildren();
+ _DebugRootNode->clearBBox();
+ }
+
+ AddDebug(iDebug);
+ }
+
+ inline void AddDebug(NodeGroup* iDebug)
+ {
+ _DebugRootNode->AddChild(iDebug);
+ }
+
+ inline void DetachModel(Node *iModel)
+ {
+ _ModelRootNode->DetachChild(iModel);
+ _ModelRootNode->UpdateBBox();
+
+ _minBBox = __min(__min(_ModelRootNode->bbox().getMin()[0],
+ _ModelRootNode->bbox().getMin()[1]),
+ _ModelRootNode->bbox().getMin()[2]);
+ _maxBBox = __max(__max(_ModelRootNode->bbox().getMax()[0],
+ _ModelRootNode->bbox().getMax()[1]),
+ _ModelRootNode->bbox().getMax()[2]);
+
+ _maxAbs = __max(rabs(_minBBox), rabs(_maxBBox));
+ _minAbs = __min(rabs(_minBBox), rabs(_maxBBox));
+ }
+
+ inline void DetachModel()
+ {
+ _ModelRootNode->DetachChildren();
+ _ModelRootNode->clearBBox();
+
+ // 2D Scene
+ //_p2DNode.DetachChildren();
+ //_pFENode->DetachChildren();
+ //_pVisibleSilhouetteNode->DetachChildren();
+
+ }
+
+ inline void DetachSilhouette()
+ {
+ _SilhouetteRootNode->DetachChildren();
+ //_pFENode->DetachChildren();
+ //_pVisibleSilhouetteNode->DetachChildren();
+ _p2DSelectionNode->destroy();
+ }
+
+ inline void DetachVisibleSilhouette()
+ {
+ //_pVisibleSilhouetteNode->DetachChildren();
+ _p2DSelectionNode->destroy();
+ }
+
+ inline void DetachDebug()
+ {
+ _DebugRootNode->DetachChildren();
+ }
+
+
+
+ real distanceToSceneCenter();
+ real GetFocalLength();
+
+ inline real GetAspect() const
+ {
+ return ((real) _width/(real) _height);
+ }
+
+ void setHorizontalFov( float hfov )
+{
+ _Fovy = 2.0 * atan (tan(hfov / 2.0) / GetAspect());
+}
+ inline real GetFovyRadian() const
+ {
+ return _Fovy;
+ }
+
+ inline real GetFovyDegrees() const
+ {
+ return _Fovy * 180.0 / M_PI;
+ }
+
+ BBox<Vec3r> scene3DBBox() const { return _ModelRootNode->bbox(); }
+
+ real znear();
+ real zfar();
+
+
+public:
+ /*! Core scene drawing */
+ void DrawScene(SceneVisitor *iRenderer);
+
+ /*! 2D Scene Drawing */
+ void Draw2DScene(SceneVisitor *iRenderer);
+
+
+protected:
+
+ /*! fabs or abs */
+ inline int rabs(int x) {return abs(x);}
+ inline real rabs(real x) {return fabs(x);}
+
+
+protected:
+ float _Fovy;
+
+ //The root node container
+ NodeGroup _RootNode;
+ NodeDrawingStyle *_ModelRootNode;
+ NodeDrawingStyle *_SilhouetteRootNode;
+ NodeDrawingStyle *_DebugRootNode;
+
+ NodeGroup _Light;
+
+ real _minBBox;
+ real _maxBBox;
+ real _maxAbs;
+ real _minAbs;
+
+ // 2D Scene
+ bool _Draw2DScene;
+ bool _Draw3DScene; NodeGroup _p2DNode;
+ NodeDrawingStyle *_p2DSelectionNode;
+
+};
+
+#endif // APPVIEW_H
diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp
new file mode 100755
index 00000000000..76c9023df57
--- /dev/null
+++ b/source/blender/freestyle/intern/application/Controller.cpp
@@ -0,0 +1,882 @@
+
+//
+// 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Must be included before any QT header, because of moc
+#include "../system/PythonInterpreter.h"
+
+#include <string>
+#include <fstream>
+#include <float.h>
+
+#include "AppView.h"
+#include "AppCanvas.h"
+#include "AppConfig.h"
+
+
+#include "../system/StringUtils.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/NodeDrawingStyle.h"
+#include "../winged_edge/WingedEdgeBuilder.h"
+#include "../winged_edge/WEdge.h"
+#include "../scene_graph/VertexRep.h"
+#include "../winged_edge/WXEdgeBuilder.h"
+#include "../scene_graph/ScenePrettyPrinter.h"
+#include "../winged_edge/WFillGrid.h"
+
+#include "../view_map/ViewMapTesselator.h"
+#include "../stroke/StrokeTesselator.h"
+#include "../view_map/ViewMapIO.h"
+#include "Controller.h"
+#include "../view_map/ViewMap.h"
+#include "../winged_edge/Curvature.h"
+#include "../image/Image.h"
+#include "../view_map/SteerableViewMap.h"
+#include "../stroke/PSStrokeRenderer.h"
+#include "../stroke/TextStrokeRenderer.h"
+#include "../stroke/StyleModule.h"
+
+#include "../system/StringUtils.h"
+
+#include "../blender_interface/BlenderFileLoader.h"
+#include "../blender_interface/BlenderStrokeRenderer.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "../../FRS_freestyle.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+Controller::Controller()
+{
+
+ const string sep(Config::DIR_SEP.c_str());
+ //const string filename = Config::Path::getInstance()->getHomeDir() + sep + Config::OPTIONS_DIR + sep + Config::OPTIONS_CURRENT_DIRS_FILE;
+ //_current_dirs = new ConfigIO(filename, Config::APPLICATION_NAME + "CurrentDirs", true);
+
+ _RootNode = new NodeGroup;
+ _RootNode->addRef();
+
+ _SilhouetteNode = NULL;
+ //_ProjectedSilhouette = NULL;
+ //_VisibleProjectedSilhouette = NULL;
+
+ _DebugNode = new NodeGroup;
+ _DebugNode->addRef();
+
+ _winged_edge = NULL;
+
+ _pView = NULL;
+
+ _edgeTesselationNature = (Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE);
+
+ _ProgressBar = new ProgressBar;
+ _SceneNumFaces = 0;
+ _minEdgeSize = DBL_MAX;
+ _EPSILON = 1e-6;
+ _bboxDiag = 0;
+
+ _ViewMap = 0;
+
+ _Canvas = 0;
+
+ _VisibilityAlgo = ViewMapBuilder::ray_casting;
+ //_VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
+
+ _Canvas = new AppCanvas;
+
+ _inter = new PythonInterpreter();
+ _EnableQI = true;
+ _ComputeRidges = true;
+ _ComputeSteerableViewMap = false;
+ _ComputeSuggestive = true;
+ _sphereRadius = 1.0;
+
+ init_options();
+}
+
+Controller::~Controller()
+{
+ if(NULL != _RootNode)
+ {
+ int ref = _RootNode->destroy();
+ if(0 == ref)
+ delete _RootNode;
+ }
+
+ if(NULL != _SilhouetteNode)
+ {
+ int ref = _SilhouetteNode->destroy();
+ if(0 == ref)
+ delete _SilhouetteNode;
+ }
+
+ if(NULL != _DebugNode)
+ {
+ int ref = _DebugNode->destroy();
+ if(0 == ref)
+ delete _DebugNode;
+ }
+
+ if(_winged_edge) {
+ delete _winged_edge;
+ _winged_edge = NULL;
+ }
+
+ if(0 != _ViewMap)
+ {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+
+ if(0 != _Canvas)
+ {
+ delete _Canvas;
+ _Canvas = 0;
+ }
+
+ if (_inter) {
+ delete _inter;
+ _inter = NULL;
+ }
+
+ //delete _current_dirs;
+}
+
+void Controller::setView(AppView *iView)
+{
+ if(NULL == iView)
+ return;
+
+ _pView = iView;
+ _Canvas->setViewer(_pView);
+}
+
+void Controller::setPassDiffuse(float *buf, int width, int height)
+{
+ AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
+ assert(app_canvas != 0);
+ app_canvas->setPassDiffuse(buf, width, height);
+}
+
+void Controller::setPassZ(float *buf, int width, int height)
+{
+ AppCanvas *app_canvas = dynamic_cast<AppCanvas *>(_Canvas);
+ assert(app_canvas != 0);
+ app_canvas->setPassZ(buf, width, height);
+}
+
+void Controller::setContext(bContext *C)
+{
+ PythonInterpreter* py_inter = dynamic_cast<PythonInterpreter*>(_inter);
+ assert(py_inter != 0);
+ py_inter->setContext(C);
+}
+
+int Controller::LoadMesh(Render *re, SceneRenderLayer* srl)
+{
+
+ BlenderFileLoader loader(re, srl);
+
+ _Chrono.start();
+
+ NodeGroup *blenderScene = loader.Load();
+
+ if (blenderScene == NULL) {
+ cout << "Cannot load scene" << endl;
+ return 1;
+ }
+
+ if( blenderScene->numberOfChildren() < 1) {
+ cout << "Empty scene" << endl;
+ blenderScene->destroy();
+ delete blenderScene;
+ return 1;
+ }
+
+ cout << "Scene loaded" << endl;
+ printf("Mesh cleaning : %lf\n", _Chrono.stop());
+ _SceneNumFaces += loader.numFacesRead();
+
+ if(loader.minEdgeSize() < _minEdgeSize)
+ {
+ _minEdgeSize = loader.minEdgeSize();
+ }
+
+ // DEBUG
+ // ScenePrettyPrinter spp;
+ // blenderScene->accept(spp);
+
+ _RootNode->AddChild(blenderScene);
+ _RootNode->UpdateBBox(); // FIXME: Correct that by making a Renderer to compute the bbox
+
+ _pView->setModel(_RootNode);
+ //_pView->FitBBox();
+
+
+ _Chrono.start();
+
+
+ WXEdgeBuilder wx_builder;
+ blenderScene->accept(wx_builder);
+ _winged_edge = wx_builder.getWingedEdge();
+
+ printf("WEdge building : %lf\n", _Chrono.stop());
+
+ _Chrono.start();
+
+ _Grid.clear();
+ Vec3r size;
+ for(unsigned int i=0; i<3; i++)
+ {
+ size[i] = fabs(_RootNode->bbox().getMax()[i] - _RootNode->bbox().getMin()[i]);
+ size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections
+ if(size[i]==0){
+ cout << "Warning: the bbox size is 0 in dimension "<<i<<endl;
+ }
+ }
+ _Grid.configure(Vec3r(_RootNode->bbox().getMin() - size / 20.0), size,
+ _SceneNumFaces);
+
+ // Fill in the grid:
+ WFillGrid fillGridRenderer(&_Grid, _winged_edge);
+ fillGridRenderer.fillGrid();
+
+ printf("Grid building : %lf\n", _Chrono.stop());
+
+ // DEBUG
+ _Grid.displayDebug();
+ //
+ // _pView->setDebug(_DebugNode);
+
+ //delete stuff
+ // if(0 != ws_builder)
+ // {
+ // delete ws_builder;
+ // ws_builder = 0;
+ // }
+
+ //soc QFileInfo qfi(iFileName);
+ //soc string basename((const char*)qfi.fileName().toAscii().data());
+ // char cleaned[FILE_MAX];
+ // BLI_strncpy(cleaned, iFileName, FILE_MAX);
+ // BLI_cleanup_file(NULL, cleaned);
+ // string basename = StringUtils::toAscii( string(cleaned) );
+
+ _ListOfModels.push_back("Blender_models");
+
+ cout << "Triangles nb : " << _SceneNumFaces << endl;
+ _bboxDiag = (_RootNode->bbox().getMax()-_RootNode->bbox().getMin()).norm();
+ cout << "Bounding Box : " << _bboxDiag << endl;
+ return 0;
+}
+
+
+void Controller::CloseFile()
+{
+ WShape::setCurrentId(0);
+ _pView->DetachModel();
+ _ListOfModels.clear();
+ if(NULL != _RootNode)
+ {
+ int ref = _RootNode->destroy();
+ if(0 == ref)
+ _RootNode->addRef();
+
+ _RootNode->clearBBox();
+ }
+
+ _pView->DetachSilhouette();
+ if (NULL != _SilhouetteNode)
+ {
+ int ref = _SilhouetteNode->destroy();
+ if(0 == ref)
+ {
+ delete _SilhouetteNode;
+ _SilhouetteNode = NULL;
+ }
+ }
+ // if(NULL != _ProjectedSilhouette)
+ // {
+ // int ref = _ProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // {
+ // delete _ProjectedSilhouette;
+ // _ProjectedSilhouette = NULL;
+ // }
+ // }
+ // if(NULL != _VisibleProjectedSilhouette)
+ // {
+ // int ref = _VisibleProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // {
+ // delete _VisibleProjectedSilhouette;
+ // _VisibleProjectedSilhouette = NULL;
+ // }
+ // }
+
+ _pView->DetachDebug();
+ if(NULL != _DebugNode)
+ {
+ int ref = _DebugNode->destroy();
+ if(0 == ref)
+ _DebugNode->addRef();
+ }
+
+ if(_winged_edge) {
+ delete _winged_edge;
+ _winged_edge = NULL;
+ }
+
+ // We deallocate the memory:
+ if(NULL != _ViewMap)
+ {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+
+ // clears the canvas
+ _Canvas->Erase();
+
+ // clears the grid
+ _Grid.clear();
+ _SceneNumFaces = 0;
+ _minEdgeSize = DBL_MAX;
+
+ // soc: reset passes
+ setPassDiffuse(NULL, 0, 0);
+ setPassZ(NULL, 0, 0);
+}
+
+
+
+void Controller::ComputeViewMap()
+{
+
+ if (!_ListOfModels.size())
+ return;
+
+ if(NULL != _ViewMap)
+ {
+ delete _ViewMap;
+ _ViewMap = 0;
+ }
+
+ _pView->DetachDebug();
+ if(NULL != _DebugNode)
+ {
+ int ref = _DebugNode->destroy();
+ if(0 == ref)
+ _DebugNode->addRef();
+ }
+
+
+ _pView->DetachSilhouette();
+ if (NULL != _SilhouetteNode)
+ {
+ int ref = _SilhouetteNode->destroy();
+ if(0 == ref)
+ delete _SilhouetteNode;
+ }
+ // if(NULL != _ProjectedSilhouette)
+ // {
+ // int ref = _ProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // delete _ProjectedSilhouette;
+ // }
+ // if(NULL != _VisibleProjectedSilhouette)
+ // {
+ // int ref = _VisibleProjectedSilhouette->destroy();
+ // if(0 == ref)
+ // {
+ // delete _VisibleProjectedSilhouette;
+ // _VisibleProjectedSilhouette = 0;
+ // }
+ // }
+
+ // retrieve the 3D viewpoint and transformations information
+ //----------------------------------------------------------
+ // Save the viewpoint context at the view level in order
+ // to be able to restore it later:
+
+ // Restore the context of view:
+ // we need to perform all these operations while the
+ // 3D context is on.
+ Vec3r vp( freestyle_viewpoint[0], freestyle_viewpoint[1], freestyle_viewpoint[2]);
+
+ //cout << "mv" << endl;
+ real mv[4][4];
+ for( int i= 0; i < 4; i++) {
+ for( int j= 0; j < 4; j++) {
+ mv[i][j] = freestyle_mv[i][j];
+ //cout << mv[i][j] << " ";
+ }
+ // cout << endl;
+ }
+
+ //cout << "\nproj" << endl;
+ real proj[4][4];
+ for( int i= 0; i < 4; i++) {
+ for( int j= 0; j < 4; j++) {
+ proj[i][j] = freestyle_proj[i][j];
+ //cout << proj[i][j] << " ";
+ }
+ //cout << endl;
+ }
+
+ int viewport[4];
+ for( int i= 0; i < 4; i++)
+ viewport[i] = freestyle_viewport[i];
+
+ //cout << "\nfocal:" << _pView->GetFocalLength() << endl << endl;
+
+
+
+ // Flag the WXEdge structure for silhouette edge detection:
+ //----------------------------------------------------------
+
+ cout << "\n=== Detecting silhouette edges ===" << endl;
+ _Chrono.start();
+
+ edgeDetector.setViewpoint(Vec3r(vp));
+ edgeDetector.enableOrthographicProjection(proj[3][3] != 0.0);
+ edgeDetector.enableRidgesAndValleysFlag(_ComputeRidges);
+ edgeDetector.enableSuggestiveContours(_ComputeSuggestive);
+ edgeDetector.setSphereRadius(_sphereRadius);
+ edgeDetector.setSuggestiveContourKrDerivativeEpsilon(_suggestiveContourKrDerivativeEpsilon);
+ edgeDetector.processShapes(*_winged_edge);
+
+ real duration = _Chrono.stop();
+ printf("Feature lines : %lf\n", duration);
+
+ // Builds the view map structure from the flagged WSEdge structure:
+ //----------------------------------------------------------
+ ViewMapBuilder vmBuilder;
+ vmBuilder.setEnableQI(_EnableQI);
+ vmBuilder.setViewpoint(Vec3r(vp));
+ vmBuilder.setTransform( mv, proj,viewport, _pView->GetFocalLength(), _pView->GetAspect(), _pView->GetFovyRadian());
+ vmBuilder.setFrustum(_pView->znear(), _pView->zfar());
+ vmBuilder.setGrid(&_Grid);
+
+ // Builds a tesselated form of the silhouette for display purpose:
+ //---------------------------------------------------------------
+ ViewMapTesselator3D sTesselator3d;
+ //ViewMapTesselator2D sTesselator2d;
+ //sTesselator2d.setNature(_edgeTesselationNature);
+ sTesselator3d.setNature(_edgeTesselationNature);
+
+ cout << "\n=== Building the view map ===" << endl;
+ _Chrono.start();
+ // Build View Map
+ _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON);
+ _ViewMap->setScene3dBBox(_RootNode->bbox());
+
+ printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size() );
+
+ //Tesselate the 3D edges:
+ _SilhouetteNode = sTesselator3d.Tesselate(_ViewMap);
+ _SilhouetteNode->addRef();
+
+ // Tesselate 2D edges
+ // _ProjectedSilhouette = sTesselator2d.Tesselate(_ViewMap);
+ // _ProjectedSilhouette->addRef();
+
+ duration = _Chrono.stop();
+ printf("ViewMap building : %lf\n", duration);
+
+
+ _pView->AddSilhouette(_SilhouetteNode);
+ //_pView->AddSilhouette(_WRoot);
+ //_pView->Add2DSilhouette(_ProjectedSilhouette);
+ //_pView->Add2DVisibleSilhouette(_VisibleProjectedSilhouette);
+ _pView->AddDebug(_DebugNode);
+
+ // Draw the steerable density map:
+ //--------------------------------
+ if(_ComputeSteerableViewMap){
+ ComputeSteerableViewMap();
+ }
+ // Reset Style modules modification flags
+ resetModified(true);
+}
+
+void Controller::ComputeSteerableViewMap(){
+//soc
+ // if((!_Canvas) || (!_ViewMap))
+ // return;
+ //
+ // // Build 4 nodes containing the edges in the 4 directions
+ // NodeGroup *ng[Canvas::NB_STEERABLE_VIEWMAP];
+ // unsigned i;
+ // real c = 32.f/255.f; // see SteerableViewMap::readSteerableViewMapPixel() for information about this 32.
+ // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
+ // ng[i] = new NodeGroup;
+ // }
+ // NodeShape *completeNS = new NodeShape;
+ // completeNS->material().setDiffuse(c,c,c,1);
+ // ng[Canvas::NB_STEERABLE_VIEWMAP-1]->AddChild(completeNS);
+ // SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ // svm->Reset();
+ //
+ // ViewMap::fedges_container& fedges = _ViewMap->FEdges();
+ // LineRep * fRep;
+ // NodeShape *ns;
+ // for(ViewMap::fedges_container::iterator f=fedges.begin(), fend=fedges.end();
+ // f!=fend;
+ // ++f){
+ // if((*f)->viewedge()->qi() != 0)
+ // continue;
+ // fRep = new LineRep((*f)->vertexA()->point2d(),(*f)->vertexB()->point2d()) ;
+ // completeNS->AddRep(fRep); // add to the complete map anyway
+ // double *oweights = svm->AddFEdge(*f);
+ // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP-1; ++i){
+ // ns = new NodeShape;
+ // double wc = oweights[i]*c;
+ // if(oweights[i] == 0)
+ // continue;
+ // ns->material().setDiffuse(wc, wc, wc, 1);
+ // ns->AddRep(fRep);
+ // ng[i]->AddChild(ns);
+ // }
+ // }
+ //
+ // GrayImage *img[Canvas::NB_STEERABLE_VIEWMAP];
+ // //#ifdef WIN32
+ // QGLBasicWidget offscreenBuffer(_pView, "SteerableViewMap", _pView->width(), _pView->height());
+ // QPixmap pm;
+ // QImage qimg;
+ // for(i=0; i<Canvas::NB_STEERABLE_VIEWMAP; ++i){
+ // offscreenBuffer.AddNode(ng[i]);
+ // //img[i] = new GrayImage(_pView->width(), _pView->height());
+ // //offscreenBuffer.readPixels(0,0,_pView->width(), _pView->height(), img[i]->getArray());
+ // pm = offscreenBuffer.renderPixmap(_pView->width(), _pView->height());
+ //
+ // if(pm.isNull())
+ // cout << "BuildViewMap Warning: couldn't render the steerable ViewMap" << endl;
+ // //pm.save(QString("steerable")+QString::number(i)+QString(".bmp"), "BMP");
+ // // FIXME!! Lost of time !
+ // qimg = pm.toImage();
+ // // FIXME !! again!
+ // img[i] = new GrayImage(_pView->width(), _pView->height());
+ // for(unsigned y=0;y<img[i]->height();++y){
+ // for(unsigned x=0;x<img[i]->width();++x){
+ // //img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y))/255.f);
+ // img[i]->setPixel(x,y,(float)qGray(qimg.pixel(x,y)));
+ // // float c = qGray(qimg.pixel(x,y));
+ // // img[i]->setPixel(x,y,qGray(qimg.pixel(x,y)));
+ // }
+ // }
+ // offscreenBuffer.DetachNode(ng[i]);
+ // ng[i]->destroy();
+ // delete ng[i];
+ // // check
+ // // qimg = QImage(_pView->width(), _pView->height(), 32);
+ // // for(y=0;y<img[i]->height();++y){
+ // // for(unsigned x=0;x<img[i]->width();++x){
+ // // float v = img[i]->pixel(x,y);
+ // // qimg.setPixel(x,y,qRgb(v,v,v));
+ // // }
+ // // }
+ // // qimg.save(QString("newsteerable")+QString::number(i)+QString(".bmp"), "BMP");
+ // }
+ //
+ //
+ // svm->buildImagesPyramids(img,false,0,1.f);
+}
+
+void Controller::saveSteerableViewMapImages(){
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ if(!svm){
+ cerr << "the Steerable ViewMap has not been computed yet" << endl;
+ return;
+ }
+ svm->saveSteerableViewMap();
+}
+
+void Controller::toggleVisibilityAlgo()
+{
+ if(_VisibilityAlgo == ViewMapBuilder::ray_casting) {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_fast;
+ }
+ else if (_VisibilityAlgo == ViewMapBuilder::ray_casting_fast) {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting_very_fast;
+ }
+ else {
+ _VisibilityAlgo = ViewMapBuilder::ray_casting;
+ }
+}
+
+void Controller::setQuantitativeInvisibility(bool iBool)
+{
+ _EnableQI = iBool;
+}
+
+bool Controller::getQuantitativeInvisibility() const
+{
+ return _EnableQI;
+}
+
+void Controller::setComputeRidgesAndValleysFlag(bool iBool){
+ _ComputeRidges = iBool;
+}
+
+bool Controller::getComputeRidgesAndValleysFlag() const {
+ return _ComputeRidges;
+}
+void Controller::setComputeSuggestiveContoursFlag(bool b){
+ _ComputeSuggestive = b;
+}
+
+bool Controller::getComputeSuggestiveContoursFlag() const {
+ return _ComputeSuggestive;
+}
+void Controller::setComputeSteerableViewMapFlag(bool iBool){
+ _ComputeSteerableViewMap = iBool;
+}
+
+bool Controller::getComputeSteerableViewMapFlag() const {
+ return _ComputeSteerableViewMap;
+}
+
+void Controller::DrawStrokes()
+{
+ if(_ViewMap == 0)
+ return;
+
+ cout << "\n=== Stroke drawing ===" << endl;
+ _Chrono.start();
+ _Canvas->Draw();
+ real d = _Chrono.stop();
+ cout << "Strokes generation : " << d << endl;
+ cout << "Stroke count : " << _Canvas->stroke_count << endl;
+ resetModified();
+}
+
+void Controller::ResetRenderCount()
+{
+ _render_count = 0;
+}
+
+Render* Controller::RenderStrokes(Render *re) {
+ BlenderStrokeRenderer* blenderRenderer = new BlenderStrokeRenderer(re, ++_render_count);
+ _Canvas->Render( blenderRenderer );
+ Render* freestyle_render = blenderRenderer->RenderScene(re);
+ delete blenderRenderer;
+
+ return freestyle_render;
+}
+
+void Controller::InsertStyleModule(unsigned index, const char *iFileName)
+{
+ if( !BLI_testextensie(iFileName, ".py") ) {
+ cerr << "Error: Cannot load \"" << StringUtils::toAscii( string(iFileName) )
+ << "\", unknown extension" << endl;
+ return;
+ }
+
+ StyleModule* sm = new StyleModule(iFileName, _inter);
+ _Canvas->InsertStyleModule(index, sm);
+
+}
+
+void Controller::AddStyleModule(const char *iFileName)
+{
+ //_pStyleWindow->Add(iFileName);
+}
+
+void Controller::RemoveStyleModule(unsigned index)
+{
+ _Canvas->RemoveStyleModule(index);
+}
+
+void Controller::Clear()
+{
+ _Canvas->Clear();
+}
+
+void Controller::ReloadStyleModule(unsigned index, const char * iFileName)
+{
+ StyleModule* sm = new StyleModule(iFileName, _inter);
+ _Canvas->ReplaceStyleModule(index, sm);
+}
+
+void Controller::SwapStyleModules(unsigned i1, unsigned i2)
+{
+ _Canvas->SwapStyleModules(i1, i2);
+}
+
+
+void Controller::toggleLayer(unsigned index, bool iDisplay)
+{
+ _Canvas->setVisible(index, iDisplay);
+}
+
+void Controller::setModified(unsigned index, bool iMod)
+{
+ //_pStyleWindow->setModified(index, iMod);
+ _Canvas->setModified(index, iMod);
+ updateCausalStyleModules(index + 1);
+}
+
+void Controller::updateCausalStyleModules(unsigned index) {
+ vector<unsigned> vec;
+ _Canvas->causalStyleModules(vec, index);
+ for (vector<unsigned>::const_iterator it = vec.begin(); it != vec.end(); it++) {
+ //_pStyleWindow->setModified(*it, true);
+ _Canvas->setModified(*it, true);
+ }
+}
+
+void Controller::resetModified(bool iMod)
+{
+ //_pStyleWindow->resetModified(iMod);
+ _Canvas->resetModified(iMod);
+}
+
+NodeGroup * Controller::BuildRep(vector<ViewEdge*>::iterator vedges_begin,
+ vector<ViewEdge*>::iterator vedges_end)
+{
+ ViewMapTesselator2D tesselator2D;
+ FrsMaterial mat;
+ mat.setDiffuse(1,1,0.3,1);
+ tesselator2D.setFrsMaterial(mat);
+
+ return (tesselator2D.Tesselate(vedges_begin, vedges_end));
+}
+
+void Controller::toggleEdgeTesselationNature(Nature::EdgeNature iNature)
+{
+ _edgeTesselationNature ^= (iNature);
+ ComputeViewMap();
+}
+
+void Controller::setModelsDir(const string& dir) {
+ //_current_dirs->setValue("models/dir", dir);
+}
+
+string Controller::getModelsDir() const {
+ string dir = ".";
+ //_current_dirs->getValue("models/dir", dir);
+ return dir;
+}
+
+void Controller::setModulesDir(const string& dir) {
+ //_current_dirs->setValue("modules/dir", dir);
+}
+
+string Controller::getModulesDir() const {
+ string dir = ".";
+ //_current_dirs->getValue("modules/dir", dir);
+ return dir;
+}
+
+void Controller::setHelpIndex(const string& index) {
+ _help_index = index;
+}
+
+string Controller::getHelpIndex() const {
+ return _help_index;
+}
+
+void Controller::setBrowserCmd(const string& cmd) {
+ _browser_cmd = cmd;
+}
+
+string Controller::getBrowserCmd() const {
+ return _browser_cmd;
+}
+
+void Controller::resetInterpreter() {
+ if (_inter)
+ _inter->reset();
+}
+
+
+void Controller::displayDensityCurves(int x, int y){
+ SteerableViewMap * svm = _Canvas->getSteerableViewMap();
+ if(!svm)
+ return;
+
+ unsigned i,j;
+ typedef vector<Vec3r> densityCurve;
+ vector<densityCurve> curves(svm->getNumberOfOrientations()+1);
+ vector<densityCurve> curvesDirection(svm->getNumberOfPyramidLevels());
+
+ // collect the curves values
+ unsigned nbCurves = svm->getNumberOfOrientations()+1;
+ unsigned nbPoints = svm->getNumberOfPyramidLevels();
+ if(!nbPoints)
+ return;
+
+ // build the density/nbLevels curves for each orientation
+ for(i=0;i<nbCurves; ++i){
+ for(j=0; j<nbPoints; ++j){
+ curves[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(i, j, x, y), 0));
+ }
+ }
+ // build the density/nbOrientations curves for each level
+ for(i=0;i<nbPoints; ++i){
+ for(j=0; j<nbCurves; ++j){
+ curvesDirection[i].push_back(Vec3r(j, svm->readSteerableViewMapPixel(j, i, x, y), 0));
+ }
+ }
+
+ // display the curves
+ // for(i=0; i<nbCurves; ++i)
+ // _pDensityCurvesWindow->setOrientationCurve(i, Vec2d(0,0), Vec2d(nbPoints, 1), curves[i], "scale", "density");
+ // for(i=1; i<=8; ++i)
+ // _pDensityCurvesWindow->setLevelCurve(i, Vec2d(0,0), Vec2d(nbCurves, 1), curvesDirection[i], "orientation", "density");
+ // _pDensityCurvesWindow->show();
+}
+
+void Controller::init_options(){
+// from AppOptionsWindow.cpp
+// Default init options
+
+ Config::Path * cpath = Config::Path::getInstance();
+
+ // Directories
+ ViewMapIO::Options::setModelsPath( StringUtils::toAscii( cpath->getModelsPath() ) );
+ PythonInterpreter::Options::setPythonPath( StringUtils::toAscii( cpath->getPythonPath() ) );
+ TextureManager::Options::setPatternsPath( StringUtils::toAscii( cpath->getPatternsPath() ) );
+ TextureManager::Options::setBrushesPath( StringUtils::toAscii( cpath->getModelsPath() ) );
+
+ // ViewMap Format
+ ViewMapIO::Options::rmFlags(ViewMapIO::Options::FLOAT_VECTORS);
+ ViewMapIO::Options::rmFlags(ViewMapIO::Options::NO_OCCLUDERS);
+ setComputeSteerableViewMapFlag( false );
+
+ // Visibility
+ setQuantitativeInvisibility(true);
+
+ // soc: initialize canvas
+ _Canvas->init();
+
+ // soc: initialize passes
+ setPassDiffuse(NULL, 0, 0);
+ setPassZ(NULL, 0, 0);
+}
diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h
new file mode 100755
index 00000000000..422707d3c1f
--- /dev/null
+++ b/source/blender/freestyle/intern/application/Controller.h
@@ -0,0 +1,235 @@
+//
+// Filename : Controller.h
+// Author : Stephane Grabli
+// Purpose : The spinal tap of the system
+// Date of creation : 01/07/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 CONTROLLER_H
+# define CONTROLLER_H
+
+# include "../view_map/ViewMapBuilder.h"
+# include <string>
+//# include "ConfigIO.h"
+# include "../geometry/FastGrid.h"
+# include "../geometry/HashGrid.h"
+# include "../system/TimeUtils.h"
+# include "../system/ProgressBar.h"
+# include "../system/Precision.h"
+# include "../system/Interpreter.h"
+# include "../view_map/FEdgeXDetector.h"
+
+class AppView;
+class NodeGroup;
+class WShape;
+class SShape;
+class ViewMap;
+class ViewEdge;
+class AppCanvas;
+class InteractiveShader;
+class Shader;
+class StrokeRenderer;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "render_types.h"
+ #include "DNA_scene_types.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+class Controller
+{
+public:
+ Controller() ;
+ ~Controller() ;
+
+ void setView(AppView *iView);
+ void setPassDiffuse(float *buf, int width, int height);
+ void setPassZ(float *buf, int width, int height);
+ void setContext(bContext *C);
+
+ //soc
+ void init_options();
+
+ int LoadMesh( Render *re, SceneRenderLayer* srl );
+ int Load3DSFile(const char *iFileName);
+ void CloseFile();
+ void ComputeViewMap();
+ void ComputeSteerableViewMap();
+ void saveSteerableViewMapImages();
+ void toggleEdgeTesselationNature(Nature::EdgeNature iNature);
+ void DrawStrokes();
+ void ResetRenderCount();
+ Render* RenderStrokes(Render *re);
+ void SwapStyleModules(unsigned i1, unsigned i2);
+ void InsertStyleModule(unsigned index, const char *iFileName);
+ void AddStyleModule(const char *iFileName);
+ void RemoveStyleModule(unsigned index);
+ void ReloadStyleModule(unsigned index, const char * iFileName);
+ void Clear();
+ void toggleLayer(unsigned index, bool iDisplay);
+ void setModified(unsigned index, bool iMod);
+ void resetModified(bool iMod=false);
+ void updateCausalStyleModules(unsigned index);
+ void displayDensityCurves(int x, int y);
+
+
+ ViewEdge * SelectViewEdge(real x, real y);
+ FEdge * SelectFEdge(real x, real y);
+ NodeGroup* BuildRep(vector<ViewEdge*>::iterator vedges_begin,
+ vector<ViewEdge*>::iterator vedges_end) ;
+
+ NodeGroup* debugNode() {return _DebugNode;}
+ AppView * view() {return _pView;}
+ NodeGroup* debugScene() {return _DebugNode;}
+ Grid& grid() {return _Grid;}
+
+ void toggleVisibilityAlgo();
+
+ void setQuantitativeInvisibility(bool iBool); // if true, we compute quantitativeInvisibility
+ bool getQuantitativeInvisibility() const;
+
+ void setComputeRidgesAndValleysFlag(bool b);
+ bool getComputeRidgesAndValleysFlag() const ;
+ void setComputeSuggestiveContoursFlag(bool b);
+ bool getComputeSuggestiveContoursFlag() const ;
+
+ void setComputeSteerableViewMapFlag(bool iBool);
+ bool getComputeSteerableViewMapFlag() const;
+ void setSphereRadius(real s){_sphereRadius=s;}
+ real getSphereRadius() const {return _sphereRadius;}
+ void setSuggestiveContourKrDerivativeEpsilon(real dkr){_suggestiveContourKrDerivativeEpsilon=dkr;}
+ real getSuggestiveContourKrDerivativeEpsilon() const {return _suggestiveContourKrDerivativeEpsilon;}
+
+ void setModelsDir(const string& dir);
+ string getModelsDir() const;
+ void setModulesDir(const string& dir);
+ string getModulesDir() const;
+ void setHelpIndex(const string& dir);
+ string getHelpIndex() const;
+ void setBrowserCmd(const string& cmd);
+ string getBrowserCmd() const;
+
+ void resetInterpreter();
+
+public:
+ // Viewmap data structure
+ ViewMap * _ViewMap;
+
+ // Canvas
+ AppCanvas *_Canvas;
+
+private:
+
+ // Main Window:
+ //AppMainWindow *_pMainWindow;
+
+ // List of models currently loaded
+ vector<string> _ListOfModels;
+
+ // Current directories
+ //ConfigIO* _current_dirs;
+
+
+
+ //View
+ // 3D
+ AppView *_pView;
+
+ // 2D
+ //Viewer2DWindow *_pView2DWindow;
+ //Viewer2D *_pView2D;
+
+ //Model
+ // Drawing Structure
+ NodeGroup *_RootNode;
+
+ // Winged-Edge structure
+ WingedEdge* _winged_edge;
+
+ // Silhouette structure:
+ //std::vector<SShape*> _SShapes;
+ //NodeGroup *_SRoot;
+
+ // Silhouette
+ NodeGroup *_SilhouetteNode;
+ NodeGroup *_ProjectedSilhouette;
+ NodeGroup *_VisibleProjectedSilhouette;
+
+ // more Debug info
+ NodeGroup *_DebugNode;
+
+ // debug
+ // NodeUser<ViewMap> *_ViewMapNode; // FIXME
+
+ // Chronometer:
+ Chronometer _Chrono;
+
+ // Progress Bar
+ ProgressBar *_ProgressBar;
+
+ // edges tesselation nature
+ int _edgeTesselationNature;
+
+ FastGrid _Grid;
+ //HashGrid _Grid;
+
+ unsigned int _SceneNumFaces;
+ real _minEdgeSize;
+ real _EPSILON;
+ real _bboxDiag;
+
+ int _render_count;
+
+ //AppStyleWindow *_pStyleWindow;
+ //AppOptionsWindow *_pOptionsWindow;
+ //AppDensityCurvesWindow *_pDensityCurvesWindow;
+
+ ViewMapBuilder::visibility_algo _VisibilityAlgo;
+
+ // Script Interpreter
+ Interpreter* _inter;
+
+ string _help_index;
+ string _browser_cmd;
+
+ bool _EnableQI;
+ bool _ComputeRidges;
+ bool _ComputeSuggestive;
+ real _sphereRadius;
+ real _suggestiveContourKrDerivativeEpsilon;
+
+ bool _ComputeSteerableViewMap;
+
+ FEdgeXDetector edgeDetector;
+};
+
+extern Controller *g_pController;
+
+#endif // CONTROLLER_H
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
new file mode 100644
index 00000000000..ab7e58287cf
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -0,0 +1,427 @@
+#include "BlenderFileLoader.h"
+
+#include <assert.h>
+
+BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer* srl)
+{
+ _re = re;
+ _srl = srl;
+ _Scene = NULL;
+ _numFacesRead = 0;
+ _minEdgeSize = DBL_MAX;
+}
+
+BlenderFileLoader::~BlenderFileLoader()
+{
+ _Scene = NULL;
+}
+
+NodeGroup* BlenderFileLoader::Load()
+{
+ ObjectInstanceRen *obi;
+
+ cout << "\n=== Importing triangular meshes into Blender ===" << endl;
+
+ // creation of the scene root node
+ _Scene = new NodeGroup;
+
+ _viewplane_left= _re->viewplane.xmin;
+ _viewplane_right= _re->viewplane.xmax;
+ _viewplane_bottom= _re->viewplane.ymin;
+ _viewplane_top= _re->viewplane.ymax;
+ _z_near= -_re->clipsta;
+ _z_far= -_re->clipend;
+#if 0
+ cout << "frustrum: l " << _viewplane_left << " r " << _viewplane_right
+ << " b " << _viewplane_bottom << " t " << _viewplane_top
+ << " n " << _z_near << " f " << _z_far << endl;
+#endif
+
+ int id = 0;
+ for(obi= (ObjectInstanceRen *) _re->instancetable.first; obi; obi=obi->next) {
+ if (!(obi->lay & _re->scene->lay & _srl->lay))
+ continue;
+ char *name = obi->ob->id.name;
+ //cout << name[0] << name[1] << ":" << (name+2) <<;
+ //print_m4("obi->mat", obi->mat);
+
+ if( obi->obr->totvlak > 0)
+ insertShapeNode(obi, ++id);
+ else
+ cout << "Warning: " << (name+2) << " is not a vlak-based object (ignored)" << endl;
+ }
+
+ //Returns the built scene.
+ return _Scene;
+}
+
+#define CLIPPED_BY_NEAR -1
+#define NOT_CLIPPED 0
+#define CLIPPED_BY_FAR 1
+
+// check if each vertex of a triangle (V1, V2, V3) is clipped by the near/far plane
+// and calculate the number of triangles to be generated by clipping
+int BlenderFileLoader::countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3])
+{
+ float *v[3];
+ int numClipped, sum, numTris;
+
+ v[0] = v1;
+ v[1] = v2;
+ v[2] = v3;
+ numClipped = sum = 0;
+ for (int i = 0; i < 3; i++) {
+ if (v[i][2] > _z_near) {
+ clip[i] = CLIPPED_BY_NEAR;
+ numClipped++;
+ } else if (v[i][2] < _z_far) {
+ clip[i] = CLIPPED_BY_FAR;
+ numClipped++;
+ } else {
+ clip[i] = NOT_CLIPPED;
+ }
+// printf("%d %s\n", i, (clip[i] == NOT_CLIPPED) ? "not" : (clip[i] == CLIPPED_BY_NEAR) ? "near" : "far");
+ sum += clip[i];
+ }
+ switch (numClipped) {
+ case 0:
+ numTris = 1; // triangle
+ break;
+ case 1:
+ numTris = 2; // tetragon
+ break;
+ case 2:
+ if (sum == 0)
+ numTris = 3; // pentagon
+ else
+ numTris = 1; // triangle
+ break;
+ case 3:
+ if (sum == 3 || sum == -3)
+ numTris = 0;
+ else
+ numTris = 2; // tetragon
+ break;
+ }
+ return numTris;
+}
+
+// find the intersection point C between the line segment from V1 to V2 and
+// a clipping plane at depth Z (i.e., the Z component of C is known, while
+// the X and Y components are unknown).
+void BlenderFileLoader::clipLine(float v1[3], float v2[3], float c[3], float z)
+{
+ double d[3];
+ for (int i = 0; i < 3; i++)
+ d[i] = v2[i] - v1[i];
+ double t = (z - v1[2]) / d[2];
+ c[0] = v1[0] + t * d[0];
+ c[1] = v1[1] + t * d[1];
+ c[2] = z;
+}
+
+// clip the triangle (V1, V2, V3) by the near and far clipping plane and
+// obtain a set of vertices after the clipping. The number of vertices
+// is at most 5.
+void BlenderFileLoader::clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], int clip[3])
+{
+ float *v[3];
+ int i, j, k;
+
+ v[0] = v1;
+ v[1] = v2;
+ v[2] = v3;
+ k = 0;
+ for (i = 0; i < 3; i++) {
+ j = (i + 1) % 3;
+ if (clip[i] == NOT_CLIPPED) {
+ copy_v3_v3(triCoords[k++], v[i]);
+ if (clip[j] != NOT_CLIPPED) {
+ clipLine(v[i], v[j], triCoords[k++], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ }
+ } else if (clip[i] != clip[j]) {
+ if (clip[j] == NOT_CLIPPED) {
+ clipLine(v[i], v[j], triCoords[k++], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ } else {
+ clipLine(v[i], v[j], triCoords[k++], (clip[i] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ clipLine(v[i], v[j], triCoords[k++], (clip[j] == CLIPPED_BY_NEAR) ? _z_near : _z_far);
+ }
+ }
+ }
+ assert (k == 2 + numTris);
+}
+
+void BlenderFileLoader::addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3])
+{
+ float v12[3], v13[3], n[3];
+ float *fv[3], len;
+ unsigned i, j;
+
+ // initialize the bounding box by the first vertex
+ if (ls->currentIndex == 0) {
+ copy_v3_v3(ls->minBBox, v1);
+ copy_v3_v3(ls->maxBBox, v1);
+ }
+
+ // compute the normal of the triangle
+ sub_v3_v3v3(v12, v1, v2);
+ sub_v3_v3v3(v13, v1, v3);
+ cross_v3_v3v3(n, v12, v13);
+ normalize_v3(n);
+
+ fv[0] = v1;
+ fv[1] = v2;
+ fv[2] = v3;
+ for (i = 0; i < 3; i++) {
+
+ copy_v3_v3(ls->pv, fv[i]);
+ copy_v3_v3(ls->pn, n);
+
+ // update the bounding box
+ for (j = 0; j < 3; j++)
+ {
+ if (ls->minBBox[j] > ls->pv[j])
+ ls->minBBox[j] = ls->pv[j];
+
+ if (ls->maxBBox[j] < ls->pv[j])
+ ls->maxBBox[j] = ls->pv[j];
+ }
+
+ len = len_v3v3(fv[i], fv[(i + 1) % 3]);
+ if (_minEdgeSize > len)
+ _minEdgeSize = len;
+
+ *ls->pvi = ls->currentIndex;
+ *ls->pni = ls->currentIndex;
+ *ls->pmi = ls->currentMIndex;
+
+ ls->currentIndex +=3;
+ ls->pv += 3;
+ ls->pn += 3;
+
+ ls->pvi++;
+ ls->pni++;
+ ls->pmi++;
+ }
+}
+
+void BlenderFileLoader::insertShapeNode(ObjectInstanceRen *obi, int id)
+{
+ ObjectRen *obr = obi->obr;
+
+ // We parse vlak nodes and count the number of faces after the clipping by
+ // the near and far view planes is applied (Note: mesh vertices are in the
+ // camera coordinate system).
+ VlakRen *vlr;
+ unsigned numFaces = 0;
+ float v1[3], v2[3], v3[3], v4[3];
+ int clip_1[3], clip_2[3];
+ for(int a=0; a < obr->totvlak; a++) {
+ if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
+ else vlr++;
+ copy_v3_v3(v1, vlr->v1->co);
+ copy_v3_v3(v2, vlr->v2->co);
+ copy_v3_v3(v3, vlr->v3->co);
+ if (vlr->v4) copy_v3_v3(v4, vlr->v4->co);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m4_v3(obi->mat, v1);
+ mul_m4_v3(obi->mat, v2);
+ mul_m4_v3(obi->mat, v3);
+ if (vlr->v4) mul_m4_v3(obi->mat, v4);
+ }
+// print_v3("v1", v1);
+// print_v3("v2", v2);
+// print_v3("v3", v3);
+// if (vlr->v4) print_v3("v4", v4);
+ numFaces += countClippedFaces(v1, v2, v3, clip_1);
+ if (vlr->v4)
+ numFaces += countClippedFaces(v1, v3, v4, clip_2);
+ }
+// cout <<"numFaces " <<numFaces<<endl;
+ if (numFaces == 0)
+ return;
+
+ // We allocate memory for the meshes to be imported
+ NodeTransform *currentMesh = new NodeTransform;
+ NodeShape * shape = new NodeShape;
+
+ unsigned vSize = 3*3*numFaces;
+ float *vertices = new float[vSize];
+ unsigned nSize = vSize;
+ float *normals = new float[nSize];
+ unsigned *numVertexPerFaces = new unsigned[numFaces];
+ vector<FrsMaterial> meshFrsMaterials;
+
+ IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces];
+ unsigned i;
+ for (i = 0; i <numFaces; i++) {
+ faceStyle[i] = IndexedFaceSet::TRIANGLES;
+ numVertexPerFaces[i] = 3;
+ }
+
+ unsigned viSize = 3*numFaces;
+ unsigned *VIndices = new unsigned[viSize];
+ unsigned niSize = viSize;
+ unsigned *NIndices = new unsigned[niSize];
+ unsigned *MIndices = new unsigned[viSize]; // Material Indices
+
+ struct LoaderState ls;
+ ls.pv = vertices;
+ ls.pn = normals;
+ ls.pvi = VIndices;
+ ls.pni = NIndices;
+ ls.pmi = MIndices;
+ ls.currentIndex = 0;
+ ls.currentMIndex = 0;
+
+ FrsMaterial tmpMat;
+
+ // We parse the vlak nodes again and import meshes while applying the clipping
+ // by the near and far view planes.
+ int p;
+ for(p=0; p < obr->totvlak; ++p) // we parse the faces of the mesh
+ {
+ // Lib3dsFace *f=&mesh->faceL[p];
+ // Lib3dsMaterial *mat=0;
+ if((p & 255)==0) vlr = obr->vlaknodes[p>>8].vlak;
+ else vlr++;
+ copy_v3_v3(v1, vlr->v1->co);
+ copy_v3_v3(v2, vlr->v2->co);
+ copy_v3_v3(v3, vlr->v3->co);
+ if (vlr->v4) copy_v3_v3(v4, vlr->v4->co);
+ if (obi->flag & R_TRANSFORMED) {
+ mul_m4_v3(obi->mat, v1);
+ mul_m4_v3(obi->mat, v2);
+ mul_m4_v3(obi->mat, v3);
+ if (vlr->v4) mul_m4_v3(obi->mat, v4);
+ }
+
+ unsigned numTris_1, numTris_2;
+ numTris_1 = countClippedFaces(v1, v2, v3, clip_1);
+ numTris_2 = (vlr->v4) ? countClippedFaces(v1, v3, v4, clip_2) : 0;
+ if (numTris_1 == 0 && numTris_2 == 0)
+ continue;
+
+ Material *mat = vlr->mat;
+
+ if (mat)
+ {
+ tmpMat.setDiffuse( mat->r, mat->g, mat->b, mat->alpha );
+ tmpMat.setSpecular( mat->specr, mat->specg, mat->specb, mat->spectra);
+ float s = 1.0 * (mat->har + 1) / 4 ; // in Blender: [1;511] => in OpenGL: [0;128]
+ if(s > 128.f)
+ s = 128.f;
+ tmpMat.setShininess(s);
+ }
+
+ if(meshFrsMaterials.empty())
+ {
+ meshFrsMaterials.push_back(tmpMat);
+ shape->setFrsMaterial(tmpMat);
+ } else {
+ // find if the material is aleady in the list
+ unsigned i=0;
+ bool found = false;
+
+ for(vector<FrsMaterial>::iterator it=meshFrsMaterials.begin(), itend=meshFrsMaterials.end();
+ it!=itend;
+ ++it){
+ if(*it == tmpMat){
+ ls.currentMIndex = i;
+ found = true;
+ break;
+ }
+ ++i;
+ }
+
+ if(!found){
+ meshFrsMaterials.push_back(tmpMat);
+ ls.currentMIndex = meshFrsMaterials.size()-1;
+ }
+ }
+
+ float triCoords[5][3];
+
+ if (numTris_1 > 0) {
+ clipTriangle(numTris_1, triCoords, v1, v2, v3, clip_1);
+ for (i = 0; i < numTris_1; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2]);
+ _numFacesRead++;
+ }
+ }
+
+ if (numTris_2 > 0) {
+ clipTriangle(numTris_2, triCoords, v1, v3, v4, clip_2);
+ for (i = 0; i < numTris_2; i++) {
+ addTriangle(&ls, triCoords[0], triCoords[i+1], triCoords[i+2]);
+ _numFacesRead++;
+ }
+ }
+ }
+
+ // We might have several times the same vertex. We want a clean
+ // shape with no real-vertex. Here, we are making a cleaning
+ // pass.
+ real *cleanVertices = NULL;
+ unsigned cvSize;
+ unsigned *cleanVIndices = NULL;
+
+ GeomCleaner::CleanIndexedVertexArray(
+ vertices, vSize,
+ VIndices, viSize,
+ &cleanVertices, &cvSize,
+ &cleanVIndices);
+
+ real *cleanNormals = NULL;
+ unsigned cnSize;
+ unsigned *cleanNIndices = NULL;
+
+ GeomCleaner::CleanIndexedVertexArray(
+ normals, nSize,
+ NIndices, niSize,
+ &cleanNormals, &cnSize,
+ &cleanNIndices);
+
+ // format materials array
+ FrsMaterial** marray = new FrsMaterial*[meshFrsMaterials.size()];
+ unsigned mindex=0;
+ for(vector<FrsMaterial>::iterator m=meshFrsMaterials.begin(), mend=meshFrsMaterials.end();
+ m!=mend;
+ ++m){
+ marray[mindex] = new FrsMaterial(*m);
+ ++mindex;
+ }
+ // deallocates memory:
+ delete [] vertices;
+ delete [] normals;
+ delete [] VIndices;
+ delete [] NIndices;
+
+ // Create the IndexedFaceSet with the retrieved attributes
+ IndexedFaceSet *rep;
+ rep = new IndexedFaceSet(cleanVertices, cvSize,
+ cleanNormals, cnSize,
+ marray, meshFrsMaterials.size(),
+ 0, 0,
+ numFaces, numVertexPerFaces, faceStyle,
+ cleanVIndices, viSize,
+ cleanNIndices, niSize,
+ MIndices, viSize,
+ 0,0,
+ 0);
+ // sets the id of the rep
+ rep->setId(Id(id, 0));
+
+ const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(ls.minBBox[0], ls.minBBox[1], ls.minBBox[2]),
+ Vec3r(ls.maxBBox[0], ls.maxBBox[1], ls.maxBBox[2]));
+ rep->setBBox(bbox);
+ shape->AddRep(rep);
+
+ Matrix44r meshMat = Matrix44r::identity();
+ currentMesh->setMatrix(meshMat);
+ currentMesh->Translate(0,0,0);
+
+ currentMesh->AddChild(shape);
+ _Scene->AddChild(currentMesh);
+
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
new file mode 100644
index 00000000000..038f4bdd6c8
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h
@@ -0,0 +1,84 @@
+#ifndef BLENDER_FILE_LOADER_H
+# define BLENDER_FILE_LOADER_H
+
+# include <string.h>
+# include <float.h>
+
+# include "../system/FreestyleConfig.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../scene_graph/NodeTransform.h"
+# include "../scene_graph/NodeShape.h"
+# include "../scene_graph/IndexedFaceSet.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "../geometry/GeomCleaner.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ #include "DNA_material_types.h"
+ #include "DNA_scene_types.h"
+ #include "render_types.h"
+ #include "renderdatabase.h"
+
+ #include "BKE_mesh.h"
+ #include "BKE_scene.h"
+ #include "BLI_math.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+class NodeGroup;
+
+struct LoaderState {
+ float *pv;
+ float *pn;
+ unsigned *pvi;
+ unsigned *pni;
+ unsigned *pmi;
+ unsigned currentIndex;
+ unsigned currentMIndex;
+ float minBBox[3];
+ float maxBBox[3];
+};
+
+class LIB_SCENE_GRAPH_EXPORT BlenderFileLoader
+{
+public:
+ /*! Builds a MaxFileLoader */
+ BlenderFileLoader(Render *re, SceneRenderLayer* srl);
+ virtual ~BlenderFileLoader();
+
+ /*! Loads the 3D scene and returns a pointer to the scene root node */
+ NodeGroup * Load();
+
+ /*! Gets the number of read faces */
+ inline unsigned int numFacesRead() {return _numFacesRead;}
+
+ /*! Gets the smallest edge size read */
+ inline real minEdgeSize() {return _minEdgeSize;}
+
+protected:
+ void insertShapeNode(ObjectInstanceRen *obi, int id);
+ int countClippedFaces(float v1[3], float v2[3], float v3[3], int clip[3]);
+ void clipLine(float v1[3], float v2[3], float c[3], float z);
+ void clipTriangle(int numTris, float triCoords[][3], float v1[3], float v2[3], float v3[3], int clip[3]);
+ void addTriangle(struct LoaderState *ls, float v1[3], float v2[3], float v3[3]);
+
+protected:
+ Render* _re;
+ SceneRenderLayer* _srl;
+ NodeGroup* _Scene;
+ unsigned _numFacesRead;
+ real _minEdgeSize;
+ float _viewplane_left;
+ float _viewplane_right;
+ float _viewplane_bottom;
+ float _viewplane_top;
+ float _z_near, _z_far;
+};
+
+#endif // BLENDER_FILE_LOADER_H
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
new file mode 100644
index 00000000000..a03b7eb4c58
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -0,0 +1,336 @@
+# include "BlenderStrokeRenderer.h"
+# include "../stroke/Canvas.h"
+# include "../application/AppConfig.h"
+
+# include "BlenderTextureManager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_customdata_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_library.h" /* free_libblock */
+#include "BKE_material.h"
+#include "BKE_main.h" /* struct Main */
+#include "BKE_object.h"
+#include "BKE_scene.h"
+
+#include "RE_pipeline.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+BlenderStrokeRenderer::BlenderStrokeRenderer(Render* re, int render_count)
+:StrokeRenderer(){
+
+ // TEMPORARY - need a texture manager
+ _textureManager = new BlenderTextureManager;
+ _textureManager->load();
+
+ // Scene.New("FreestyleStrokes")
+ old_scene = re->scene;
+
+ ListBase lb;
+ char name[22];
+ snprintf(name, sizeof(name), "FRS%d_%s", render_count, re->scene->id.name+2);
+ freestyle_scene = add_scene(name);
+ lb = freestyle_scene->r.layers;
+ freestyle_scene->r= old_scene->r;
+ freestyle_scene->r.layers= lb;
+ set_scene_bg( freestyle_scene );
+
+ // image dimensions
+ float ycor = ((float)re->r.yasp) / ((float)re->r.xasp);
+ float width = freestyle_scene->r.xsch;
+ float height = freestyle_scene->r.ysch * ycor;
+
+ // Camera
+ Object* object_camera = add_object(freestyle_scene, OB_CAMERA);
+
+ Camera* camera = (Camera *) object_camera->data;
+ camera->type = CAM_ORTHO;
+ camera->ortho_scale = max(width,height);
+ camera->clipsta = 0.1f;
+ camera->clipend = 100.0f;
+
+ _z_delta = 0.00001f;
+ _z = camera->clipsta + _z_delta;
+
+ // test
+ //_z = 999.90f; _z_delta = 0.01f;
+
+ object_camera->loc[0] = 0.5 * width;
+ object_camera->loc[1] = 0.5 * height;
+ object_camera->loc[2] = 1.0;
+
+ freestyle_scene->camera = object_camera;
+
+ // Material
+ material = add_material("stroke_material");
+ material->mode |= MA_VERTEXCOLP;
+ material->mode |= MA_TRANSP;
+ material->mode |= MA_SHLESS;
+ material->vcol_alpha = 1;
+}
+
+BlenderStrokeRenderer::~BlenderStrokeRenderer(){
+
+ if(0 != _textureManager)
+ {
+ delete _textureManager;
+ _textureManager = 0;
+ }
+
+ // release objects and data blocks
+ Base *b = (Base *)freestyle_scene->base.first;
+ while(b) {
+ Object *ob = b->object;
+ void *data = ob->data;
+ char name[24];
+ strcpy(name, ob->id.name);
+ //cout << "removing " << name[0] << name[1] << ":" << (name+2) << endl;
+ switch (ob->type) {
+ case OB_MESH:
+ free_libblock( &G.main->object, ob );
+ free_libblock( &G.main->mesh, data );
+ break;
+ case OB_CAMERA:
+ free_libblock( &G.main->object, ob );
+ free_libblock( &G.main->camera, data );
+ freestyle_scene->camera = NULL;
+ break;
+ default:
+ cerr << "Warning: unexpected object in the scene: " << name[0] << name[1] << ":" << (name+2) << endl;
+ }
+ b = b->next;
+ }
+ BLI_freelistN( &freestyle_scene->base );
+
+ // release material
+ free_libblock( &G.main->mat, material );
+
+ set_scene_bg( old_scene );
+}
+
+float BlenderStrokeRenderer::get_stroke_vertex_z(void) const {
+ float z = _z;
+ BlenderStrokeRenderer *self = const_cast<BlenderStrokeRenderer *>(this);
+ if (!(_z < _z_delta * 100000.0f))
+ self->_z_delta *= 10.0f;
+ self->_z += _z_delta;
+ return -z;
+}
+
+void BlenderStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void BlenderStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
+
+ ////////////////////
+ // Build up scene
+ ////////////////////
+
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec3r color[3];
+ unsigned int vertex_index;
+ float ycor = ((float)freestyle_scene->r.yasp) / ((float)freestyle_scene->r.xasp);
+ float width = freestyle_scene->r.xsch;
+ float height = freestyle_scene->r.ysch * ycor;
+ Vec2r p;
+
+ for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
+ s!=send;
+ ++s){
+
+ Strip::vertex_container& strip_vertices = (*s)->vertices();
+ int strip_vertex_count = (*s)->sizeStrip();
+ int m, n, visible_faces, visible_segments;
+ bool visible;
+
+ // iterate over all vertices and count visible faces and strip segments
+ // (note: a strip segment is a series of visible faces, while two strip
+ // segments are separated by one or more invisible faces)
+ v[0] = strip_vertices.begin();
+ v[1] = v[0]; ++(v[1]);
+ v[2] = v[1]; ++(v[2]);
+ visible_faces = visible_segments = 0;
+ visible = false;
+ for (n = 2; n < strip_vertex_count; n++)
+ {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ m = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0 || p[0] > width || p[1] < 0.0 || p[1] > height)
+ m++;
+ }
+ if (m == 3) {
+ visible = false;
+ } else {
+ visible_faces++;
+ if (!visible)
+ visible_segments++;
+ visible = true;
+ }
+ ++v[0]; ++v[1]; ++v[2];
+ }
+ if (visible_faces == 0)
+ continue;
+
+ // me = Mesh.New()
+ Object* object_mesh = add_object(freestyle_scene, OB_MESH);
+ Mesh* mesh = (Mesh *) object_mesh->data;
+ MEM_freeN(mesh->bb);
+ mesh->bb= NULL;
+ mesh->id.us = 0;
+
+#if 1
+ // me.materials = [mat]
+ mesh->mat = ( Material ** ) MEM_mallocN( 1 * sizeof( Material * ), "MaterialList" );
+ mesh->mat[0] = material;
+ mesh->totcol = 1;
+ test_object_materials( (ID*) mesh );
+#else
+ assign_material(object_mesh, material, object_mesh->totcol+1);
+ object_mesh->actcol= object_mesh->totcol;
+#endif
+
+ // vertices allocation
+ mesh->totvert = visible_faces + visible_segments * 2;
+ mesh->mvert = (MVert*) CustomData_add_layer( &mesh->vdata, CD_MVERT, CD_CALLOC, NULL, mesh->totvert);
+
+ // faces allocation
+ mesh->totface = visible_faces;
+ mesh->mface = (MFace*) CustomData_add_layer( &mesh->fdata, CD_MFACE, CD_CALLOC, NULL, mesh->totface);
+
+ // colors allocation - me.vertexColors = True
+ mesh->mcol = (MCol *) CustomData_add_layer( &mesh->fdata, CD_MCOL, CD_CALLOC, NULL, mesh->totface );
+
+ ////////////////////
+ // Data copy
+ ////////////////////
+
+ MVert* vertices = mesh->mvert;
+ MFace* faces = mesh->mface;
+ MCol* colors = mesh->mcol;
+
+ v[0] = strip_vertices.begin();
+ v[1] = v[0]; ++(v[1]);
+ v[2] = v[1]; ++(v[2]);
+
+ vertex_index = 0;
+ visible = false;
+
+ for (n = 2; n < strip_vertex_count; n++)
+ {
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+ m = 0;
+ for (int j = 0; j < 3; j++) {
+ p = svRep[j]->point2d();
+ if (p[0] < 0.0 || p[0] > width || p[1] < 0.0 || p[1] > height)
+ m++;
+ }
+ if (m == 3) {
+ visible = false;
+ } else {
+ if (!visible) {
+ vertex_index += 2;
+
+ // first vertex
+ vertices->co[0] = svRep[0]->point2d()[0];
+ vertices->co[1] = svRep[0]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+
+ // second vertex
+ vertices->co[0] = svRep[1]->point2d()[0];
+ vertices->co[1] = svRep[1]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+ ++vertices;
+ }
+ visible = true;
+
+ // vertex
+ vertices->co[0] = svRep[2]->point2d()[0];
+ vertices->co[1] = svRep[2]->point2d()[1];
+ vertices->co[2] = get_stroke_vertex_z();
+
+ // faces
+ faces->v1 = vertex_index - 2;
+ faces->v2 = vertex_index - 1;
+ faces->v3 = vertex_index;
+ faces->v4 = 0;
+
+ // colors
+ // red and blue are swapped - cf DNA_meshdata_types.h : MCol
+ color[0] = svRep[0]->color();
+ color[1] = svRep[1]->color();
+ color[2] = svRep[2]->color();
+
+ colors->r = (short)(255.0f*(color[0])[2]);
+ colors->g = (short)(255.0f*(color[0])[1]);
+ colors->b = (short)(255.0f*(color[0])[0]);
+ colors->a = (short)(255.0f*svRep[0]->alpha());
+ ++colors;
+
+ colors->r = (short)(255.0f*(color[1])[2]);
+ colors->g = (short)(255.0f*(color[1])[1]);
+ colors->b = (short)(255.0f*(color[1])[0]);
+ colors->a = (short)(255.0f*svRep[1]->alpha());
+ ++colors;
+
+ colors->r = (short)(255.0f*(color[2])[2]);
+ colors->g = (short)(255.0f*(color[2])[1]);
+ colors->b = (short)(255.0f*(color[2])[0]);
+ colors->a = (short)(255.0f*svRep[2]->alpha());
+ ++colors;
+
+ ++faces; ++vertices; ++colors;
+ ++vertex_index;
+ }
+ ++v[0]; ++v[1]; ++v[2];
+
+ } // loop over strip vertices
+
+ } // loop over strips
+
+}
+
+Render* BlenderStrokeRenderer::RenderScene( Render *re ) {
+ Camera *camera = (Camera *)freestyle_scene->camera->data;
+ if (camera->clipend < _z)
+ camera->clipend = _z + _z_delta * 100.0f;
+ //cout << "clipsta " << camera->clipsta << ", clipend " << camera->clipend << endl;
+
+ freestyle_scene->r.mode &= ~( R_EDGE_FRS | R_SHADOW | R_SSS | R_PANORAMA | R_ENVMAP | R_MBLUR );
+ freestyle_scene->r.scemode &= ~( R_SINGLE_LAYER );
+ freestyle_scene->r.planes = R_PLANES32;
+ freestyle_scene->r.imtype = R_PNG;
+ if (freestyle_scene->r.mode & R_BORDER)
+ freestyle_scene->r.mode |= R_CROP;
+
+ Render *freestyle_render = RE_NewRender(freestyle_scene->id.name);
+
+ RE_RenderFreestyleStrokes(freestyle_render, freestyle_scene);
+ return freestyle_render;
+}
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
new file mode 100644
index 00000000000..40d87ce53a1
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h
@@ -0,0 +1,44 @@
+#ifndef BLENDERSTROKERENDERER_H
+# define BLENDERSTROKERENDERER_H
+
+# include "../stroke/StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "render_types.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+class LIB_STROKE_EXPORT BlenderStrokeRenderer : public StrokeRenderer
+{
+public:
+ BlenderStrokeRenderer(Render *re, int render_count);
+ virtual ~BlenderStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ Render* RenderScene(Render *re);
+
+protected:
+ Scene* old_scene;
+ Scene* freestyle_scene;
+ Material* material;
+ float _z, _z_delta;
+
+ float get_stroke_vertex_z(void) const;
+};
+
+#endif // BLENDERSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
new file mode 100644
index 00000000000..d731af42d0e
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.cpp
@@ -0,0 +1,71 @@
+#include "BlenderTextureManager.h"
+
+
+BlenderTextureManager::BlenderTextureManager ()
+: TextureManager()
+{
+ //_brushes_path = Config::getInstance()...
+}
+
+BlenderTextureManager::~BlenderTextureManager ()
+{
+}
+
+void BlenderTextureManager::loadStandardBrushes()
+{
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ //_defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+}
+
+
+unsigned
+BlenderTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
+{
+// GLuint texId;
+// glGenTextures(1, &texId);
+// bool found = false;
+// vector<string> pathnames;
+// string path; //soc
+// StringUtils::getPathName(TextureManager::Options::getBrushesPath(),
+// sname,
+// pathnames);
+// for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+// path = j->c_str();
+// //soc if(QFile::exists(path)){
+// if( BLI_exists( const_cast<char *>(path.c_str()) ) ) {
+// found = true;
+// break;
+// }
+// }
+// if(!found)
+// return 0;
+// // Brush texture
+// cout << "Loading brush texture..." << endl;
+// switch(mediumType){
+// case Stroke::DRY_MEDIUM:
+// //soc prepareTextureLuminance((const char*)path.toAscii(), texId);
+// prepareTextureLuminance(StringUtils::toAscii(path), texId);
+// break;
+// case Stroke::HUMID_MEDIUM:
+// case Stroke::OPAQUE_MEDIUM:
+// default:
+// //soc prepareTextureAlpha((const char*)path.toAscii(), texId);
+// prepareTextureAlpha(StringUtils::toAscii(path), texId);
+// break;
+// }
+// cout << "Done." << endl << endl;
+//
+// return texId;
+//
+ return 0;
+}
+
+
+
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h
new file mode 100644
index 00000000000..fac33c139e1
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/BlenderTextureManager.h
@@ -0,0 +1,23 @@
+#ifndef BLENDERTEXTUREMANAGER_H
+#define BLENDERTEXTUREMANAGER_H
+
+# include "../stroke/StrokeRenderer.h"
+# include "../stroke/StrokeRep.h"
+# include "../system/FreestyleConfig.h"
+
+/*! Class to load textures
+ */
+class LIB_RENDERING_EXPORT BlenderTextureManager : public TextureManager
+{
+ public:
+ BlenderTextureManager ();
+ virtual ~BlenderTextureManager ();
+protected:
+ virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM);
+
+ protected:
+ virtual void loadStandardBrushes();
+
+};
+
+#endif // BLENDERTEXTUREMANAGER_H
diff --git a/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
new file mode 100644
index 00000000000..1b22e1003d3
--- /dev/null
+++ b/source/blender/freestyle/intern/blender_interface/FRS_freestyle.cpp
@@ -0,0 +1,349 @@
+#include "../application/Controller.h"
+#include "../application/AppView.h"
+#include "../application/AppConfig.h"
+#include "../application/AppCanvas.h"
+
+#include <iostream>
+#include <map>
+#include <set>
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_freestyle_types.h"
+
+#include "BKE_main.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BPY_extern.h"
+
+#include "renderpipeline.h"
+#include "pixelblending.h"
+
+#include "../../FRS_freestyle.h"
+#include "../../FRS_freestyle_config.h"
+
+ // Freestyle configuration
+ static short freestyle_is_initialized = 0;
+ static Config::Path *pathconfig = NULL;
+ static Controller *controller = NULL;
+ static AppView *view = NULL;
+
+ // camera information
+ float freestyle_viewpoint[3];
+ float freestyle_mv[4][4];
+ float freestyle_proj[4][4];
+ int freestyle_viewport[4];
+
+ // current scene
+ Scene *freestyle_scene;
+
+ string default_module_path;
+
+ //=======================================================
+ // Initialization
+ //=======================================================
+
+ void FRS_initialize() {
+
+ if( freestyle_is_initialized )
+ return;
+
+ pathconfig = new Config::Path;
+ controller = new Controller();
+ view = new AppView;
+ controller->setView(view);
+ freestyle_scene = NULL;
+
+ default_module_path = pathconfig->getProjectDir() + Config::DIR_SEP + "style_modules" + Config::DIR_SEP + "contour.py";
+
+ freestyle_is_initialized = 1;
+ }
+
+ void FRS_set_context(bContext* C) {
+ cout << "FRS_set_context: context 0x" << C << " scene 0x" << CTX_data_scene(C) << endl;
+ controller->setContext(C);
+ }
+
+ void FRS_exit() {
+ delete pathconfig;
+ delete controller;
+ delete view;
+ }
+
+ //=======================================================
+ // Rendering
+ //=======================================================
+
+ void init_view(Render* re){
+ float ycor = ((float)re->r.yasp) / ((float)re->r.xasp);
+ int width = re->r.xsch;
+ int height = (int)(((float)re->r.ysch) * ycor);
+ int xmin = re->r.border.xmin * width;
+ int xmax = re->r.border.xmax * width;
+ int ymin = re->r.border.ymin * height;
+ int ymax = re->r.border.ymax * height;
+
+ freestyle_viewport[0] = freestyle_viewport[1] = 0;
+ freestyle_viewport[2] = width;
+ freestyle_viewport[3] = height;
+
+ view->setWidth( width );
+ view->setHeight( height );
+ view->setBorder( xmin, ymin, xmax, ymax );
+
+ cout << "\n=== Dimensions of the 2D image coordinate system ===" << endl;
+ cout << "Width : " << width << endl;
+ cout << "Height : " << height << endl;
+ if (re->r.mode & R_BORDER)
+ cout << "Border : (" << xmin << ", " << ymin << ") - (" << xmax << ", " << ymax << ")" << endl;
+ }
+
+ void init_camera(Render* re){
+ // It is assumed that imported meshes are in the camera coordinate system.
+ // Therefore, the view point (i.e., camera position) is at the origin, and
+ // the the model-view matrix is simply the identity matrix.
+
+ freestyle_viewpoint[0] = 0.0;
+ freestyle_viewpoint[1] = 0.0;
+ freestyle_viewpoint[2] = 0.0;
+
+ for( int i = 0; i < 4; i++ )
+ for( int j = 0; j < 4; j++ )
+ freestyle_mv[i][j] = (i == j) ? 1.0 : 0.0;
+
+ for( int i = 0; i < 4; i++ )
+ for( int j = 0; j < 4; j++ )
+ freestyle_proj[i][j] = re->winmat[i][j];
+
+ //print_m4("mv", freestyle_mv);
+ //print_m4("proj", freestyle_proj);
+ }
+
+
+ void prepare(Render* re, SceneRenderLayer* srl ) {
+
+ // clear canvas
+ controller->Clear();
+
+ // load mesh
+ re->i.infostr= "Freestyle: Mesh loading";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr= NULL;
+ if( controller->LoadMesh(re, srl) ) // returns if scene cannot be loaded or if empty
+ return;
+ if( re->test_break(re->tbh) )
+ return;
+
+ // add style modules
+ FreestyleConfig* config = &srl->freestyleConfig;
+
+ cout << "\n=== Rendering options ===" << endl;
+ cout << "Modules :"<< endl;
+ int layer_count = 0;
+
+
+ for( FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)config->modules.first; module_conf; module_conf = module_conf->next ) {
+ if( module_conf->is_displayed ) {
+ cout << " " << layer_count+1 << ": " << module_conf->module_path << endl;
+ controller->InsertStyleModule( layer_count, module_conf->module_path );
+ controller->toggleLayer(layer_count, true);
+ layer_count++;
+ }
+ }
+ cout << endl;
+
+ // set parameters
+ controller->setSphereRadius( config->sphere_radius );
+ controller->setComputeRidgesAndValleysFlag( (config->flags & FREESTYLE_RIDGES_AND_VALLEYS_FLAG) ? true : false);
+ controller->setComputeSuggestiveContoursFlag( (config->flags & FREESTYLE_SUGGESTIVE_CONTOURS_FLAG) ? true : false);
+ controller->setSuggestiveContourKrDerivativeEpsilon( config->dkr_epsilon ) ;
+
+ cout << "Sphere radius : " << controller->getSphereRadius() << endl;
+ cout << "Redges and valleys : " << (controller->getComputeRidgesAndValleysFlag() ? "enabled" : "disabled") << endl;
+ cout << "Suggestive contours : " << (controller->getComputeSuggestiveContoursFlag() ? "enabled" : "disabled") << endl;
+ cout << "Suggestive contour dkr epsilon : " << controller->getSuggestiveContourKrDerivativeEpsilon() << endl;
+ cout << endl;
+
+ // set diffuse and z depth passes
+ RenderLayer *rl = RE_GetRenderLayer(re->result, srl->name);
+ bool diffuse = false, z = false;
+ for (RenderPass *rpass = (RenderPass *)rl->passes.first; rpass; rpass = rpass->next) {
+ switch (rpass->passtype) {
+ case SCE_PASS_DIFFUSE:
+ controller->setPassDiffuse(rpass->rect, rpass->rectx, rpass->recty);
+ diffuse = true;
+ break;
+ case SCE_PASS_Z:
+ controller->setPassZ(rpass->rect, rpass->rectx, rpass->recty);
+ z = true;
+ break;
+ }
+ }
+ cout << "Passes :" << endl;
+ cout << " Diffuse = " << (diffuse ? "enabled" : "disabled") << endl;
+ cout << " Z = " << (z ? "enabled" : "disabled") << endl;
+
+ // compute view map
+ re->i.infostr= "Freestyle: View map creation";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr= NULL;
+ controller->ComputeViewMap();
+ }
+
+ void FRS_composite_result(Render* re, SceneRenderLayer* srl, Render* freestyle_render)
+ {
+ RenderLayer *rl;
+ float *src, *dest, *pixSrc, *pixDest;
+ int x, y, rectx, recty;
+
+ if( freestyle_render == NULL || freestyle_render->result == NULL )
+ return;
+
+ rl = render_get_active_layer( freestyle_render, freestyle_render->result );
+ if( !rl || rl->rectf == NULL) { cout << "Cannot find Freestyle result image" << endl; return; }
+ src = rl->rectf;
+ //cout << "src: " << rl->rectx << " x " << rl->recty << endl;
+
+ rl = RE_GetRenderLayer(re->result, srl->name);
+ if( !rl || rl->rectf == NULL) { cout << "No layer to composite to" << endl; return; }
+ dest = rl->rectf;
+ //cout << "dest: " << rl->rectx << " x " << rl->recty << endl;
+
+ rectx = re->rectx;
+ recty = re->recty;
+ for( y = 0; y < recty; y++) {
+ for( x = 0; x < rectx; x++) {
+ pixSrc = src + 4 * (rectx * y + x);
+ if( pixSrc[3] > 0.0) {
+ pixDest = dest + 4 * (rectx * y + x);
+ addAlphaOverFloat(pixDest, pixSrc);
+ }
+ }
+ }
+ }
+
+ int displayed_layer_count( SceneRenderLayer* srl ) {
+ int count = 0;
+
+ for( FreestyleModuleConfig* module_conf = (FreestyleModuleConfig *)srl->freestyleConfig.modules.first; module_conf; module_conf = module_conf->next ) {
+ if( module_conf->is_displayed )
+ count++;
+ }
+ return count;
+ }
+
+ int FRS_is_freestyle_enabled(SceneRenderLayer* srl) {
+ return (!(srl->layflag & SCE_LAY_DISABLE) &&
+ srl->layflag & SCE_LAY_FRS &&
+ displayed_layer_count(srl) > 0);
+ }
+
+ void FRS_init_stroke_rendering(Render* re) {
+
+ cout << "\n#===============================================================" << endl;
+ cout << "# Freestyle" << endl;
+ cout << "#===============================================================" << endl;
+
+ init_view(re);
+ init_camera(re);
+
+ controller->ResetRenderCount();
+ }
+
+ Render* FRS_do_stroke_rendering(Render* re, SceneRenderLayer *srl) {
+
+ Render* freestyle_render = NULL;
+
+ cout << "\n----------------------------------------------------------" << endl;
+ cout << "| " << (re->scene->id.name+2) << "|" << srl->name << endl;
+ cout << "----------------------------------------------------------" << endl;
+
+ // prepare Freestyle:
+ // - clear canvas
+ // - load mesh
+ // - add style modules
+ // - set parameters
+ // - compute view map
+ prepare(re, srl);
+
+ if( re->test_break(re->tbh) ) {
+ controller->CloseFile();
+ return NULL;
+ }
+
+ // render and composite Freestyle result
+ if( controller->_ViewMap ) {
+
+ // render strokes
+ re->i.infostr= "Freestyle: Stroke rendering";
+ re->stats_draw(re->sdh, &re->i);
+ re->i.infostr= NULL;
+ freestyle_scene = re->scene;
+ controller->DrawStrokes();
+ freestyle_render = controller->RenderStrokes(re);
+ controller->CloseFile();
+ freestyle_scene = NULL;
+
+ // composite result
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
+
+ return freestyle_render;
+ }
+
+ //=======================================================
+ // Freestyle Panel Configuration
+ //=======================================================
+
+ void FRS_add_freestyle_config( SceneRenderLayer* srl )
+ {
+ FreestyleConfig* config = &srl->freestyleConfig;
+
+ config->modules.first = config->modules.last = NULL;
+ config->flags = 0;
+ config->sphere_radius = 1.0;
+ config->dkr_epsilon = 0.001;
+ }
+
+ void FRS_free_freestyle_config( SceneRenderLayer* srl )
+ {
+ BLI_freelistN( &srl->freestyleConfig.modules );
+ }
+
+ void FRS_add_module(FreestyleConfig *config)
+ {
+ FreestyleModuleConfig* module_conf = (FreestyleModuleConfig*) MEM_callocN( sizeof(FreestyleModuleConfig), "style module configuration");
+ BLI_addtail(&config->modules, (void*) module_conf);
+
+ strcpy( module_conf->module_path, default_module_path.c_str() );
+ module_conf->is_displayed = 1;
+ }
+
+ void FRS_delete_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+ {
+ BLI_freelinkN(&config->modules, module_conf);
+ }
+
+ void FRS_move_up_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+ {
+ BLI_remlink(&config->modules, module_conf);
+ BLI_insertlink(&config->modules, module_conf->prev->prev, module_conf);
+ }
+
+ void FRS_move_down_module(FreestyleConfig *config, FreestyleModuleConfig *module_conf)
+ {
+ BLI_remlink(&config->modules, module_conf);
+ BLI_insertlink(&config->modules, module_conf->next, module_conf);
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
new file mode 100755
index 00000000000..9c46d7918e2
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -0,0 +1,141 @@
+//
+// Filename : BBox.h
+// Author(s) : Stephane Grabli
+// Purpose : A class to hold a bounding box
+// Date of creation : 22/05/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 BBOX_H
+# define BBOX_H
+
+template <class Point>
+class BBox
+{
+ public:
+
+ inline BBox() {
+ _empty = true;
+ }
+
+ template <class T>
+ inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in) {
+ _empty = false;
+ }
+
+ template <class T>
+ inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax()) {
+ _empty = false;
+ }
+
+ template <class T>
+ inline void extendToContain(const T& p) {
+ if (_empty) {
+ _min = p;
+ _max = p;
+ _empty = false;
+ return;
+ }
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ if (p[i] < _min[i])
+ _min[i] = p[i];
+ else if (p[i] > _max[i])
+ _max[i] = p[i];
+ }
+ _empty = false;
+ }
+
+ inline void clear() {
+ _empty = true;
+ }
+
+ inline bool empty() const {
+ return _empty;
+ }
+
+ inline const Point& getMin() const {
+ return _min;
+ }
+
+ inline const Point& getMax() const {
+ return _max;
+ }
+
+ inline BBox<Point>& operator=(const BBox<Point>& b) {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ return *this;
+ }
+
+ inline BBox<Point>& operator+=(const BBox<Point>& b) {
+ if (_empty) {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ }
+ else {
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ if (b.getMin()[i] < _min[i])
+ _min[i] = b.getMin()[i];
+ if (b.getMax()[i] > _max[i])
+ _max[i] = b.getMax()[i];
+ }
+ }
+ return *this;
+ }
+
+ inline bool inside(const Point& p){
+ if(empty())
+ return false;
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ if((_min[i]>p[i]) || (_max[i]<p[i]))
+ return false;
+ }
+ return true;
+
+ }
+
+private:
+
+ Point _min;
+ Point _max;
+ bool _empty;
+};
+
+template <class Point>
+BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
+{
+ Point new_min;
+ Point new_max;
+
+ for (unsigned i = 0; i < Point::dim(); i++) {
+ new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
+ new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
+ }
+
+ return BBox<Point>(new_min, new_max);
+}
+
+#endif // BBOX_H
diff --git a/source/blender/freestyle/intern/geometry/Bezier.cpp b/source/blender/freestyle/intern/geometry/Bezier.cpp
new file mode 100755
index 00000000000..8f9771f29d3
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Bezier.cpp
@@ -0,0 +1,118 @@
+
+//
+// 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 "Bezier.h"
+#include "FitCurve.h"
+
+using namespace std;
+
+BezierCurveSegment::BezierCurveSegment()
+{
+}
+
+BezierCurveSegment::~BezierCurveSegment()
+{
+}
+
+void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
+{
+ _ControlPolygon.push_back(iPoint);
+ if(_ControlPolygon.size() == 4)
+ Build();
+}
+
+void BezierCurveSegment::Build()
+{
+ if(_ControlPolygon.size() != 4)
+ return;
+
+ // Compute the rightmost part of the matrix:
+ vector<Vec2d>::const_iterator p0,p1,p2,p3;
+ p0 = _ControlPolygon.begin();
+ p1 = p0;++p1;
+ p2 = p1;++p2;
+ p3 = p2;++p3;
+ float x[4], y[4];
+
+ x[0] = -p0->x()+3*p1->x()-3*p2->x()+p3->x();
+ x[1] = 3*p0->x()-6*p1->x()+3*p2->x();
+ x[2] = -3*p0->x()+3*p1->x();
+ x[3] = p0->x();
+
+ y[0] = -p0->y()+3*p1->y()-3*p2->y()+p3->y();
+ y[1] = 3*p0->y()-6*p1->y()+3*p2->y();
+ y[2] = -3*p0->y()+3*p1->y();
+ y[3] = p0->y();
+
+ int nvertices = 12;
+ float increment = 1.0/(float)nvertices;
+ float t = 0.f;
+ for(int i=0; i<=nvertices; ++i)
+ {
+ _Vertices.push_back(Vec2d((x[3] + t*(x[2] + t*(x[1] + t*x[0]))),
+ (y[3] + t*(y[2] + t*(y[1] + t*y[0])))));
+ t+=increment;
+ }
+}
+
+BezierCurve::BezierCurve()
+{
+ _currentSegment = new BezierCurveSegment;
+}
+
+BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error)
+{
+ FitCurveWrapper fitcurve;
+ _currentSegment = new BezierCurveSegment;
+ vector<Vec2d> curve;
+
+ fitcurve.FitCurve(iPoints, curve, error);
+ int i=0;
+ vector<Vec2d>::iterator v,vend;
+ for(v=curve.begin(),vend=curve.end();
+ v!=vend;
+ ++v)
+ {
+ if((i == 0) || (i%4 != 0))
+ AddControlPoint(*v);
+ ++i;
+ }
+}
+
+BezierCurve::~BezierCurve()
+{
+ if(_currentSegment)
+ delete _currentSegment;
+}
+
+void BezierCurve::AddControlPoint(const Vec2d& iPoint)
+{
+ _ControlPolygon.push_back(iPoint);
+ _currentSegment->AddControlPoint(iPoint);
+ if(_currentSegment->size() == 4)
+ {
+ _Segments.push_back(_currentSegment);
+ _currentSegment = new BezierCurveSegment;
+ _currentSegment->AddControlPoint(iPoint);
+ }
+}
+
+
diff --git a/source/blender/freestyle/intern/geometry/Bezier.h b/source/blender/freestyle/intern/geometry/Bezier.h
new file mode 100755
index 00000000000..acae71bbb2c
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Bezier.h
@@ -0,0 +1,73 @@
+//
+// Filename : Bezier.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a Bezier curve of order 4.
+// Date of creation : 04/06/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 BEZIER_H
+# define BEZIER_H
+
+#include <vector>
+#include "../system/FreestyleConfig.h"
+#include "Geom.h"
+
+using namespace Geometry;
+
+class LIB_GEOMETRY_EXPORT BezierCurveSegment
+{
+private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<Vec2d> _Vertices;
+
+public:
+ BezierCurveSegment();
+ virtual ~BezierCurveSegment();
+
+ void AddControlPoint(const Vec2d& iPoint);
+ void Build();
+ inline int size() const {return _ControlPolygon.size();}
+ inline std::vector<Vec2d>& vertices() {return _Vertices;}
+};
+
+
+class LIB_GEOMETRY_EXPORT BezierCurve
+{
+private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<BezierCurveSegment*> _Segments;
+ BezierCurveSegment *_currentSegment;
+
+public:
+ BezierCurve();
+ BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
+ virtual ~BezierCurve();
+
+ void AddControlPoint(const Vec2d& iPoint);
+ std::vector<Vec2d>& controlPolygon() {return _ControlPolygon;}
+ std::vector<BezierCurveSegment*>& segments() {return _Segments;}
+};
+
+#endif // BEZIER_H
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.cpp b/source/blender/freestyle/intern/geometry/FastGrid.cpp
new file mode 100755
index 00000000000..325126b4b96
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FastGrid.cpp
@@ -0,0 +1,62 @@
+
+//
+// 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 "FastGrid.h"
+
+void FastGrid::clear() {
+ if(!_cells)
+ return;
+
+ for(unsigned i = 0; i < _cells_size; i++)
+ if (_cells[i])
+ delete _cells[i];
+ delete[] _cells;
+ _cells = NULL;
+ _cells_size = 0;
+
+ Grid::clear();
+}
+
+void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
+ Grid::configure(orig, size, nb);
+ _cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
+ _cells = new Cell*[_cells_size];
+ memset(_cells, 0, _cells_size * sizeof(*_cells));
+}
+
+Cell* FastGrid::getCell(const Vec3u& p) {
+ //cout << _cells<< " "<< p << " " <<_cells_nb[0]<<"-"<< _cells_nb[1]<<"-"<< _cells_nb[2]<< " "<<_cells_size<< endl;
+ assert(_cells||("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
+ assert(p[0]<_cells_nb[0]);
+ assert(p[1]<_cells_nb[1]);
+ assert(p[2]<_cells_nb[2]);
+ return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
+}
+
+void FastGrid::fillCell(const Vec3u& p, Cell& cell) {
+ assert(_cells||("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
+ assert(p[0]<_cells_nb[0]);
+ assert(p[1]<_cells_nb[1]);
+ assert(p[2]<_cells_nb[2]);
+ _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
+}
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.h b/source/blender/freestyle/intern/geometry/FastGrid.h
new file mode 100755
index 00000000000..e620ff24385
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FastGrid.h
@@ -0,0 +1,85 @@
+//
+// Filename : FastGrid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a cell grid surrounding the
+// bounding box of the scene
+// Date of creation : 30/07/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 FASTGRID_H
+# define FASTGRID_H
+
+# include "Grid.h"
+# include <cassert>
+/*! Class to define a regular grid used for ray
+ * casting computations
+ * We don't use a hashtable here. The grid is
+ * explicitly stored for faster computations.
+ * However, this might result in significant
+ * increase in memory usage (compared to the regular grid)
+ */
+
+class LIB_GEOMETRY_EXPORT FastGrid : public Grid
+{
+ public:
+
+ FastGrid() : Grid() {
+ _cells = NULL;
+ _cells_size = 0;
+ }
+
+ virtual ~FastGrid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable,
+ * resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates are pased as argument */
+ Cell* getCell(const Vec3u& p) ;
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell);
+
+protected:
+
+ Cell** _cells;
+ unsigned _cells_size;
+};
+
+#endif // FASTGRID_H
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp
new file mode 100755
index 00000000000..7754fcda32b
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -0,0 +1,603 @@
+
+//
+// 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 <cstdlib> // for malloc and free
+#include <stdio.h>
+#include <math.h>
+#include "FitCurve.h"
+
+using namespace std;
+
+typedef Vector2 *BezierCurve;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* Forward declarations */
+static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve);
+static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u);
+static Vector2 BezierII(int degree, Vector2 *V, double t);
+static double B0(double u);
+static double B1(double u);
+static double B2(double u);
+static double B3(double u);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static Vector2 ComputeLeftTangent(Vector2 *d, int end);
+static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
+static double *ChordLengthParameterize(Vector2 *d, int first, int last);
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
+static Vector2 V2AddII(Vector2 a, Vector2 b);
+static Vector2 V2ScaleIII(Vector2 v, double s);
+static Vector2 V2SubII(Vector2 a, Vector2 b);
+
+
+#define MAXPOINTS 1000 /* The most points you can have */
+
+/* returns squared length of input vector */
+double V2SquaredLength(Vector2 *a)
+{ return(((*a)[0] * (*a)[0])+((*a)[1] * (*a)[1]));
+}
+
+/* returns length of input vector */
+double V2Length(Vector2 *a)
+{
+ return(sqrt(V2SquaredLength(a)));
+}
+
+Vector2 *V2Scale(Vector2 *v, double newlen)
+{
+ double len = V2Length(v);
+ if (len != 0.0) { (*v)[0] *= newlen/len; (*v)[1] *= newlen/len; }
+ return(v);
+}
+
+/* return the dot product of vectors a and b */
+double V2Dot(Vector2 *a, Vector2 *b)
+{
+ return(((*a)[0]*(*b)[0])+((*a)[1]*(*b)[1]));
+}
+
+/* return the distance between two points */
+double V2DistanceBetween2Points(Vector2 *a, Vector2 *b)
+{
+double dx = (*a)[0] - (*b)[0];
+double dy = (*a)[1] - (*b)[1];
+ return(sqrt((dx*dx)+(dy*dy)));
+}
+
+/* return vector sum c = a+b */
+Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c)
+{
+ (*c)[0] = (*a)[0]+(*b)[0]; (*c)[1] = (*a)[1]+(*b)[1];
+ return(c);
+}
+
+/* normalizes the input vector and returns it */
+Vector2 *V2Normalize(Vector2 *v)
+{
+double len = V2Length(v);
+ if (len != 0.0) { (*v)[0] /= len; (*v)[1] /= len; }
+ return(v);
+}
+
+/* negates the input vector and returns it */
+Vector2 *V2Negate(Vector2 *v)
+{
+ (*v)[0] = -(*v)[0]; (*v)[1] = -(*v)[1];
+ return(v);
+}
+
+
+/*
+ * GenerateBezier :
+ * Use least-squares method to find Bezier control points for region.
+ *
+ */
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+// double *uPrime; /* Parameter values for region */
+// Vector2 tHat1, tHat2; /* Unit tangents at endpoints */
+{
+ int i;
+ Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
+ int nPts; /* Number of pts in sub-curve */
+ double C[2][2]; /* Matrix C */
+ double X[2]; /* Matrix X */
+ double det_C0_C1, /* Determinants of matrices */
+ det_C0_X,
+ det_X_C1;
+ double alpha_l, /* Alpha values, left and right */
+ alpha_r;
+ Vector2 tmp; /* Utility variable */
+ BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
+
+ bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ nPts = last - first + 1;
+
+
+ /* Compute the A's */
+ for (i = 0; i < nPts; i++) {
+ Vector2 v1, v2;
+ v1 = tHat1;
+ v2 = tHat2;
+ V2Scale(&v1, B1(uPrime[i]));
+ V2Scale(&v2, B2(uPrime[i]));
+ A[i][0] = v1;
+ A[i][1] = v2;
+ }
+
+ /* Create the C and X matrices */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+
+ for (i = 0; i < nPts; i++) {
+ C[0][0] += V2Dot(&A[i][0], &A[i][0]);
+ C[0][1] += V2Dot(&A[i][0], &A[i][1]);
+/* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/
+ C[1][0] = C[0][1];
+ C[1][1] += V2Dot(&A[i][1], &A[i][1]);
+
+ tmp = V2SubII(d[first + i],
+ V2AddII(
+ V2ScaleIII(d[first], B0(uPrime[i])),
+ V2AddII(
+ V2ScaleIII(d[first], B1(uPrime[i])),
+ V2AddII(
+ V2ScaleIII(d[last], B2(uPrime[i])),
+ V2ScaleIII(d[last], B3(uPrime[i]))))));
+
+
+ X[0] += V2Dot(&((A[i])[0]), &tmp);
+ X[1] += V2Dot(&((A[i])[1]), &tmp);
+ }
+
+ /* Compute the determinants of C and X */
+ det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+
+ /* Finally, derive alpha values */
+ if (det_C0_C1 == 0.0) {
+ det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
+ }
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text) */
+ /* (if alpha is 0, you get coincident control points that lead to
+ * divide by zero in any subsequent NewtonRaphsonRootFind() call. */
+ if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) /
+ 3.0;
+
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1]));
+ V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2]));
+ return (bezCurve);
+ }
+
+ /* First and last control points of the Bezier curve are */
+ /* positioned exactly at the first and last data points */
+ /* Control points 1 and 2 are positioned an alpha distance out */
+ /* on the tangent vectors, left and right, respectively */
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
+ return (bezCurve);
+}
+
+
+/*
+ * Reparameterize:
+ * Given set of points and their parameterization, try to find
+ * a better parameterization.
+ *
+ */
+static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+// double *u; /* Current parameter values */
+// BezierCurve bezCurve; /* Current fitted curve */
+{
+ int nPts = last-first+1;
+ int i;
+ double *uPrime; /* New parameter values */
+
+ uPrime = (double *)malloc(nPts * sizeof(double));
+ for (i = first; i <= last; i++) {
+ uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-
+ first]);
+ }
+ return (uPrime);
+}
+
+
+
+/*
+ * NewtonRaphsonRootFind :
+ * Use Newton-Raphson iteration to find better root.
+ */
+static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
+// BezierCurve Q; /* Current fitted curve */
+// Vector2 P; /* Digitized point */
+// double u; /* Parameter value for "P" */
+{
+ double numerator, denominator;
+ Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
+ Vector2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */
+ double uPrime; /* Improved u */
+ int i;
+
+ /* Compute Q(u) */
+ Q_u = BezierII(3, Q, u);
+
+ /* Generate control vertices for Q' */
+ for (i = 0; i <= 2; i++) {
+ Q1[i][0] = (Q[i+1][0] - Q[i][0]) * 3.0;
+ Q1[i][1] = (Q[i+1][1] - Q[i][1]) * 3.0;
+ }
+
+ /* Generate control vertices for Q'' */
+ for (i = 0; i <= 1; i++) {
+ Q2[i][0] = (Q1[i+1][0] - Q1[i][0]) * 2.0;
+ Q2[i][1] = (Q1[i+1][1] - Q1[i][1]) * 2.0;
+ }
+
+ /* Compute Q'(u) and Q''(u) */
+ Q1_u = BezierII(2, Q1, u);
+ Q2_u = BezierII(1, Q2, u);
+
+ /* Compute f(u)/f'(u) */
+ numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
+ denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
+ (Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
+
+ /* u = u - f(u)/f'(u) */
+ if(denominator == 0) // FIXME
+ return u;
+ uPrime = u - (numerator/denominator);
+ return (uPrime);
+}
+
+
+
+/*
+ * Bezier :
+ * Evaluate a Bezier curve at a particular parameter value
+ *
+ */
+static Vector2 BezierII(int degree, Vector2 *V, double t)
+// int degree; /* The degree of the bezier curve */
+// Vector2 *V; /* Array of control points */
+// double t; /* Parametric value to find point for */
+{
+ int i, j;
+ Vector2 Q; /* Point on curve at parameter t */
+ Vector2 *Vtemp; /* Local copy of control points */
+
+ /* Copy array */
+ Vtemp = (Vector2 *)malloc((unsigned)((degree+1)
+ * sizeof (Vector2)));
+ for (i = 0; i <= degree; i++) {
+ Vtemp[i] = V[i];
+ }
+
+ /* Triangle computation */
+ for (i = 1; i <= degree; i++) {
+ for (j = 0; j <= degree-i; j++) {
+ Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j+1][0];
+ Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j+1][1];
+ }
+ }
+
+ Q = Vtemp[0];
+ free((void *)Vtemp);
+ return Q;
+}
+
+
+/*
+ * B0, B1, B2, B3 :
+ * Bezier multipliers
+ */
+static double B0(double u)
+{
+ double tmp = 1.0 - u;
+ return (tmp * tmp * tmp);
+}
+
+
+static double B1(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * (tmp * tmp));
+}
+
+static double B2(double u)
+{
+ double tmp = 1.0 - u;
+ return (3 * u * u * tmp);
+}
+
+static double B3(double u)
+{
+ return (u * u * u);
+}
+
+
+
+/*
+ * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
+ *Approximate unit tangents at endpoints and "center" of digitized curve
+ */
+static Vector2 ComputeLeftTangent(Vector2 *d, int end)
+// Vector2 *d; /* Digitized points*/
+// int end; /* Index to "left" end of region */
+{
+ Vector2 tHat1;
+ tHat1 = V2SubII(d[end+1], d[end]);
+ tHat1 = *V2Normalize(&tHat1);
+ return tHat1;
+}
+
+static Vector2 ComputeRightTangent(Vector2 *d, int end)
+// Vector2 *d; /* Digitized points */
+// int end; /* Index to "right" end of region */
+{
+ Vector2 tHat2;
+ tHat2 = V2SubII(d[end-1], d[end]);
+ tHat2 = *V2Normalize(&tHat2);
+ return tHat2;
+}
+
+static Vector2 ComputeCenterTangent(Vector2 *d, int center)
+// Vector2 *d; /* Digitized points */
+// int center; /* Index to point inside region */
+{
+ Vector2 V1, V2, tHatCenter;
+
+ V1 = V2SubII(d[center-1], d[center]);
+ V2 = V2SubII(d[center], d[center+1]);
+ tHatCenter[0] = (V1[0] + V2[0])/2.0;
+ tHatCenter[1] = (V1[1] + V2[1])/2.0;
+ tHatCenter = *V2Normalize(&tHatCenter);
+ return tHatCenter;
+}
+
+
+/*
+ * ChordLengthParameterize :
+ * Assign parameter values to digitized points
+ * using relative distances between points.
+ */
+static double *ChordLengthParameterize(Vector2 *d, int first, int last)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+{
+ int i;
+ double *u; /* Parameterization */
+
+ u = (double *)malloc((unsigned)(last-first+1) * sizeof(double));
+
+ u[0] = 0.0;
+ for (i = first+1; i <= last; i++) {
+ u[i-first] = u[i-first-1] +
+ V2DistanceBetween2Points(&d[i], &d[i-1]);
+ }
+
+ for (i = first + 1; i <= last; i++) {
+ u[i-first] = u[i-first] / u[last-first];
+ }
+
+ return(u);
+}
+
+
+
+
+/*
+ * ComputeMaxError :
+ * Find the maximum squared distance of digitized points
+ * to fitted curve.
+*/
+static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
+// Vector2 *d; /* Array of digitized points */
+// int first, last; /* Indices defining region */
+// BezierCurve bezCurve; /* Fitted Bezier curve */
+// double *u; /* Parameterization of points */
+// int *splitPoint; /* Point of maximum error */
+{
+ int i;
+ double maxDist; /* Maximum error */
+ double dist; /* Current error */
+ Vector2 P; /* Point on curve */
+ Vector2 v; /* Vector from point to curve */
+
+ *splitPoint = (last - first + 1)/2;
+ maxDist = 0.0;
+ for (i = first + 1; i < last; i++) {
+ P = BezierII(3, bezCurve, u[i-first]);
+ v = V2SubII(P, d[i]);
+ dist = V2SquaredLength(&v);
+ if (dist >= maxDist) {
+ maxDist = dist;
+ *splitPoint = i;
+ }
+ }
+ return (maxDist);
+}
+static Vector2 V2AddII(Vector2 a, Vector2 b)
+{
+ Vector2 c;
+ c[0] = a[0] + b[0]; c[1] = a[1] + b[1];
+ return (c);
+}
+static Vector2 V2ScaleIII(Vector2 v, double s)
+{
+ Vector2 result;
+ result[0] = v[0] * s; result[1] = v[1] * s;
+ return (result);
+}
+
+static Vector2 V2SubII(Vector2 a, Vector2 b)
+{
+ Vector2 c;
+ c[0] = a[0] - b[0]; c[1] = a[1] - b[1];
+ return (c);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+//------------------------- WRAPPER -----------------------------//
+
+FitCurveWrapper::FitCurveWrapper()
+{
+}
+
+FitCurveWrapper::~FitCurveWrapper()
+{
+ _vertices.clear();
+}
+
+void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve )
+{
+ for(int i=0; i<n+1; ++i)
+ _vertices.push_back(curve[i]);
+}
+
+void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
+{
+ int size = data.size();
+ Vector2 *d = new Vector2[size];
+ for(int i=0; i<size; ++i)
+ {
+ d[i][0] = data[i][0];
+ d[i][1] = data[i][1];
+ }
+
+ FitCurve(d,size,error);
+
+ // copy results
+ for(vector<Vector2>::iterator v=_vertices.begin(), vend=_vertices.end();
+ v!=vend;
+ ++v)
+ {
+ oCurve.push_back(Vec2d(v->x(), v->y())) ;
+ }
+
+}
+
+void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error)
+{
+ Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
+
+ tHat1 = ComputeLeftTangent(d, 0);
+ tHat2 = ComputeRightTangent(d, nPts - 1);
+ FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
+}
+
+void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error)
+{
+ BezierCurve bezCurve; /*Control points of fitted Bezier curve*/
+ double *u; /* Parameter values for point */
+ double *uPrime; /* Improved parameter values */
+ double maxError; /* Maximum fitting error */
+ int splitPoint; /* Point to split point set at */
+ int nPts; /* Number of points in subset */
+ double iterationError; /*Error below which you try iterating */
+ int maxIterations = 4; /* Max times to try iterating */
+ Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
+ int i;
+
+ iterationError = error * error;
+ nPts = last - first + 1;
+
+ /* Use heuristic if region only has two points in it */
+ if (nPts == 2) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
+
+ bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
+ DrawBezierCurve(3, bezCurve);
+ free((void *)bezCurve);
+ return;
+ }
+
+ /* Parameterize points, and attempt to fit curve */
+ u = ChordLengthParameterize(d, first, last);
+ bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
+
+ /* Find max deviation of points to fitted curve */
+ maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+
+
+ /* If error not too large, try some reparameterization */
+ /* and iteration */
+ if (maxError < iterationError) {
+ for (i = 0; i < maxIterations; i++) {
+ uPrime = Reparameterize(d, first, last, u, bezCurve);
+ bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
+ maxError = ComputeMaxError(d, first, last,
+ bezCurve, uPrime, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+ free((void *)u);
+ u = uPrime;
+ }
+ }
+
+ /* Fitting failed -- split at max error point and fit recursively */
+ free((void *)u);
+ free((void *)bezCurve);
+ tHatCenter = ComputeCenterTangent(d, splitPoint);
+ FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
+ V2Negate(&tHatCenter);
+ FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
+
+}
+
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.h b/source/blender/freestyle/intern/geometry/FitCurve.h
new file mode 100755
index 00000000000..ed7cbe34780
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/FitCurve.h
@@ -0,0 +1,101 @@
+//
+// Filename : FitCurve.h
+// Author(s) : Stephane Grabli
+// Purpose : An Algorithm for Automatically Fitting Digitized Curves
+// by Philip J. Schneider
+// from "Graphics Gems", Academic Press, 1990
+// Date of creation : 06/06/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 FITCURVE_H
+# define FITCURVE_H
+
+#include <vector>
+#include "../system/FreestyleConfig.h"
+#include "Geom.h"
+
+using namespace Geometry;
+
+typedef struct Point2Struct { /* 2d point */
+ double coordinates[2];
+ Point2Struct() {coordinates[0]=0;coordinates[1]=0;}
+ inline double operator[](const int i) const
+ {
+ return coordinates[i];
+ }
+ inline double& operator[](const int i)
+ {
+ return coordinates[i];
+ }
+ inline double x() const {return coordinates[0];}
+ inline double y() const {return coordinates[1];}
+ } Point2;
+
+typedef Point2 Vector2;
+
+
+
+class LIB_GEOMETRY_EXPORT FitCurveWrapper
+{
+private:
+ std::vector<Vector2> _vertices;
+
+public:
+ FitCurveWrapper();
+ ~FitCurveWrapper();
+
+ /*! Fits a set of 2D data points to a set of Bezier Curve segments
+ * data
+ * Input data points
+ * oCurve
+ * Control points of the sets of bezier curve segments.
+ * Each segment is made of 4 points (polynomial degree of curve = 3)
+ * error
+ * max error tolerance between resulting curve and input data
+ */
+ void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
+protected:
+ /* Vec2d *d; Array of digitized points */
+ /* int nPts; Number of digitized points */
+ /* double error; User-defined error squared */
+ void FitCurve(Vector2 *d, int nPts, double error);
+
+ /*! Draws a Bezier curve segment
+ * n
+ * degree of curve (=3)
+ * curve
+ * bezier segments control points
+ */
+ void DrawBezierCurve(int n, Vector2 *curve);
+
+ /* Vec2d *d; Array of digitized points */
+ /* int first, last; Indices of first and last pts in region */
+ /* Vec2d tHat1, tHat2; Unit tangent vectors at endpoints */
+ /* double error; User-defined error squared */
+ void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
+
+};
+
+#endif // FITCURVE_H
diff --git a/source/blender/freestyle/intern/geometry/Geom.h b/source/blender/freestyle/intern/geometry/Geom.h
new file mode 100755
index 00000000000..ac94213fe98
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Geom.h
@@ -0,0 +1,78 @@
+//
+// Filename : Geom.h
+// Author(s) : Sylvain Paris
+// Emmanuel Turquin
+// Stephane Grabli
+// Purpose : Vectors and Matrices (useful type definitions)
+// Date of creation : 20/05/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 GEOM_H
+# define GEOM_H
+
+# include "VecMat.h"
+# include "../system/Precision.h"
+
+namespace Geometry {
+
+ typedef VecMat::Vec2<unsigned> Vec2u;
+ typedef VecMat::Vec2<int> Vec2i;
+ typedef VecMat::Vec2<float> Vec2f;
+ typedef VecMat::Vec2<double> Vec2d;
+ typedef VecMat::Vec2<real> Vec2r;
+
+ typedef VecMat::Vec3<unsigned> Vec3u;
+ typedef VecMat::Vec3<int> Vec3i;
+ typedef VecMat::Vec3<float> Vec3f;
+ typedef VecMat::Vec3<double> Vec3d;
+ typedef VecMat::Vec3<real> Vec3r;
+
+ typedef VecMat::HVec3<unsigned> HVec3u;
+ typedef VecMat::HVec3<int> HVec3i;
+ typedef VecMat::HVec3<float> HVec3f;
+ typedef VecMat::HVec3<double> HVec3d;
+ typedef VecMat::HVec3<real> HVec3r;
+
+ typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
+ typedef VecMat::SquareMatrix<int, 2> Matrix22i;
+ typedef VecMat::SquareMatrix<float, 2> Matrix22f;
+ typedef VecMat::SquareMatrix<double, 2> Matrix22d;
+ typedef VecMat::SquareMatrix<real, 2> Matrix22r;
+
+ typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
+ typedef VecMat::SquareMatrix<int, 3> Matrix33i;
+ typedef VecMat::SquareMatrix<float, 3> Matrix33f;
+ typedef VecMat::SquareMatrix<double, 3> Matrix33d;
+ typedef VecMat::SquareMatrix<real, 3> Matrix33r;
+
+ typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
+ typedef VecMat::SquareMatrix<int, 4> Matrix44i;
+ typedef VecMat::SquareMatrix<float, 4> Matrix44f;
+ typedef VecMat::SquareMatrix<double, 4> Matrix44d;
+ typedef VecMat::SquareMatrix<real, 4> Matrix44r;
+
+} // end of namespace Geometry
+
+#endif // GEOM_H
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
new file mode 100755
index 00000000000..c148c521a46
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -0,0 +1,240 @@
+
+//
+// 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//#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 <stdio.h>
+#include <list>
+#include <map>
+#include "../system/TimeUtils.h"
+#include "GeomCleaner.h"
+
+using namespace std;
+
+
+void GeomCleaner::SortIndexedVertexArray( const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices,
+ unsigned **oIndices)
+{
+ // First, we build a list of IndexVertex:
+ list<IndexedVertex> indexedVertices;
+ unsigned i;
+ for(i=0; i<iVSize; i+= 3)
+ {
+ indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]), i/3));
+ }
+
+ // q-sort
+ indexedVertices.sort();
+
+ // build the indices mapping array:
+ unsigned *mapIndices = new unsigned[iVSize/3];
+ *oVertices = new real[iVSize];
+ list<IndexedVertex>::iterator iv;
+ unsigned newIndex = 0;
+ unsigned vIndex = 0;
+ for(iv=indexedVertices.begin(); iv!=indexedVertices.end(); iv++)
+ {
+ // Build the final results:
+ (*oVertices)[vIndex] = iv->x();
+ (*oVertices)[vIndex+1] = iv->y();
+ (*oVertices)[vIndex+2] = iv->z();
+
+ mapIndices[iv->index()] = newIndex;
+ newIndex++;
+ vIndex+=3;
+ }
+
+
+ // Build the final index array:
+ *oIndices = new unsigned[iISize];
+ for(i=0; i<iISize; i++)
+ {
+ (*oIndices)[i] = 3*mapIndices[iIndices[i]/3];
+ }
+
+ delete [] mapIndices;
+}
+
+void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+ // First, we build a list of IndexVertex:
+ vector<Vec3r> vertices;
+ unsigned i;
+ for(i=0; i<iVSize; i+= 3)
+ {
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
+ }
+
+ unsigned *mapVertex = new unsigned[iVSize];
+ vector<Vec3r>::iterator v = vertices.begin();
+
+ vector<Vec3r> compressedVertices;
+ Vec3r previous = *v;
+ mapVertex[0] = 0;
+ compressedVertices.push_back(vertices.front());
+
+ v++;
+ Vec3r current;
+ i=1;
+ for(; v!=vertices.end(); v++)
+ {
+ current = *v;
+ if(current == previous)
+ mapVertex[i] = compressedVertices.size()-1;
+ else
+ {
+ compressedVertices.push_back(current);
+ mapVertex[i] = compressedVertices.size()-1;
+ }
+ previous = current;
+ i++;
+ }
+
+ // Builds the resulting vertex array:
+ *oVSize = 3*compressedVertices.size();
+ *oVertices = new real [*oVSize];
+ i=0;
+ for(v=compressedVertices.begin(); v!=compressedVertices.end(); v++)
+ {
+ (*oVertices)[i] = (*v)[0];
+ (*oVertices)[i+1] = (*v)[1];
+ (*oVertices)[i+2] = (*v)[2];
+ i += 3;
+ }
+
+ // Map the index array:
+ *oIndices = new unsigned[iISize];
+ for(i=0; i<iISize; i++)
+ {
+ (*oIndices)[i] = 3*mapVertex[iIndices[i]/3];
+ }
+
+ delete [] mapVertex;
+}
+
+void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+
+ // tmp arrays used to store the sorted data:
+ real *tmpVertices;
+ unsigned *tmpIndices;
+
+ Chronometer chrono;
+ // Sort data
+ chrono.start();
+ GeomCleaner::SortIndexedVertexArray(iVertices, iVSize,
+ iIndices, iISize,
+ &tmpVertices, &tmpIndices
+ );
+ printf("Sorting: %lf\n", chrono.stop());
+
+ // compress data
+ chrono.start();
+ GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize,
+ tmpIndices, iISize,
+ oVertices, oVSize,
+ oIndices);
+ printf("Merging: %lf\n", chrono.stop());
+
+ // deallocates memory:
+ delete [] tmpVertices;
+ delete [] tmpIndices;
+}
+
+/*! Defines a hash table used for searching the Cells */
+struct GeomCleanerHasher{
+#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;
+ }
+};
+
+void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices)
+{
+ typedef map<Vec3r, unsigned> cleanHashTable;
+ vector<Vec3r> vertices;
+ unsigned i;
+ for(i=0; i<iVSize; i+= 3)
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
+
+ cleanHashTable ht;
+ vector<unsigned> newIndices;
+ vector<Vec3r> newVertices;
+
+ // elimination of needless points
+ unsigned currentIndex = 0;
+ vector<Vec3r>::const_iterator v = vertices.begin();
+ vector<Vec3r>::const_iterator end = vertices.end();
+ cleanHashTable::const_iterator found;
+ for(; v!=end; v++)
+ {
+ found = ht.find(*v);
+ if(found != ht.end())
+ {
+ // The vertex is already in the new array.
+ newIndices.push_back((*found).second);
+ }
+ else
+ {
+ newVertices.push_back(*v);
+ newIndices.push_back(currentIndex);
+ ht[*v] = currentIndex;
+ currentIndex++;
+ }
+ }
+
+ // creation of oVertices array:
+ *oVSize = 3*newVertices.size();
+ *oVertices = new real[*oVSize];
+ currentIndex = 0;
+ end = newVertices.end();
+ for(v=newVertices.begin(); v!=end ; v++)
+ {
+ (*oVertices)[currentIndex++] = (*v)[0];
+ (*oVertices)[currentIndex++] = (*v)[1];
+ (*oVertices)[currentIndex++] = (*v)[2];
+ }
+
+ // map new indices:
+ *oIndices = new unsigned[iISize];
+ for(i=0; i<iISize; i++)
+ (*oIndices)[i] = 3*newIndices[iIndices[i]/3];
+}
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h
new file mode 100755
index 00000000000..5fdfda0162a
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h
@@ -0,0 +1,219 @@
+//
+// Filename : GeomCleaner.h
+// Author : Stephane Grabli
+// Purpose : Class to define a cleaner of geometry providing
+// a set of useful tools
+// Date of creation : 04/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 GEOMCLEANER_H
+# define GEOMCLEANER_H
+
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+
+using namespace Geometry;
+
+class LIB_GEOMETRY_EXPORT GeomCleaner
+{
+public:
+
+ inline GeomCleaner() {}
+ inline ~GeomCleaner() {}
+
+ /*! Sorts an array of Indexed vertices
+ * iVertices
+ * Array of vertices to sort. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * Output of sorted vertices. A vertex v1 precedes another one
+ * v2 in this array if v1.x<v2.x, or v1.x=v2.x && v1.y < v2.y
+ * or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oIndices
+ * Output corresponding to the iIndices array but
+ * reorganized in order to match the sorted vertex array.
+ */
+
+ static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices,
+ unsigned **oIndices);
+
+ /*! Compress a SORTED indexed vertex array by eliminating
+ * multiple appearing occurences of a single vertex.
+ * iVertices
+ * The SORTED vertex array to compress. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the compression.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the compressed
+ * oVertices array.
+ */
+
+ static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+
+ /*! Sorts and compress an array of indexed vertices.
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the sorted and compressed
+ * oVertices array.
+ */
+
+ static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+
+ /*! Cleans an indexed vertex array. (Identical to
+ * SortAndCompress except that we use here a hash
+ * table to create the new array.)
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a
+ * float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer
+ * to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving
+ * the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the sorted and compressed
+ * oVertices array.
+ */
+
+ static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
+ const unsigned *iIndices, unsigned iISize,
+ real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+};
+
+
+/*! Binary operators */
+//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+
+/*! Class Indexed Vertex. Used to represent
+ * an indexed vertex by storing the vertex
+ * coordinates as well as its index
+ */
+class IndexedVertex
+{
+public:
+
+private:
+ Vec3r _Vector;
+ unsigned _index;
+public:
+ inline IndexedVertex() {}
+ inline IndexedVertex(Vec3r iVector, unsigned iIndex)
+ {
+ _Vector = iVector;
+ _index = iIndex;
+ }
+ /*! accessors */
+ inline const Vec3r& vector() const {return _Vector;}
+ inline unsigned index() {return _index;}
+ inline real x() {return _Vector[0];}
+ inline real y() {return _Vector[1];}
+ inline real z() {return _Vector[2];}
+
+ /*! modifiers */
+ inline void setVector(const Vec3r& iVector) {_Vector = iVector;}
+ inline void setIndex(unsigned iIndex) {_index = iIndex;}
+
+ /*! operators */
+ IndexedVertex& operator=(const IndexedVertex& iv)
+ {
+ _Vector = iv._Vector;
+ _index = iv._index;
+ return *this;
+ }
+ inline real operator[](const unsigned i) {return _Vector[i];}
+ //friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+ inline bool operator<(const IndexedVertex& v) const
+ {
+ return (_Vector < v._Vector);
+ }
+ inline bool operator==(const IndexedVertex& v)
+ {
+ return (_Vector == v._Vector);
+ }
+};
+
+//bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
+//{
+// return iv1.operator<(iv2);
+//}
+
+#endif // GEOMCLEANER_H
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
new file mode 100755
index 00000000000..2169bce0364
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -0,0 +1,753 @@
+
+//
+// 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 "GeomUtils.h"
+
+namespace GeomUtils {
+
+ // This internal procedure is defined below.
+ bool intersect2dSegPoly(Vec2r* seg,
+ Vec2r* poly,
+ unsigned n);
+
+ bool intersect2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B) {
+ Vec2r seg[2];
+ seg[0] = A;
+ seg[1] = B;
+
+ Vec2r poly[5];
+ poly[0][0] = min[0];
+ poly[0][1] = min[1];
+ poly[1][0] = max[0];
+ poly[1][1] = min[1];
+ poly[2][0] = max[0];
+ poly[2][1] = max[1];
+ poly[3][0] = min[0];
+ poly[3][1] = max[1];
+ poly[4][0] = min[0];
+ poly[4][1] = min[1];
+
+ return intersect2dSegPoly(seg, poly, 4);
+ }
+
+ bool include2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B) {
+ if((((max[0] > A[0])&&(A[0] > min[0]))&&((max[0] > B[0])&&(B[0] > min[0])))
+ && (((max[1] > A[1])&&(A[1] > min[1]))&&((max[1] > B[1])&&(B[1] > min[1]))))
+ return true;
+ return false;
+ }
+
+ intersection_test intersect2dSeg2dSeg(const Vec2r& p1,
+ const Vec2r& p2,
+ const Vec2r& p3,
+ const Vec2r& p4,
+ Vec2r& res) {
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2
+ // is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on
+ // same side of line 1, the line segments do not intersect.
+ if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie
+ // on same side of second line segment, the line segments do
+ // not intersect.
+ if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+ }
+
+ intersection_test intersect2dLine2dLine(const Vec2r& p1,
+ const Vec2r& p2,
+ const Vec2r& p3,
+ const Vec2r& p4,
+ Vec2r& res) {
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2
+ // is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+ }
+
+ intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1,
+ const Vec2r& p2,
+ const Vec2r& p3,
+ const Vec2r& p4,
+ real& t,
+ real& u,
+ real epsilon) {
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2
+ // is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on
+ // same side of line 1, the line segments do not intersect.
+ if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie
+ // on same side of second line segment, the line segments do
+ // not intersect.
+ if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < epsilon)
+ return (COLINEAR);
+
+ real d1, d2, e1;
+
+ d1 = p1[1] - p3[1];
+ d2 = p2[1] - p1[1];
+ e1 = p1[0] - p3[0];
+
+ num = -b2 * d1 - a2 * e1;
+ t = num / denom;
+
+ num = -b1 * d1 - a1 * e1;
+ u = num / denom;
+
+ return (DO_INTERSECT);
+ }
+
+ // AABB-triangle overlap test code
+ // by Tomas Akenine-Möller
+ // Function: int triBoxOverlap(real boxcenter[3],
+ // real boxhalfsize[3],real triverts[3][3]);
+ // History:
+ // 2001-03-05: released the code in its first version
+ // 2001-06-18: changed the order of the tests, faster
+ //
+ // Acknowledgement: Many thanks to Pierre Terdiman for
+ // suggestions and discussions on how to optimize code.
+ // Thanks to David Hunt for finding a ">="-bug!
+
+#define X 0
+#define Y 1
+#define Z 2
+
+#define FINDMINMAX(x0, x1, x2, min, max) \
+ min = max = x0; \
+ if(x1<min) min=x1; \
+ if(x1>max) max=x1; \
+ if(x2<min) min=x2; \
+ if(x2>max) max=x2;
+
+ //======================== X-tests ========================//
+#define AXISTEST_X01(a, b, fa, fb) \
+ p0 = a*v0[Y] - b*v0[Z]; \
+ p2 = a*v2[Y] - b*v2[Z]; \
+ if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+#define AXISTEST_X2(a, b, fa, fb) \
+ p0 = a*v0[Y] - b*v0[Z]; \
+ p1 = a*v1[Y] - b*v1[Z]; \
+ if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+ //======================== Y-tests ========================//
+#define AXISTEST_Y02(a, b, fa, fb) \
+ p0 = -a*v0[X] + b*v0[Z]; \
+ p2 = -a*v2[X] + b*v2[Z]; \
+ if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+#define AXISTEST_Y1(a, b, fa, fb) \
+ p0 = -a*v0[X] + b*v0[Z]; \
+ p1 = -a*v1[X] + b*v1[Z]; \
+ if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if(min>rad || max<-rad) return 0;
+
+ //======================== Z-tests ========================//
+#define AXISTEST_Z12(a, b, fa, fb) \
+ p1 = a*v1[X] - b*v1[Y]; \
+ p2 = a*v2[X] - b*v2[Y]; \
+ if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if(min>rad || max<-rad) return 0;
+
+#define AXISTEST_Z0(a, b, fa, fb) \
+ p0 = a*v0[X] - b*v0[Y]; \
+ p1 = a*v1[X] - b*v1[Y]; \
+ if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if(min>rad || max<-rad) return 0;
+
+ // This internal procedure is defined below.
+ bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox);
+
+ // Use separating axis theorem to test overlap between triangle and box
+ // need to test for overlap in these directions:
+ // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
+ // we do not even need to test these)
+ // 2) normal of the triangle
+ // 3) crossproduct(edge from tri, {x,y,z}-directin)
+ // this gives 3x3=9 more tests
+ bool overlapTriangleBox(Vec3r& boxcenter,
+ Vec3r& boxhalfsize,
+ Vec3r triverts[3]) {
+ Vec3r v0, v1, v2, normal, e0, e1, e2;
+ real min, max, d, p0, p1, p2, rad, fex, fey, fez;
+
+ // This is the fastest branch on Sun
+ // move everything so that the boxcenter is in (0, 0, 0)
+ v0 = triverts[0] - boxcenter;
+ v1 = triverts[1] - boxcenter;
+ v2 = triverts[2] - boxcenter;
+
+ // compute triangle edges
+ e0 = v1 - v0;
+ e1 = v2 - v1;
+ e2 = v0 - v2;
+
+ // Bullet 3:
+ // Do the 9 tests first (this was faster)
+ fex = fabs(e0[X]);
+ fey = fabs(e0[Y]);
+ fez = fabs(e0[Z]);
+ AXISTEST_X01(e0[Z], e0[Y], fez, fey);
+ AXISTEST_Y02(e0[Z], e0[X], fez, fex);
+ AXISTEST_Z12(e0[Y], e0[X], fey, fex);
+
+ fex = fabs(e1[X]);
+ fey = fabs(e1[Y]);
+ fez = fabs(e1[Z]);
+ AXISTEST_X01(e1[Z], e1[Y], fez, fey);
+ AXISTEST_Y02(e1[Z], e1[X], fez, fex);
+ AXISTEST_Z0(e1[Y], e1[X], fey, fex);
+
+ fex = fabs(e2[X]);
+ fey = fabs(e2[Y]);
+ fez = fabs(e2[Z]);
+ AXISTEST_X2(e2[Z], e2[Y], fez, fey);
+ AXISTEST_Y1(e2[Z], e2[X], fez, fex);
+ AXISTEST_Z12(e2[Y], e2[X], fey, fex);
+
+ // Bullet 1:
+ // first test overlap in the {x,y,z}-directions
+ // find min, max of the triangle each direction, and test for overlap in
+ // that direction -- this is equivalent to testing a minimal AABB around
+ // the triangle against the AABB
+
+ // test in X-direction
+ FINDMINMAX(v0[X], v1[X], v2[X], min, max);
+ if (min > boxhalfsize[X] || max < -boxhalfsize[X])
+ return false;
+
+ // test in Y-direction
+ FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
+ if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
+ return false;
+
+ // test in Z-direction
+ FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
+ if(min > boxhalfsize[Z] || max < -boxhalfsize[Z])
+ return false;
+
+ // Bullet 2:
+ // test if the box intersects the plane of the triangle
+ // compute plane equation of triangle: normal * x + d = 0
+ normal = e0 ^ e1;
+ d = -(normal * v0); // plane eq: normal.x + d = 0
+ if (!overlapPlaneBox(normal, d, boxhalfsize))
+ return false;
+
+ return true; // box and triangle overlaps
+ }
+
+ // Fast, Minimum Storage Ray-Triangle Intersection
+ //
+ // Tomas Möller
+ // Prosolvia Clarus AB
+ // Sweden
+ // tompa@clarus.se
+ //
+ // Ben Trumbore
+ // Cornell University
+ // Ithaca, New York
+ // wbt@graphics.cornell.edu
+
+ bool intersectRayTriangle(Vec3r& orig, Vec3r& dir,
+ Vec3r& v0, Vec3r& v1, Vec3r& v2,
+ real& t, real& u, real& v, real epsilon) {
+ Vec3r edge1, edge2, tvec, pvec, qvec;
+ real det, inv_det;
+
+ // find vectors for two edges sharing v0
+ edge1 = v1 - v0;
+ edge2 = v2 - v0;
+
+ // begin calculating determinant - also used to calculate U parameter
+ pvec = dir ^ edge2;
+
+ // if determinant is near zero, ray lies in plane of triangle
+ det = edge1 * pvec;
+
+ // calculate distance from v0 to ray origin
+ tvec = orig - v0;
+ inv_det = 1.0 / det;
+
+ qvec = tvec ^ edge1;
+
+ if (det > epsilon) {
+ u = tvec * pvec;
+ if (u < 0.0 || u > det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v < 0.0 || u + v > det)
+ return false;
+ }
+ else if(det < -epsilon) {
+ // calculate U parameter and test bounds
+ u = tvec * pvec;
+ if (u > 0.0 || u < det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v > 0.0 || u + v < det)
+ return false;
+ }
+ else
+ return false; // ray is parallell to the plane of the triangle
+
+ u *= inv_det;
+ v *= inv_det;
+ t = (edge2 * qvec) * inv_det;
+
+ return true;
+ }
+
+ // Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
+ intersection_test intersectRayPlane(Vec3r& orig, Vec3r& dir,
+ Vec3r& norm, real d,
+ real& t,
+ real epsilon) {
+ real denom = norm * dir;
+
+ if(fabs(denom) <= epsilon) { // plane and ray are parallel
+ if(fabs((norm * orig) + d) <= epsilon)
+ return COINCIDENT; // plane and ray are coincident
+ else
+ return COLINEAR;
+ }
+
+ t = -(d + (norm * orig)) / denom;
+
+ if (t < 0.0f)
+ return DONT_INTERSECT;
+
+ return DO_INTERSECT;
+ }
+
+ bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ real t0, real t1,
+ real& tmin, real& tmax, // I0=orig+tmin*dir is the first intersection, I1=orig+tmax*dir is the second intersection
+ real epsilon){
+
+ float tymin, tymax, tzmin, tzmax;
+ Vec3r inv_direction(1.0/dir[0], 1.0/dir[1], 1.0/dir[2]);
+ int sign[3];
+ sign[0] = (inv_direction.x() < 0);
+ sign[1] = (inv_direction.y() < 0);
+ sign[2] = (inv_direction.z() < 0);
+
+ Vec3r bounds[2];
+ bounds[0] = boxMin;
+ bounds[1] = boxMax;
+
+ tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
+ tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x();
+ tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
+ tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y();
+ if ( (tmin > tymax) || (tymin > tmax) )
+ return false;
+ if (tymin > tmin)
+ tmin = tymin;
+ if (tymax < tmax)
+ tmax = tymax;
+ tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
+ tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z();
+ if ( (tmin > tzmax) || (tzmin > tmax) )
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ( (tmin < t1) && (tmax > t0) );
+ }
+
+ // Checks whether 3D points p lies inside or outside of the triangle ABC
+ bool includePointTriangle(Vec3r& P,
+ Vec3r& A,
+ Vec3r& B,
+ Vec3r& C) {
+ Vec3r AB(B - A);
+ Vec3r BC(C - B);
+ Vec3r CA(A - C);
+ Vec3r AP(P - A);
+ Vec3r BP(P - B);
+ Vec3r CP(P - C);
+
+ Vec3r N(AB ^ BC); // triangle's normal
+
+ N.normalize();
+
+ Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
+ J.normalize();
+ K.normalize();
+ L.normalize();
+
+ if(J * N < 0)
+ return false; // on the right of AB
+
+ if(K * N < 0)
+ return false; // on the right of BC
+
+ if(L * N < 0)
+ return false; // on the right of CA
+
+ return true;
+ }
+
+ void transformVertex(const Vec3r& vert,
+ const Matrix44r& matrix,
+ Vec3r& res) {
+ HVec3r hvert(vert), res_tmp;
+ real scale;
+ for (unsigned j = 0; j < 4; j++) {
+ scale = hvert[j];
+ for (unsigned i = 0; i < 4; i++)
+ res_tmp[i] += matrix(i, j) * scale;
+ }
+
+ res[0] = res_tmp.x();
+ res[1] = res_tmp.y();
+ res[2] = res_tmp.z();
+ }
+
+ void transformVertices(const vector<Vec3r>& vertices,
+ const Matrix44r& trans,
+ vector<Vec3r>& res) {
+ for (vector<Vec3r>::const_iterator v = vertices.begin();
+ v != vertices.end();
+ v++) {
+ Vec3r *res_tmp = new Vec3r;
+ transformVertex(*v, trans, *res_tmp);
+ res.push_back(*res_tmp);
+ }
+ }
+
+ Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) {
+ Vec3r res;
+ for (unsigned i = 0; i < 3; i++) {
+ res[i] = 0;
+ for (unsigned j = 0; j < 3; j++)
+ res[i] += mat(i, j) * v[j];
+ }
+ res.normalize();
+ return res;
+ }
+
+ // This internal procedure is defined below.
+ void fromCoordAToCoordB(const Vec3r& p,
+ Vec3r& q,
+ const real transform[4][4]);
+
+ void fromWorldToCamera(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]) {
+ fromCoordAToCoordB(p, q, model_view_matrix);
+ }
+
+ void fromCameraToRetina(const Vec3r& p,
+ Vec3r& q,
+ const real projection_matrix[4][4]) {
+ fromCoordAToCoordB(p, q, projection_matrix);
+ }
+
+ void fromRetinaToImage(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]) {
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
+
+ // winY:
+ q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
+
+ // winZ:
+ q[2] = (p[2] + 1.0) / 2.0;
+ }
+
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4],
+ const real projection_matrix[4][4],
+ const int viewport[4]) {
+ Vec3r p1, p2;
+ fromWorldToCamera(p, p1, model_view_matrix);
+ fromCameraToRetina(p1, p2, projection_matrix);
+ fromRetinaToImage(p2, q, viewport);
+ q[2] = p1[2];
+ }
+
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real transform[4][4],
+ const int viewport[4]) {
+ fromCoordAToCoordB(p, q, transform);
+
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
+
+ //winY:
+ q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
+ }
+
+ void fromImageToRetina(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]) {
+ q = p;
+ q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1;
+ q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1;
+ }
+
+ void fromRetinaToCamera(const Vec3r& p,
+ Vec3r& q,
+ real focal,
+ const real projection_matrix[4][4]) {
+
+ if( projection_matrix[3][3] == 0.0 ) // perspective
+ {
+ q[0] = (-p[0] * focal) / projection_matrix[0][0];
+ q[1] = (-p[1] * focal) / projection_matrix[1][1];
+ q[2] = focal;
+ }
+ else // orthogonal
+ {
+ q[0] = p[0] / projection_matrix[0][0];
+ q[1] = p[1] / projection_matrix[1][1];
+ q[2] = focal;
+ }
+ }
+
+ void fromCameraToWorld(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]) {
+
+ real translation[3] = { model_view_matrix[0][3],
+ model_view_matrix[1][3],
+ model_view_matrix[2][3] };
+ for (unsigned i = 0; i < 3; i++) {
+ q[i] = 0.0;
+ for (unsigned short j = 0; j < 3; j++)
+ q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
+ }
+ }
+
+
+ //
+ // Internal code
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Copyright 2001, softSurfer (www.softsurfer.com)
+ // This code may be freely used and modified for any purpose
+ // providing that this copyright notice is included with it.
+ // SoftSurfer makes no warranty for this code, and cannot be held
+ // liable for any real or imagined damage resulting from its use.
+ // Users of this code must verify correctness for their application.
+
+#define perp(u,v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
+
+ inline bool intersect2dSegPoly(Vec2r* seg,
+ Vec2r* poly,
+ unsigned n) {
+ if (seg[0] == seg[1])
+ return false;
+
+ real tE = 0; // the maximum entering segment parameter
+ real tL = 1; // the minimum leaving segment parameter
+ real t, N, D; // intersect parameter t = N / D
+ Vec2r dseg; // the segment direction vector
+ dseg = seg[1] - seg[0];
+ Vec2r e; // edge vector
+
+ for (unsigned i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
+ e = poly[i+1] - poly[i];
+ N = perp(e, seg[0] - poly[i]);
+ D = -perp(e, dseg);
+ if (fabs(D) < M_EPSILON) {
+ if (N < 0)
+ return false;
+ else
+ continue;
+ }
+
+ t = N / D;
+ if (D < 0) { // segment seg is entering across this edge
+ if (t > tE) { // new max tE
+ tE = t;
+ if (tE > tL) // seg enters after leaving polygon
+ return false;
+ }
+ }
+ else { // segment seg is leaving across this edge
+ if (t < tL) { // new min tL
+ tL = t;
+ if (tL < tE) // seg leaves before entering polygon
+ return false;
+ }
+ }
+ }
+
+ // tE <= tL implies that there is a valid intersection subsegment
+ return true;
+ }
+
+ inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox) {
+ Vec3r vmin, vmax;
+
+ for(unsigned q = X; q <= Z; q++) {
+ if(normal[q] > 0.0f) {
+ vmin[q] = -maxbox[q];
+ vmax[q] = maxbox[q];
+ }
+ else {
+ vmin[q] = maxbox[q];
+ vmax[q] = -maxbox[q];
+ }
+ }
+ if((normal * vmin) + d > 0.0f)
+ return false;
+ if((normal * vmax) + d >= 0.0f)
+ return true;
+ return false;
+ }
+
+ inline void fromCoordAToCoordB(const Vec3r&p,
+ Vec3r& q,
+ const real transform[4][4]) {
+ HVec3r hp(p);
+ HVec3r hq(0, 0, 0, 0);
+
+ for (unsigned i = 0; i < 4; i++)
+ for (unsigned j = 0; j < 4; j++)
+ hq[i] += transform[i][j] * hp[j];
+
+ if(hq[3] == 0) {
+ q = p;
+ return;
+ }
+
+ for (unsigned k = 0; k < 3; k++)
+ q[k] = hq[k] / hq[3];
+ }
+
+} // end of namespace GeomUtils
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
new file mode 100755
index 00000000000..787376108e1
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -0,0 +1,310 @@
+//
+// Filename : GeomUtils.h
+// Author(s) : Stephane Grabli
+// Purpose : Various tools for geometry
+// Date of creation : 12/04/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 GEOMUTILS_H
+# define GEOMUTILS_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+
+using namespace std;
+using namespace Geometry;
+
+namespace GeomUtils {
+
+ //
+ // Templated procedures
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ /*! Computes the distance from a point P to a segment AB */
+ template<class T>
+ real distPointSegment( const T& P, const T& A , const T& B) {
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
+
+ real c1(AB * AP);
+ if (c1 <= 0)
+ return AP.norm();
+
+ real c2(AB * AB);
+ if (c2 <= c1)
+ return BP.norm();
+
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
+
+ return PPb.norm();
+ }
+
+ //
+ // Non-templated procedures
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ typedef enum {
+ DONT_INTERSECT,
+ DO_INTERSECT,
+ COLINEAR,
+ COINCIDENT
+ } intersection_test;
+
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ real& t, // I = P1 + t * P1P2)
+ real& u, // I = P3 + u * P3P4
+ real epsilon = M_EPSILON);
+
+ /*! check whether a 2D segment intersect a 2D region or not */
+ LIB_GEOMETRY_EXPORT
+ bool intersect2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B);
+
+ /*! check whether a 2D segment is included in a 2D region or not */
+ LIB_GEOMETRY_EXPORT
+ bool include2dSeg2dArea(const Vec2r& min,
+ const Vec2r& max,
+ const Vec2r& A,
+ const Vec2r& B);
+
+ /*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
+ LIB_GEOMETRY_EXPORT
+ bool overlapTriangleBox(Vec3r& boxcenter,
+ Vec3r& boxhalfsize,
+ Vec3r triverts[3]);
+
+ /*! Fast, Minimum Storage Ray-Triangle Intersection,
+ * adapted from Tomas Möller and Ben Trumbore code.
+ */
+ LIB_GEOMETRY_EXPORT
+ bool intersectRayTriangle(Vec3r& orig, Vec3r& dir,
+ Vec3r& v0, Vec3r& v1, Vec3r& v2,
+ real& t, // I = orig + t * dir
+ real& u, real& v, // I = (1-u-v)*v0+u*v1+v*v2
+ real epsilon = M_EPSILON); // the epsilon to use
+
+ /*! Intersection between plane and ray
+ * adapted from Graphics Gems, Didier Badouel
+ */
+ LIB_GEOMETRY_EXPORT
+ intersection_test intersectRayPlane(Vec3r& orig, Vec3r& dir, // ray origin and direction
+ Vec3r& norm, real d, // plane's normal and offset (plane = { P / P.N + d = 0 })
+ real& t, // I = orig + t * dir
+ real epsilon = M_EPSILON); // the epsilon to use
+
+ /*! Intersection Ray-Bounding box (axis aligned).
+ * Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm",
+ * JGT 10:1 (2005), pp. 49-54.
+ * Returns
+ */
+ LIB_GEOMETRY_EXPORT
+ bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ real t0, real t1, // the interval in which at least on of the intersections must happen
+ real& tmin, real& tmax, // Imin=orig+tmin*dir is the first intersection, Imax=orig+tmax*dir is the second intersection
+ real epsilon = M_EPSILON); // the epsilon to use
+
+
+ /*! Checks whether 3D point P lies inside or outside of the triangle ABC */
+ LIB_GEOMETRY_EXPORT
+ bool includePointTriangle(Vec3r& P,
+ Vec3r& A,
+ Vec3r& B,
+ Vec3r& C);
+
+ LIB_GEOMETRY_EXPORT
+ void transformVertex(const Vec3r& vert,
+ const Matrix44r& matrix,
+ Vec3r& res);
+
+ LIB_GEOMETRY_EXPORT
+ void transformVertices(const vector<Vec3r>& vertices,
+ const Matrix44r& trans,
+ vector<Vec3r>& res);
+
+ LIB_GEOMETRY_EXPORT
+ Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
+
+ //
+ // Coordinates systems changing procedures
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ /*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4],
+ const real projection_matrix[4][4],
+ const int viewport[4]);
+
+ /*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * transform
+ * The transformation matrix (gathering model view and projection),
+ * expressed in line major order (OpenGL matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromWorldToImage(const Vec3r& p,
+ Vec3r& q,
+ const real transform[4][4],
+ const int viewport[4]);
+
+ /*! Projects from world coordinates to camera coordinates
+ * Returns the point's coordinates expressed in the camera's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromWorldToCamera(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]);
+
+ /*! Projects from World Coordinates to retina coordinates
+ * Returns the point's coordinates expressed in Retina system.
+ * p
+ * point's coordinates expressed in camera system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromCameraToRetina(const Vec3r& p,
+ Vec3r& q,
+ const real projection_matrix[4][4]);
+
+ /*! From retina to image.
+ * Returns the coordinates expressed in Image coorinates system.
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromRetinaToImage(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]);
+
+ /*! From image to retina
+ * p
+ * point's coordinates expressed in image system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromImageToRetina(const Vec3r& p,
+ Vec3r& q,
+ const int viewport[4]);
+
+ /*! computes the coordinates of q in the camera coordinates system,
+ * using the known z coordinates of the 3D point.
+ * That means that this method does not inverse any matrices,
+ * it only computes X and Y from x,y and Z)
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromRetinaToCamera(const Vec3r& p,
+ Vec3r& q,
+ real z,
+ const real projection_matrix[4][4]);
+
+ /*! Projects from camera coordinates to world coordinates
+ * Returns the point's coordinates expressed in the world's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in the camera coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+ LIB_GEOMETRY_EXPORT
+ void fromCameraToWorld(const Vec3r& p,
+ Vec3r& q,
+ const real model_view_matrix[4][4]);
+
+} // end of namespace GeomUtils
+
+#endif // GEOMUTILS_H
diff --git a/source/blender/freestyle/intern/geometry/Grid.cpp b/source/blender/freestyle/intern/geometry/Grid.cpp
new file mode 100755
index 00000000000..2477227c410
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Grid.cpp
@@ -0,0 +1,388 @@
+
+//
+// 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 "Grid.h"
+#include "BBox.h"
+#include <cassert>
+#include <stdexcept>
+
+// Grid Visitors
+/////////////////
+void allOccludersGridVisitor::examineOccluder(Polygon3r *occ){
+ occluders_.push_back(occ);
+}
+
+bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){
+ if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x()))
+ && ((inter.y()>=box_min.y()) && (inter.y() <box_max.y()))
+ && ((inter.z()>=box_min.z()) && (inter.z() <box_max.z()))
+ ){
+ return true;
+ }
+ return false;
+}
+void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ){
+
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ Vec3r v1(((occ)->getVertices())[0]);
+ Vec3d normal((occ)->getNormal());
+ //soc unused - double d = -(v1 * normal);
+
+ double tmp_u, tmp_v, tmp_t;
+ if((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)){
+ if (fabs(ray_dir_ * normal) > 0.0001){
+ // Check whether the intersection is in the cell:
+ if(inBox(ray_org_+tmp_t*ray_dir_/ray_dir_.norm(), current_cell_->getOrigin(), current_cell_->getOrigin()+cell_size_)){
+
+ //Vec3d bboxdiag(_scene3d->bbox().getMax()-_scene3d->bbox().getMin());
+ //if ((t>1.0E-06*(min(min(bboxdiag.x(),bboxdiag.y()),bboxdiag.z()))) && (t<raylength)){
+ if(tmp_t < t_){
+ occluder_ = occ;
+ u_ = tmp_u;
+ v_ = tmp_v;
+ t_ = tmp_t;
+ }
+ }else{
+ occ->userdata2 = 0;
+ }
+ }
+ }
+}
+
+bool firstIntersectionGridVisitor::stop(){
+ if(occluder_)
+ return true;
+ return false;
+}
+
+// Grid
+/////////////////
+
+void Grid::clear() {
+ if (_occluders.size() != 0) {
+ for(OccludersSet::iterator it = _occluders.begin();
+ it != _occluders.end();
+ it++) {
+ delete (*it);
+ }
+ _occluders.clear();
+ }
+
+ _size = Vec3r(0, 0, 0);
+ _cell_size = Vec3r(0, 0, 0);
+ _orig = Vec3r(0, 0, 0);
+ _cells_nb = Vec3u(0, 0, 0);
+ //_ray_occluders.clear();
+}
+
+void Grid::configure(const Vec3r& orig,
+ const Vec3r& size,
+ unsigned nb) {
+
+ _orig = orig;
+ Vec3r tmpSize=size;
+ // Compute the volume of the desired grid
+ real grid_vol = size[0] * size[1] * size[2];
+
+ if(grid_vol == 0){
+ double min=DBL_MAX;
+ int index=0;
+ int nzeros=0;
+ for(int i=0;i<3;++i){
+ if(size[i] == 0){
+ ++nzeros;
+ index=i;
+ }
+ if((size[i]!=0) && (min>size[i])){
+ min=size[i];
+ }
+ }
+ if(nzeros>1){
+ throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
+ }
+ tmpSize[index]=min;
+ _orig[index] = _orig[index]-min/2;
+ }
+ // Compute the desired volume of a single cell
+ real cell_vol = grid_vol / nb;
+ // The edge of such a cubic cell is cubic root of cellVolume
+ real edge = pow(cell_vol, 1.0 / 3.0);
+
+ // We compute the number of cells par edge
+ // such as we cover at least the whole box.
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ _cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
+
+ _size = tmpSize;
+
+ for(i = 0; i < 3; i++)
+ _cell_size[i] = _size[i] / _cells_nb[i];
+}
+
+void Grid::insertOccluder(Polygon3r* occluder) {
+ const vector<Vec3r> vertices = occluder->getVertices();
+ if (vertices.size() == 0)
+ return;
+
+ // add this occluder to the grid's occluders list
+ addOccluder(occluder);
+
+ // find the bbox associated to this polygon
+ Vec3r min, max;
+ occluder->getBBox(min, max);
+
+ // Retrieve the cell x, y, z cordinates associated with these min and max
+ Vec3u imax, imin;
+ getCellCoordinates(max, imax);
+ getCellCoordinates(min, imin);
+
+ // We are now going to fill in the cells overlapping with the
+ // polygon bbox.
+ // If the polygon is a triangle (most of cases), we also
+ // check for each of these cells if it is overlapping with
+ // the triangle in order to only fill in the ones really overlapping
+ // the triangle.
+
+ unsigned i, x, y, z;
+ vector<Vec3r>::const_iterator it;
+ Vec3u coord;
+
+ if (vertices.size() == 3) { // Triangle case
+ Vec3r triverts[3];
+ i = 0;
+ for(it = vertices.begin();
+ it != vertices.end();
+ it++) {
+ triverts[i] = Vec3r(*it);
+ i++;
+ }
+
+ Vec3r boxmin, boxmax;
+
+ for (z = imin[2]; z <= imax[2]; z++)
+ for (y = imin[1]; y <= imax[1]; y++)
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ // We retrieve the box coordinates of the current cell
+ getCellBox(coord, boxmin, boxmax);
+ // We check whether the triangle and the box ovewrlap:
+ Vec3r boxcenter((boxmin + boxmax) / 2.0);
+ Vec3r boxhalfsize(_cell_size / 2.0);
+ if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
+ // We must then create the Cell and add it to the cells list
+ // if it does not exist yet.
+ // We must then add the occluder to the occluders list of this cell.
+ Cell* cell = getCell(coord);
+ if (!cell) {
+ cell = new Cell(boxmin);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+ }
+ else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
+ for (z = imin[2]; z <= imax[2]; z++)
+ for (y = imin[1]; y <= imax[1]; y++)
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ Cell* cell = getCell(coord);
+ if (!cell) {
+ Vec3r orig;
+ getCellOrigin(coord, orig);
+ cell = new Cell(orig);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+}
+
+bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell) {
+ next_cell = current_cell;
+ real t_min, t;
+ unsigned i;
+
+ t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
+ unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
+
+
+ // using a parametric equation of
+ // a line : B = A + t u, we find
+ // the tx, ty and tz respectively coresponding
+ // to the intersections with the plans:
+ // x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
+ for (i = 0; i < 3; i++) {
+ if (_ray_dir[i] == 0)
+ continue;
+ if (_ray_dir[i] > 0)
+ t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
+ else
+ t = -_pt[i] / _ray_dir[i];
+ if (t < t_min) {
+ t_min = t;
+ coord = i;
+ }
+ }
+
+ // We use the parametric line equation and
+ // the found t (tamx) to compute the
+ // B coordinates:
+ Vec3r pt_tmp(_pt);
+ _pt = pt_tmp + t_min * _ray_dir;
+
+ // We express B coordinates in the next cell
+ // coordinates system. We just have to
+ // set the coordinate coord of B to 0
+ // of _CellSize[coord] depending on the sign
+ // of _u[coord]
+ if (_ray_dir[coord] > 0) {
+ next_cell[coord]++;
+ _pt[coord] -= _cell_size[coord];
+ // if we are out of the grid, we must stop
+ if (next_cell[coord] >= _cells_nb[coord])
+ return false;
+ }
+ else {
+ int tmp = next_cell[coord] - 1;
+ _pt[coord] = _cell_size[coord];
+ if (tmp < 0)
+ return false;
+ next_cell[coord]--;
+ }
+
+ _t += t_min;
+ if (_t >= _t_end)
+ return false;
+
+ return true;
+}
+
+void Grid::castRay(const Vec3r& orig,
+ const Vec3r& end,
+ OccludersSet& occluders,
+ unsigned timestamp) {
+ initRay(orig, end, timestamp);
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
+}
+
+void Grid::castInfiniteRay(const Vec3r& orig,
+ const Vec3r& dir,
+ OccludersSet& occluders,
+ unsigned timestamp) {
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if(!inter)
+ return;
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
+}
+
+Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig,
+ const Vec3r& dir,
+ double& t,
+ double& u,
+ double& v,
+ unsigned timestamp){
+ Polygon3r *occluder = 0;
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if(!inter){
+ return 0;
+ }
+ firstIntersectionGridVisitor visitor(orig,dir,_cell_size);
+ castRayInternal(visitor);
+ occluder = visitor.occluder();
+ t = visitor.t_;
+ u = visitor.u_;
+ v = visitor.v_;
+ return occluder;
+}
+
+void Grid::initRay (const Vec3r &orig,
+ const Vec3r& end,
+ unsigned timestamp) {
+ _ray_dir = end - orig;
+ _t_end = _ray_dir.norm();
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ for(unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ //_ray_occluders.clear();
+
+}
+
+bool Grid::initInfiniteRay (const Vec3r &orig,
+ const Vec3r& dir,
+ unsigned timestamp) {
+ _ray_dir = dir;
+ _t_end = FLT_MAX;
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ // check whether the origin is in or out the box:
+ Vec3r boxMin(_orig);
+ Vec3r boxMax(_orig+_size);
+ BBox<Vec3r> box(boxMin, boxMax);
+ if(box.inside(orig)){
+ for(unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ }else{
+ // is the ray intersecting the box?
+ real tmin(-1.0), tmax(-1.0);
+ if(GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)){
+ assert(tmin != -1.0);
+ Vec3r newOrig = orig + tmin*_ray_dir;
+ for(unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
+ if(_current_cell[i] == _cells_nb[i])
+ _current_cell[i] = _cells_nb[i] - 1;
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+
+ }else{
+ return false;
+ }
+ }
+ //_ray_occluders.clear();
+
+ return true;
+
+}
+
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
new file mode 100755
index 00000000000..e54b7b4d381
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -0,0 +1,363 @@
+//
+// Filename : Grid.h
+// Author(s) : Stephane Grabli
+// Purpose : Base class to define a cell grid surrounding
+// the bounding box of the scene
+// Date of creation : 30/07/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 GRID_H
+# define GRID_H
+
+# include <cstring> // for memset
+# include <float.h>
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "GeomUtils.h"
+# include "Geom.h"
+# include "Polygon.h"
+
+using namespace std;
+using namespace Geometry;
+
+typedef vector<Polygon3r*> OccludersSet;
+
+
+//
+// Class to define cells used by the regular grid
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class LIB_GEOMETRY_EXPORT Cell
+{
+ public:
+
+ Cell(Vec3r& orig) {
+ _orig = orig;
+ }
+
+ virtual ~Cell() {}
+
+ inline void addOccluder(Polygon3r* o) {
+ if (o)
+ _occluders.push_back(o);
+ }
+
+ inline const Vec3r& getOrigin() {
+ return _orig;
+ }
+
+ inline OccludersSet& getOccluders() {
+ return _occluders;
+ }
+
+ private:
+
+ Vec3r _orig;
+ OccludersSet _occluders;
+};
+
+
+class GridVisitor{
+public:
+ virtual ~GridVisitor() {}; //soc
+ virtual void discoverCell(Cell *cell) {}
+ virtual void examineOccluder(Polygon3r *occ) {}
+ virtual void finishCell(Cell *cell) {}
+ virtual bool stop() {return false;}
+};
+
+/*! Gathers all the occluders belonging to the cells
+ * traversed by the ray */
+class allOccludersGridVisitor : public GridVisitor{
+public:
+ allOccludersGridVisitor(OccludersSet& occluders)
+ :GridVisitor(), occluders_(occluders){}
+ virtual void examineOccluder(Polygon3r *occ);
+
+ OccludersSet& occluders() {return occluders_;}
+ void clear() {occluders_.clear();}
+
+private:
+ OccludersSet& occluders_;
+};
+
+/*! Finds the first intersection and breaks. The occluder and
+ * the intersection information are stored and accessible.
+ */
+class firstIntersectionGridVisitor : public GridVisitor {
+
+//soc - changed order to remove warnings
+public:
+ double u_, v_, t_;
+private:
+ Polygon3r *occluder_;
+ Vec3r ray_org_, ray_dir_, cell_size_;
+ Cell * current_cell_;
+
+public:
+ firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
+ GridVisitor(), u_(0),v_(0),t_(DBL_MAX),
+ occluder_(0),
+ ray_org_(ray_org), ray_dir_(ray_dir), cell_size_(cell_size),
+ current_cell_(0) {}
+ virtual ~firstIntersectionGridVisitor() {}
+
+ virtual void discoverCell(Cell *cell) {current_cell_=cell;}
+ virtual void examineOccluder(Polygon3r *occ);
+ virtual bool stop();
+
+ Polygon3r * occluder() {return occluder_;}
+};
+
+//
+// Class to define a regular grid used for ray casting computations
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class LIB_GEOMETRY_EXPORT Grid
+{
+public:
+
+ /*! Builds a Grid
+ * Must be followed by a call to configure()
+ */
+ Grid() {}
+
+ virtual ~Grid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable,
+ * resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns a vector of integer containing the
+ * coordinates of the cell containing the point
+ * passed as argument
+ * p
+ * The point for which we're looking the cell
+ */
+ inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
+ int tmp;
+ for (int i = 0; i < 3; i++) {
+ tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
+ if (tmp < 0)
+ res[i] = 0;
+ else if ((unsigned)tmp >= _cells_nb[i])
+ res[i] = _cells_nb[i] - 1;
+ else
+ res[i] = tmp;
+ }
+ }
+
+ /*! Fills the case corresponding to coord with the cell */
+ virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
+
+ /*! returns the cell whose coordinates
+ * are pased as argument
+ */
+ virtual Cell* getCell(const Vec3u& coord) = 0;
+
+ /*! returns the cell containing the point
+ * passed as argument. If the cell is empty
+ * (contains no occluder), NULL is returned
+ * p
+ * The point for which we're looking the cell
+ */
+ inline Cell* getCell(const Vec3r& p) {
+ Vec3u coord;
+ getCellCoordinates(p, coord);
+ return getCell(coord);
+ }
+
+ /*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k)
+ * is passed as argument
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * orig
+ * x,y,x vector to be filled in with the cell origin's coordinates
+ */
+ inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
+ for (unsigned i = 0; i < 3; i++)
+ orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
+ }
+
+ /*! Retrieves the box corresponding to the cell whose coordinates
+ * are passed as argument.
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * min_out
+ * The min x,y,x vector of the box. Filled in by the method.
+ * max_out
+ * The max x,y,z coordinates of the box. Filled in by the method.
+ */
+ inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
+ getCellOrigin(cell_coord, min_out);
+ max_out = min_out + _cell_size;
+ }
+
+ /*! inserts a convex polygon occluder
+ * This method is quite coarse insofar as it
+ * adds all cells intersecting the polygon bounding box
+ * convex_poly
+ * The list of 3D points constituing a convex polygon
+ */
+ void insertOccluder(Polygon3r * convex_poly);
+
+ /*! Adds an occluder to the list of occluders */
+ void addOccluder(Polygon3r* occluder) {
+ _occluders.push_back(occluder);
+ }
+
+ /*! Casts a ray between a starting point and an ending point
+ * Returns the list of occluders contained
+ * in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castRay(const Vec3r& orig,
+ const Vec3r& end,
+ OccludersSet& occluders,
+ unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the list of occluders contained
+ * in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castInfiniteRay(const Vec3r& orig,
+ const Vec3r& dir,
+ OccludersSet& occluders,
+ unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the first intersection (occluder,t,u,v) or null.
+ * Starts with a call to InitRay.
+ */
+ Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig,
+ const Vec3r& dir,
+ double& t,
+ double& u,
+ double& v,
+ unsigned timestamp);
+
+
+ /*! Init all structures and values for computing
+ * the cells intersected by this new ray
+ */
+ void initRay (const Vec3r &orig,
+ const Vec3r& end,
+ unsigned timestamp);
+
+ /*! Init all structures and values for computing
+ * the cells intersected by this infinite ray.
+ * Returns false if the ray doesn't intersect the
+ * grid.
+ */
+ bool initInfiniteRay (const Vec3r &orig,
+ const Vec3r& dir,
+ unsigned timestamp);
+
+
+ /*! Accessors */
+ inline const Vec3r& getOrigin() const {
+ return _orig;
+ }
+ inline Vec3r gridSize() const {
+ return _size;
+ }
+ inline Vec3r getCellSize() const {
+ return _cell_size;
+ }
+
+ void displayDebug() {
+ cerr << "Cells nb : " << _cells_nb << endl;
+ cerr << "Cell size : " << _cell_size << endl;
+ cerr << "Origin : " << _orig << endl;
+ cerr << "Occluders nb : " << _occluders.size() << endl;
+ }
+
+ protected:
+
+ /*! Core of castRay and castInfiniteRay, find occluders
+ * along the given ray
+ */
+ inline void castRayInternal(GridVisitor& visitor) {
+ Cell* current_cell = NULL;
+ do {
+ current_cell = getCell(_current_cell);
+ if (current_cell){
+ visitor.discoverCell(current_cell);
+ OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
+ for (OccludersSet::iterator it = occluders.begin();
+ it != occluders.end();
+ it++) {
+ if ((unsigned long)(*it)->userdata2 != _timestamp) {
+ (*it)->userdata2 = (void*)_timestamp;
+ visitor.examineOccluder(*it);
+ }
+ }
+ visitor.finishCell(current_cell);
+ }
+ } while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
+ }
+
+
+ /*! returns the cell next to the cell
+ * passed as argument.
+ */
+ bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
+
+ unsigned _timestamp;
+
+ Vec3u _cells_nb; // number of cells for x,y,z axis
+ Vec3r _cell_size; // cell x,y,z dimensions
+ Vec3r _size; // grid x,y,x dimensions
+ Vec3r _orig; // grid origin
+
+ Vec3r _ray_dir; // direction vector for the ray
+ Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
+ Vec3r _pt; // Points corresponding to the incoming and outgoing intersections
+ // of one cell with the ray
+ real _t_end; // To know when we are at the end of the ray
+ real _t;
+
+ //OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
+ OccludersSet _occluders; // List of all occluders inserted in the grid
+};
+
+#endif // GRID_H
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp
new file mode 100755
index 00000000000..3cf845d57ef
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp
@@ -0,0 +1,41 @@
+
+//
+// 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 "HashGrid.h"
+
+void HashGrid::clear()
+{
+ if(!_cells.empty()) {
+ for(GridHashTable::iterator it = _cells.begin();
+ it !=_cells.end();
+ it++) {
+ Cell* cell = (*it).second;
+ delete cell;
+ }
+ _cells.clear();
+ }
+
+ Grid::clear();
+}
+
+void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
+ Grid::configure(orig, size, nb);
+}
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.h b/source/blender/freestyle/intern/geometry/HashGrid.h
new file mode 100755
index 00000000000..f6605957676
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/HashGrid.h
@@ -0,0 +1,109 @@
+//
+// Filename : HashGrid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a cell grid surrounding the
+// bounding box of the scene
+// Date of creation : 30/07/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 HASHGRID_H
+# define HASHGRID_H
+
+//# 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 "Grid.h"
+# include <map>
+/*! Defines a hash table used for searching the Cells */
+struct GridHasher{
+#define _MUL 950706376UL
+#define _MOD 2147483647UL
+ inline size_t operator() (const Vec3u& 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;
+ }
+};
+
+/*! Class to define a regular grid used for ray
+ casting computations */
+
+class LIB_GEOMETRY_EXPORT HashGrid : public Grid
+{
+ public:
+
+ typedef map<Vec3u, Cell*> GridHashTable;
+
+ HashGrid() : Grid() {}
+
+ virtual ~HashGrid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable,
+ * resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates
+ * are pased as argument
+ */
+ virtual Cell* getCell(const Vec3u& p) {
+ Cell* found_cell = NULL;
+
+ GridHashTable::const_iterator found = _cells.find(p);
+ if (found != _cells.end())
+ found_cell = (*found).second;
+ return found_cell;
+ }
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell) {
+ _cells[p] = &cell;
+ }
+
+protected:
+
+ GridHashTable _cells;
+};
+
+#endif // HASHGRID_H
diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
new file mode 100755
index 00000000000..396fc3bbb47
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -0,0 +1,264 @@
+
+//
+// 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 "Noise.h"
+# include <stdlib.h>
+# include <stdio.h>
+# include <math.h>
+#include <time.h>
+
+#define MINX -1000000
+#define MINY MINX
+#define MINZ MINX
+#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
+#define REALSCALE ( 2.0 / 65536.0 )
+#define NREALSCALE ( 2.0 / 4096.0 )
+#define HASH3D(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
+#define HASH(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
+#define INCRSUM(m,s,x,y,z) ((s)*(RTable[m]*0.5 \
+ + RTable[m+1]*(x) \
+ + RTable[m+2]*(y) \
+ + RTable[m+3]*(z)))
+#define MAXSIZE 500
+#define nrand() ((float)rand()/(float)RAND_MAX)
+#define seednrand(x) srand(x*RAND_MAX)
+
+#define BM 0xff
+
+#define N 0x1000
+#define NP 12 /* 2^N */
+#define NM 0xfff
+
+#define s_curve(t) ( t * t * (3. - 2. * t) )
+
+#define lerp(t, a, b) ( a + t * (b - a) )
+
+#define setup(i,b0,b1,r0,r1)\
+ t = i + N;\
+ b0 = ((int)t) & BM;\
+ b1 = (b0+1) & BM;\
+ r0 = t - (int)t;\
+ r1 = r0 - 1.;
+
+void normalize2(float v[2])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+}
+
+void normalize3(float v[3])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+ v[2] = v[2] / s;
+}
+
+float Noise::turbulence1(float arg, float freq, float amp, unsigned oct)
+{
+ float t;
+ float vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
+ {
+ vec = freq * arg;
+ t += smoothNoise1(vec) * amp;
+ }
+ return t;
+}
+
+float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct)
+{
+ float t;
+ Vec2f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
+ {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ t += smoothNoise2(vec) * amp;
+ }
+ return t;
+}
+
+float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct)
+{
+ float t;
+ Vec3f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
+ {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ vec.z() = freq * v.z();
+ t += smoothNoise3(vec) * amp;
+ }
+ return t;
+}
+
+// Noise functions over 1, 2, and 3 dimensions
+
+float Noise::smoothNoise1(float arg)
+{
+ int bx0, bx1;
+ float rx0, rx1, sx, t, u, v, vec;
+
+ vec = arg;
+ setup(vec, bx0,bx1, rx0,rx1);
+
+ sx = s_curve(rx0);
+
+ u = rx0 * g1[ p[ bx0 ] ];
+ v = rx1 * g1[ p[ bx1 ] ];
+
+ return lerp(sx, u, v);
+}
+
+float Noise::smoothNoise2(Vec2f& vec)
+{
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+ register int i, j;
+
+ setup(vec.x(), bx0,bx1, rx0,rx1);
+ setup(vec.y(), by0,by1, ry0,ry1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ sx = s_curve(rx0);
+ sy = s_curve(ry0);
+
+#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
+
+ q = g2[ b00 ] ; u = at2(rx0,ry0);
+ q = g2[ b10 ] ; v = at2(rx1,ry0);
+ a = lerp(sx, u, v);
+
+ q = g2[ b01 ] ; u = at2(rx0,ry1);
+ q = g2[ b11 ] ; v = at2(rx1,ry1);
+ b = lerp(sx, u, v);
+
+ return lerp(sy, a, b);
+}
+
+float Noise::smoothNoise3(Vec3f& vec)
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+ setup(vec.x(), bx0,bx1, rx0,rx1);
+ setup(vec.y(), by0,by1, ry0,ry1);
+ setup(vec.z(), bz0,bz1, rz0,rz1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ t = s_curve(rx0);
+ sy = s_curve(ry0);
+ sz = s_curve(rz0);
+
+#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+
+ q = g3[ b00 + bz0 ] ;
+ u = at3(rx0,ry0,rz0);
+ q = g3[ b10 + bz0 ] ;
+ v = at3(rx1,ry0,rz0);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz0 ] ;
+ u = at3(rx0,ry1,rz0);
+ q = g3[ b11 + bz0 ] ;
+ v = at3(rx1,ry1,rz0);
+ b = lerp(t, u, v);
+
+ c = lerp(sy, a, b);
+
+ q = g3[ b00 + bz1 ] ;
+ u = at3(rx0,ry0,rz1);
+ q = g3[ b10 + bz1 ] ;
+ v = at3(rx1,ry0,rz1);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz1 ] ;
+ u = at3(rx0,ry1,rz1);
+ q = g3[ b11 + bz1 ] ;
+ v = at3(rx1,ry1,rz1);
+ b = lerp(t, u, v);
+
+ d = lerp(sy, a, b);
+
+ return lerp(sz, c, d);
+}
+
+Noise::Noise()
+{
+ int i, j, k;
+
+ seednrand(time(NULL));
+ for (i = 0 ; i < _Noise_B_ ; i++)
+ {
+ p[i] = i;
+
+ g1[i] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
+ normalize2(g2[i]);
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
+ normalize3(g3[i]);
+ }
+
+ while (--i)
+ {
+ k = p[i];
+ p[i] = p[j = rand() % _Noise_B_];
+ p[j] = k;
+ }
+
+ for (i = 0 ; i < _Noise_B_ + 2 ; i++)
+ {
+ p[_Noise_B_ + i] = p[i];
+ g1[_Noise_B_ + i] = g1[i];
+ for (j = 0 ; j < 2 ; j++)
+ g2[_Noise_B_ + i][j] = g2[i][j];
+ for (j = 0 ; j < 3 ; j++)
+ g3[_Noise_B_ + i][j] = g3[i][j];
+ }
+}
diff --git a/source/blender/freestyle/intern/geometry/Noise.h b/source/blender/freestyle/intern/geometry/Noise.h
new file mode 100755
index 00000000000..00cebbb451e
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Noise.h
@@ -0,0 +1,77 @@
+//
+// Filename : Noise.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Class to define Perlin noise
+// Date of creation : 12/01/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 NOISE_H
+# define NOISE_H
+
+
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+
+#define _Noise_B_ 0x100
+
+using namespace Geometry;
+using namespace std;
+
+/*! Class to provide Perlin Noise functionalities */
+class LIB_GEOMETRY_EXPORT Noise
+{
+ public:
+
+ /*! Builds a Noise object */
+ Noise();
+ /*! Destructor */
+ ~Noise() {}
+
+ /*! Returns a noise value for a 1D element */
+ float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a noise value for a 2D element */
+ float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a noise value for a 3D element */
+ float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
+
+ /*! Returns a smooth noise value for a 1D element */
+ float smoothNoise1(float arg);
+ /*! Returns a smooth noise value for a 2D element */
+ float smoothNoise2(Vec2f& vec);
+ /*! Returns a smooth noise value for a 3D element */
+ float smoothNoise3(Vec3f& vec);
+
+ private:
+
+ int p[ _Noise_B_ + _Noise_B_ + 2];
+ float g3[ _Noise_B_ + _Noise_B_ + 2][3];
+ float g2[ _Noise_B_ + _Noise_B_ + 2][2];
+ float g1[ _Noise_B_ + _Noise_B_ + 2];
+ int start;
+};
+
+#endif // NOISE_H
diff --git a/source/blender/freestyle/intern/geometry/Polygon.h b/source/blender/freestyle/intern/geometry/Polygon.h
new file mode 100755
index 00000000000..f9c4c78d424
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/Polygon.h
@@ -0,0 +1,215 @@
+//
+// Filename : Polygon.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a polygon
+// Date of creation : 30/07/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 POLYGON_H
+# define POLYGON_H
+
+# include <vector>
+# include "Geom.h"
+# include "GeomUtils.h"
+
+using namespace std;
+
+namespace Geometry {
+
+template <class Point>
+class Polygon
+{
+ public:
+
+ inline Polygon() {
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const vector<Point>& vertices) {
+ _vertices = vertices;
+ computeBBox();
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const Polygon<Point>& poly) {
+ Point p;
+ for(typename vector<Point>::const_iterator it = poly.getVertices().begin();
+ it != poly.getVertices().end();
+ it++) {
+ p = *it;
+ _vertices.push_back(p);
+ }
+
+ _id = poly.getId();
+ poly.getBBox(_min, _max);
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ virtual ~Polygon() {}
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline const vector<Point>& getVertices() const {
+ return _vertices;
+ }
+
+ inline void getBBox(Point& min, Point& max) const {
+ min = _min;
+ max = _max;
+ }
+
+ inline Point& getBBoxCenter()
+ {
+ Point result;
+ result = (_min + _max) / 2;
+ return result;
+ }
+
+ inline Point& getCenter() {
+ Point result;
+ for (typename vector<Point>::iterator it = _vertices.begin();
+ it != _vertices.end();
+ it++)
+ result += *it;
+ result /= _vertices.size();
+ return result;
+ }
+
+ inline unsigned getId() const {
+ return _id;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void setVertices(const vector<Point>& vertices) {
+ _vertices.clear();
+ Point p;
+ for (typename vector<Point>::const_iterator it = vertices.begin();
+ it != vertices.end();
+ it++) {
+ p = *it;
+ _vertices.push_back(p);
+ }
+ computeBBox();
+ }
+
+ inline void setId(unsigned id) {
+ _id = id;
+ }
+
+ //
+ // Other methods
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void computeBBox() {
+ if(_vertices.empty())
+ return;
+
+ _max = _vertices[0];
+ _min = _vertices[0];
+
+ for(typename vector<Point>::iterator it = _vertices.begin();
+ it != _vertices.end();
+ it++) {
+ for(unsigned i = 0; i < Point::dim(); i++) {
+ if((*it)[i] > _max[i])
+ _max[i] = (*it)[i];
+ if((*it)[i] < _min[i])
+ _min[i] = (*it)[i];
+ }
+ }
+ }
+
+ // FIXME Is it possible to get rid of userdatas ?
+ void* userdata;
+ void* userdata2; // Used during ray casting
+
+ protected:
+
+ vector<Point> _vertices;
+ Point _min;
+ Point _max;
+ unsigned _id;
+};
+
+
+//
+// Polygon3r class
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class Polygon3r : public Polygon<Vec3r>
+{
+ public:
+
+ inline Polygon3r() : Polygon<Vec3r>() {}
+
+ inline Polygon3r(const vector<Vec3r>& vertices,
+ const Vec3r& normal) : Polygon<Vec3r>(vertices) {
+ setNormal(normal);
+ }
+
+ inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly) {}
+
+ virtual ~Polygon3r() {}
+
+ void setNormal(const Vec3r& normal) {
+ _normal = normal;
+ }
+
+ Vec3r getNormal() const {
+ return _normal;
+ }
+
+ /*! Check whether the Polygon intersects with the ray or not */
+ inline bool rayIntersect(Vec3r& orig, Vec3r& dir,
+ real& t, real& u, real& v, real epsilon = M_EPSILON) {
+ // if (_vertices.size() < 3)
+ // return false;
+ return GeomUtils::intersectRayTriangle(orig, dir,
+ _vertices[0], _vertices[1], _vertices[2],
+ t, u, v, epsilon);
+ }
+
+ private:
+
+ Vec3r _normal;
+};
+
+} // end of namespace Geometry
+
+#endif // POLYGON_H
diff --git a/source/blender/freestyle/intern/geometry/SweepLine.h b/source/blender/freestyle/intern/geometry/SweepLine.h
new file mode 100755
index 00000000000..cf4c86d006d
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/SweepLine.h
@@ -0,0 +1,336 @@
+//
+// Filename : SweepLine.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a Sweep Line
+// Date of creation : 29/08/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 SWEEPLINE_H
+# define SWEEPLINE_H
+
+# include <list>
+# include <vector>
+
+/*! Class to define the intersection berween two segments*/
+template<class Edge>
+class Intersection
+{
+public:
+
+ template<class EdgeClass>
+ Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb)
+ {
+ EdgeA = eA;
+ EdgeB = eB;
+ tA = ta;
+ tB = tb;
+ userdata = 0;
+ }
+
+ Intersection(const Intersection& iBrother)
+ {
+ EdgeA = iBrother.EdgeA;
+ EdgeB = iBrother.EdgeB;
+ tA = iBrother.tA;
+ tB = iBrother.tB;
+ userdata = 0;
+ }
+
+ /*! returns the parameter giving the
+ * intersection, for the edge iEdge
+ */
+ real getParameter(Edge *iEdge)
+ {
+ if(iEdge == EdgeA)
+ return tA;
+ if(iEdge == EdgeB)
+ return tB;
+ return 0;
+ }
+
+public:
+ void * userdata; // FIXME
+
+ Edge *EdgeA; // first segment
+ Edge *EdgeB; // second segment
+ real tA; // parameter defining the intersection point with respect to the segment EdgeA.
+ real tB; // parameter defining the intersection point with respect to the segment EdgeB.
+};
+
+
+
+
+
+
+
+
+template<class T, class Point>
+class Segment
+{
+ public:
+ Segment()
+ {
+ }
+ Segment(T& s, const Point& iA, const Point& iB)
+ {
+ _edge = s;
+ if(iA < iB)
+ {
+ A = iA;
+ B = iB;
+ _order = true;
+ }
+ else
+ {
+ A = iB;
+ B = iA;
+ _order = false;
+ }
+ }
+
+ Segment(Segment<T,Point>& iBrother)
+ {
+ _edge = iBrother.edge();
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ Segment(const Segment<T,Point>& iBrother)
+ {
+ _edge = iBrother._edge;
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ ~Segment() {
+ _Intersections.clear();
+ }
+
+ inline Point operator[](const unsigned short int& i) const
+ {
+ return i%2==0 ? A : B;
+ }
+
+ inline bool operator==(const Segment<T,Point>& iBrother)
+ {
+ if(_edge == iBrother._edge)
+ return true;
+
+ return false;
+ }
+
+ /* Adds an intersection for this segment */
+ inline void AddIntersection(Intersection<Segment<T,Point> > *i) {_Intersections.push_back(i);}
+
+ /*! Checks for a common vertex with another edge */
+ inline bool CommonVertex(const Segment<T,Point>& S, Point& CP)
+ {
+ if((A == S[0]) || (A == S[1]))
+ {
+ CP = A;
+ return true;
+ }
+ if((B == S[0]) || (B == S[1]))
+ {
+ CP = B;
+ return true;
+ }
+
+ return false;
+ }
+
+ inline vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
+ inline bool order() {return _order;}
+ inline T& edge() {return _edge;}
+
+ private:
+ T _edge;
+ Point A;
+ Point B;
+ std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters
+ bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
+};
+
+/*! defines a binary function that can be overload
+ * by the user to specify at each condition
+ * the intersection between 2 edges must be computed
+ */
+template<class T1, class T2>
+struct binary_rule
+{
+ binary_rule() {}
+ template<class T3,class T4>
+ binary_rule(const binary_rule<T3,T4>& brother) {}
+ virtual ~binary_rule() {}
+
+ virtual bool operator()(T1&, T2&)
+ {
+ return true;
+ }
+};
+
+
+template<class T,class Point>
+class SweepLine
+{
+public:
+
+ SweepLine() {}
+ ~SweepLine()
+ {
+ for(typename vector<Intersection<Segment<T,Point> >*>::iterator i=_Intersections.begin(),iend=_Intersections.end();
+ i!=iend;
+ i++)
+ {
+ delete (*i);
+ }
+ _Intersections.clear();
+
+ for(typename vector<Segment<T,Point>* >::iterator ie=_IntersectedEdges.begin(),ieend=_IntersectedEdges.end();
+ ie!=ieend;
+ ie++)
+ {
+ delete (*ie);
+ }
+ _IntersectedEdges.clear();
+
+ _set.clear();
+ }
+
+
+ inline void process(Point& p,
+ vector<Segment<T,Point>*>& segments,
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
+ //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>,Segment<T,Point> >(),
+ real epsilon = M_EPSILON
+ )
+ {
+ // first we remove the segments that need to be removed and then
+ // we add the segments to add
+ vector<Segment<T,Point>*> toadd;
+ typename vector<Segment<T,Point>*>::iterator s, send;
+ for(s=segments.begin(), send=segments.end();
+ s!=send;
+ s++)
+ {
+ if(p == (*(*s))[0])
+ toadd.push_back((*s));
+ else
+ remove((*s));
+ }
+ for(s=toadd.begin(), send=toadd.end();
+ s!=send;
+ s++)
+ {
+ add((*s), binrule, epsilon);
+ }
+ }
+
+ inline void add(Segment<T,Point>* S,
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
+ //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>, Segment<T,Point> >(),
+ real epsilon
+ )
+ {
+ real t,u;
+ Point CP;
+ Vec2r v0, v1, v2, v3;
+ if(true == S->order())
+ {
+ v0[0] = ((*S)[0])[0];
+ v0[1] = ((*S)[0])[1];
+ v1[0] = ((*S)[1])[0];
+ v1[1] = ((*S)[1])[1];
+ }
+ else
+ {
+ v1[0] = ((*S)[0])[0];
+ v1[1] = ((*S)[0])[1];
+ v0[0] = ((*S)[1])[0];
+ v0[1] = ((*S)[1])[1];
+ }
+ for(typename std::list<Segment<T,Point>* >::iterator s=_set.begin(), send=_set.end();
+ s!=send;
+ s++)
+ {
+ Segment<T,Point>* currentS = (*s);
+ if(true != binrule(*S, *currentS))
+ continue;
+
+ if(true == currentS->order())
+ {
+ v2[0] = ((*currentS)[0])[0];
+ v2[1] = ((*currentS)[0])[1];
+ v3[0] = ((*currentS)[1])[0];
+ v3[1] = ((*currentS)[1])[1];
+ }
+ else
+ {
+ v3[0] = ((*currentS)[0])[0];
+ v3[1] = ((*currentS)[0])[1];
+ v2[0] = ((*currentS)[1])[0];
+ v2[1] = ((*currentS)[1])[1];
+ }
+ if(S->CommonVertex(*currentS, CP))
+ continue; // the two edges have a common vertex->no need to check
+
+ if(GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT)
+ {
+ // create the intersection
+ Intersection<Segment<T,Point> > * inter = new Intersection<Segment<T,Point> >(S,t,currentS,u);
+ // add it to the intersections list
+ _Intersections.push_back(inter);
+ // add this intersection to the first edge intersections list
+ S->AddIntersection(inter);
+ // add this intersection to the second edge intersections list
+ currentS->AddIntersection(inter);
+ }
+ }
+ // add the added segment to the list of active segments
+ _set.push_back(S);
+ }
+
+ inline void remove(Segment<T,Point>* s)
+ {
+ if(s->intersections().size() > 0)
+ _IntersectedEdges.push_back(s);
+ _set.remove(s);
+ }
+
+ vector<Segment<T,Point>* >& intersectedEdges() {return _IntersectedEdges;}
+ vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
+
+
+private:
+ std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line
+ std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges
+ std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections.
+};
+
+#endif // SWEEPLINE_H
diff --git a/source/blender/freestyle/intern/geometry/VecMat.h b/source/blender/freestyle/intern/geometry/VecMat.h
new file mode 100755
index 00000000000..9bbec3b1349
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/VecMat.h
@@ -0,0 +1,899 @@
+//
+// Filename : VecMat.h
+// Author(s) : Sylvain Paris
+// Emmanuel Turquin
+// Stephane Grabli
+// Purpose : Vectors and Matrices definition and manipulation
+// Date of creation : 12/06/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 VECMAT_H
+# define VECMAT_H
+
+# include <math.h>
+# include <vector>
+# include <iostream>
+
+namespace VecMat {
+
+ namespace Internal {
+
+ template <bool B>
+ struct is_false {};
+
+ template <>
+ struct is_false<false> {
+ static inline void ensure() {}
+ };
+
+ } // end of namespace Internal
+
+ //
+ // Vector class
+ // - T: value type
+ // - N: dimension
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T, unsigned N>
+ class Vec
+ {
+ public:
+
+ typedef T value_type;
+
+ // constructors
+
+ inline Vec() {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Vec() {
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Vec(const U tab[N]) {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const std::vector<U>& tab) {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const Vec<U, N>& v) {
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ }
+
+ // accessors
+
+ inline value_type operator[](const unsigned i) const {
+ return this->_coord[i];
+ }
+
+ inline value_type& operator[](const unsigned i) {
+ return this->_coord[i];
+ }
+
+ static inline unsigned dim() {
+ return N;
+ }
+
+ // various useful methods
+
+ inline value_type norm() const {
+ return (T)sqrt((float)squareNorm());
+ }
+
+ inline value_type squareNorm() const {
+ return (*this) * (*this);
+ }
+
+ inline Vec<T, N>& normalize() {
+ value_type n = norm();
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] /= n;
+ return *this;
+ }
+
+ inline Vec<T, N>& normalizeSafe() {
+ value_type n = norm();
+ if (n)
+ for (unsigned i=0; i < N; i++)
+ this->_coord[i] /= n;
+ return *this;
+ }
+
+ // classical operators
+ inline Vec<T, N> operator+(const Vec<T, N>& v) const{
+ Vec<T, N> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec<T, N> operator-(const Vec<T,N>& v) const{
+ Vec<T, N> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const{
+ Vec<T, N> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const{
+ Vec<T, N> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec<T, N>& v) const{
+ value_type sum = 0;
+ for (unsigned i = 0; i < N; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator=(const Vec<U, N>& v) {
+ if (this != &v)
+ for (unsigned i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator+=(const Vec<U, N>& v) {
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] += (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator-=(const Vec<U, N>& v) {
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] -= (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator*=(const U r) {
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] *= r;
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator/=(const U r) {
+ if (r)
+ for (unsigned i = 0 ; i < N; i++)
+ this->_coord[i] /= r;
+ return *this;
+ }
+
+
+ inline bool operator==(const Vec<T, N>& v) const {
+ for(unsigned i = 0; i < N; i++)
+ if (this->_coord[i] != v[i])
+ return false;
+ return true;
+ }
+
+ inline bool operator!=(const Vec<T, N>& v) const {
+ for(unsigned i = 0; i < N; i++)
+ if (this->_coord[i] != v[i])
+ return true;
+ return false;
+ }
+
+ inline bool operator<(const Vec<T, N>& v) const {
+ for (unsigned i = 0; i<N; i++) {
+ if (this->_coord[i] < v[i])
+ return true;
+ if (this->_coord[i] > v[i])
+ return false;
+ if (this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+ inline bool operator>(const Vec<T, N>& v) const {
+ for (unsigned i=0; i<N; i++) {
+ if(this->_coord[i] > v[i])
+ return true;
+ if(this->_coord[i] < v[i])
+ return false;
+ if(this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+ protected:
+
+ value_type _coord[N];
+ enum {
+ _dim = N,
+ };
+ };
+
+
+ //
+ // Vec2 class (2D Vector)
+ // - T: value type
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class Vec2 : public Vec<T, 2>
+ {
+ public:
+
+ typedef typename Vec<T, 2>::value_type value_type;
+
+ inline Vec2() : Vec<T, 2>() {}
+
+ template <class U>
+ explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {}
+
+ inline Vec2(const value_type x,
+ const value_type y = 0) : Vec<T, 2>() {
+ this->_coord[0] = (T)x;
+ this->_coord[1] = (T)y;
+ }
+
+ inline value_type x() const {
+ return this->_coord[0];
+ }
+
+ inline value_type& x() {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const {
+ return this->_coord[1];
+ }
+
+ inline value_type& y() {
+ return this->_coord[1];
+ }
+
+ inline void setX(const value_type v) {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v) {
+ this->_coord[1] = v;
+ }
+
+ // FIXME: hack swig -- no choice
+ inline Vec2<T> operator+(const Vec2<T>& v) const{
+ Vec2<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec2<T> operator-(const Vec2<T>& v) const{
+ Vec2<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec2<T> operator*(const value_type r) const{
+ Vec2<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec2<T> operator/(const value_type r) const{
+ Vec2<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec2<T>& v) const{
+ value_type sum = 0;
+ for (unsigned i = 0; i < 2; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+ };
+
+
+ //
+ // HVec3 class (3D Vector in homogeneous coordinates)
+ // - T: value type
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class HVec3 : public Vec<T, 4>
+ {
+ public:
+
+ typedef typename Vec<T, 4>::value_type value_type;
+
+ inline HVec3() : Vec<T, 4>() {}
+
+ template <class U>
+ explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {}
+
+ template <class U>
+ explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {}
+
+ template<class U>
+ inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {}
+
+ inline HVec3(const value_type sx,
+ const value_type sy = 0,
+ const value_type sz = 0,
+ const value_type s = 1) {
+ this->_coord[0] = sx;
+ this->_coord[1] = sy;
+ this->_coord[2] = sz;
+ this->_coord[3] = s;
+ }
+
+ template <class U>
+ inline HVec3(const Vec<U, 3>& sv,
+ const U s = 1) {
+ this->_coord[0] = (T)sv[0];
+ this->_coord[1] = (T)sv[1];
+ this->_coord[2] = (T)sv[2];
+ this->_coord[3] = (T)s;
+ }
+
+ inline value_type sx() const {
+ return this->_coord[0];
+ }
+
+ inline value_type& sx() {
+ return this->_coord[0];
+ }
+
+ inline value_type sy() const {
+ return this->_coord[1];
+ }
+
+ inline value_type& sy() {
+ return this->_coord[1];
+ }
+
+ inline value_type sz() const {
+ return this->_coord[2];
+ }
+
+ inline value_type& sz() {
+ return this->_coord[2];
+ }
+
+ inline value_type s() const {
+ return this->_coord[3];
+ }
+
+ inline value_type& s() {
+ return this->_coord[3];
+ }
+
+ // Acces to non-homogeneous coordinates in 3D
+
+ inline value_type x() const {
+ return this->_coord[0] / this->_coord[3];
+ }
+
+ inline value_type y() const {
+ return this->_coord[1] / this->_coord[3];
+ }
+
+ inline value_type z() const {
+ return this->_coord[2] / this->_coord[3];
+ }
+ };
+
+
+ //
+ // Vec3 class (3D Vec)
+ // - T: value type
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class Vec3 : public Vec<T, 3>
+ {
+ public:
+
+ typedef typename Vec<T, 3>::value_type value_type;
+
+ inline Vec3() : Vec<T, 3>() {}
+
+ template <class U>
+ explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {}
+
+ template <class U>
+ explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {}
+
+ template<class U>
+ inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {}
+
+ template<class U>
+ inline Vec3(const HVec3<U>& v) {
+ this->_coord[0] = (T)v.x();
+ this->_coord[1] = (T)v.y();
+ this->_coord[2] = (T)v.z();
+ }
+
+ inline Vec3(const value_type x,
+ const value_type y = 0,
+ const value_type z = 0) : Vec<T, 3>() {
+ this->_coord[0] = x;
+ this->_coord[1] = y;
+ this->_coord[2] = z;
+ }
+
+ inline value_type x() const {
+ return this->_coord[0];
+ }
+
+ inline value_type& x() {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const {
+ return this->_coord[1];
+ }
+
+ inline value_type& y() {
+ return this->_coord[1];
+ }
+
+ inline value_type z() const {
+ return this->_coord[2];
+ }
+
+ inline value_type& z() {
+ return this->_coord[2];
+ }
+
+ inline void setX(const value_type v) {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v) {
+ this->_coord[1] = v;
+ }
+
+ inline void setZ(const value_type v) {
+ this->_coord[2] = v;
+ }
+
+ // classical operators
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator+(const Vec3<T>& v) const{
+ Vec3<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec3<T> operator-(const Vec3<T>& v) const{
+ Vec3<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec3<T> operator*(const value_type r) const{
+ Vec3<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec3<T> operator/(const value_type r) const{
+ Vec3<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec3<T>& v) const{
+ value_type sum = 0;
+ for (unsigned i = 0; i < 3; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ // cross product for 3D Vectors
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator^(const Vec3<T>& v) const{
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+
+ // cross product for 3D Vectors
+ template <typename U>
+ inline Vec3<T> operator^(const Vec<U, 3>& v) const{
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+ };
+
+
+ //
+ // Matrix class
+ // - T: value type
+ // - M: rows
+ // - N: cols
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Dirty, but icc under Windows needs this
+# define _SIZE (M * N)
+
+ template <class T, unsigned M, unsigned N>
+ class Matrix
+ {
+ public:
+
+ typedef T value_type;
+
+ inline Matrix() {
+ for (unsigned i = 0; i < _SIZE; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Matrix() {
+ Internal::is_false<(M == 0)>::ensure();
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Matrix(const U tab[_SIZE]) {
+ for (unsigned i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ explicit inline Matrix(const std::vector<U>& tab) {
+ for (unsigned i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ inline Matrix(const Matrix<U, M, N>& m) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ }
+
+ inline value_type operator()(const unsigned i, const unsigned j) const {
+ return this->_coord[i * N + j];
+ }
+
+ inline value_type& operator()(const unsigned i, const unsigned j) {
+ return this->_coord[i * N + j];
+ }
+
+ static inline unsigned rows() {
+ return M;
+ }
+
+ static inline unsigned cols() {
+ return N;
+ }
+
+ inline Matrix<T, M, N>& transpose() const {
+ Matrix<T, N, M> res;
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ res(j,i) = this->_coord[i * N + j];
+ return res;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m) {
+ if (this != &m)
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] += (T)m(i, j);
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] -= (T)m(i, j);
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator*=(const U lambda) {
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] *= lambda;
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator/=(const U lambda) {
+ if (lambda)
+ for (unsigned i = 0; i < M; i++)
+ for (unsigned j = 0; j < N; j++)
+ this->_coord[i * N + j] /= lambda;
+ return *this;
+ }
+
+ protected:
+
+ value_type _coord[_SIZE];
+ };
+
+
+ //
+ // SquareMatrix class
+ // - T: value type
+ // - N: rows & cols
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // Dirty, but icc under Windows needs this
+# define __SIZE (N * N)
+
+ template <class T, unsigned N>
+ class SquareMatrix : public Matrix<T, N, N>
+ {
+ public:
+
+ typedef T value_type;
+
+ inline SquareMatrix() : Matrix<T, N, N>() {}
+
+ template <class U>
+ explicit inline SquareMatrix(const U tab[__SIZE]) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {}
+
+ static inline SquareMatrix<T, N> identity() {
+ SquareMatrix<T, N> res;
+ for (unsigned i = 0; i < N; i++)
+ res(i, i) = 1;
+ return res;
+ }
+ };
+
+
+ //
+ // Vector external functions
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator+(const Vec<T, N>& v1,
+ // const Vec<T, N>& v2) {
+ // Vec<T, N> res(v1);
+ // res += v2;
+ // return res;
+ // }
+ //
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator-(const Vec<T, N>& v1,
+ // const Vec<T, N>& v2) {
+ // Vec<T, N> res(v1);
+ // res -= v2;
+ // return res;
+ // }
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator*(const Vec<T, N>& v,
+ // const typename Vec<T, N>::value_type r) {
+ // Vec<T, N> res(v);
+ // res *= r;
+ // return res;
+ // }
+
+ template <class T, unsigned N>
+ inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r,
+ const Vec<T, N>& v) {
+ Vec<T, N> res(v);
+ res *= r;
+ return res;
+ }
+ //
+ // template <class T, unsigned N>
+ // inline Vec<T, N> operator/(const Vec<T, N>& v,
+ // const typename Vec<T, N>::value_type r) {
+ // Vec<T, N> res(v);
+ // if (r)
+ // res /= r;
+ // return res;
+ // }
+ //
+ // dot product
+ // template <class T, unsigned N>
+ // inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1,
+ // const Vec<T, N>& v2) {
+ // typename Vec<T, N>::value_type sum = 0;
+ // for (unsigned i = 0; i < N; i++)
+ // sum += v1[i] * v2[i];
+ // return sum;
+ // }
+ //
+ // // cross product for 3D Vectors
+ // template <typename T>
+ // inline Vec3<T> operator^(const Vec<T, 3>& v1,
+ // const Vec<T, 3>& v2) {
+ // Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1],
+ // v1[2] * v2[0] - v1[0] * v2[2],
+ // v1[0] * v2[1] - v1[1] * v2[0]);
+ // return res;
+ // }
+
+ // stream operator
+ template <class T, unsigned N>
+ inline std::ostream& operator<<(std::ostream& s,
+ const Vec<T, N>& v) {
+ unsigned i;
+ s << "[";
+ for (i = 0; i < N - 1; i++)
+ s << v[i] << ", ";
+ s << v[i] << "]";
+ return s;
+ }
+
+
+ //
+ // Matrix external functions
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator+(const Matrix<T, M, N>& m1,
+ const Matrix<T, M, N>& m2) {
+ Matrix<T, M, N> res(m1);
+ res += m2;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator-(const Matrix<T, M, N>& m1,
+ const Matrix<T, M, N>& m2) {
+ Matrix<T, M, N> res(m1);
+ res -= m2;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator*(const Matrix<T, M, N>& m1,
+ const typename Matrix<T, M, N>::value_type lambda) {
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator*(const typename Matrix<T, M, N>::value_type lambda,
+ const Matrix<T, M, N>& m1) {
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Matrix<T, M, N>
+ operator/(const Matrix<T, M, N>& m1,
+ const typename Matrix<T, M, N>::value_type lambda) {
+ Matrix<T, M, N> res(m1);
+ res /= lambda;
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N, unsigned P>
+ inline Matrix<T, M, P>
+ operator*(const Matrix<T, M, N>& m1,
+ const Matrix<T, N, P>& m2) {
+ unsigned i, j, k;
+ Matrix<T, M, P> res;
+ typename Matrix<T, N, P>::value_type scale;
+
+ for (j = 0; j < P; j++) {
+ for (k = 0; k < N; k++) {
+ scale = m2(k, j);
+ for (i = 0; i < N; i++)
+ res(i, j) += m1(i, k) * scale;
+ }
+ }
+ return res;
+ }
+
+ template <class T, unsigned M, unsigned N>
+ inline Vec<T, M>
+ operator*(const Matrix<T, M, N>& m,
+ const Vec<T, N>& v) {
+
+ Vec<T, M> res;
+ typename Matrix<T, M, N>::value_type scale;
+
+ for (unsigned j = 0; j < M; j++) {
+ scale = v[j];
+ for (unsigned i = 0; i < N; i++)
+ res[i] += m(i, j) * scale;
+ }
+ return res;
+ }
+
+ // stream operator
+ template <class T, unsigned M, unsigned N>
+ inline std::ostream& operator<<(std::ostream& s,
+ const Matrix<T, M, N>& m) {
+ unsigned i, j;
+ for (i = 0; i < M; i++) {
+ s << "[";
+ for (j = 0; j < N - 1; j++)
+ s << m(i, j) << ", ";
+ s << m(i, j) << "]" << std::endl;
+ }
+ return s;
+ }
+
+} // end of namespace VecMat
+
+#endif // VECMAT_H
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp
new file mode 100755
index 00000000000..2117b06e62f
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp
@@ -0,0 +1,265 @@
+/*
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+
+
+#include "matrix_util.h"
+#include <math.h>
+
+
+
+namespace OGF {
+
+ namespace MatrixUtil {
+
+ static const double EPS = 0.00001 ;
+ static int MAX_ITER = 100 ;
+
+ void semi_definite_symmetric_eigen(
+ const double *mat, int n, double *eigen_vec, double *eigen_val
+ ) {
+ double *a,*v;
+ double a_norm,a_normEPS,thr,thr_nn;
+ int nb_iter = 0;
+ int jj;
+ int i,j,k,ij,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il,nn;
+ int *index;
+ double a_ij,a_lm,a_ll,a_mm,a_im,a_il;
+ double a_lm_2;
+ double v_ilv,v_imv;
+ double x;
+ double sinx,sinx_2,cosx,cosx_2,sincos;
+ double delta;
+
+ // Number of entries in mat
+
+ nn = (n*(n+1))/2;
+
+ // Step 1: Copy mat to a
+
+ a = new double[nn];
+
+ for( ij=0; ij<nn; ij++ ) {
+ a[ij] = mat[ij];
+ }
+
+ // Ugly Fortran-porting trick: indices for a are between 1 and n
+ a--;
+
+ // Step 2 : Init diagonalization matrix as the unit matrix
+ v = new double[n*n];
+
+ ij = 0;
+ for( i=0; i<n; i++ ) {
+ for( j=0; j<n; j++ ) {
+ if( i==j ) {
+ v[ij++] = 1.0;
+ } else {
+ v[ij++] = 0.0;
+ }
+ }
+ }
+
+ // Ugly Fortran-porting trick: indices for v are between 1 and n
+ v--;
+
+ // Step 3 : compute the weight of the non diagonal terms
+ ij = 1 ;
+ a_norm = 0.0;
+ for( i=1; i<=n; i++ ) {
+ for( j=1; j<=i; j++ ) {
+ if( i!=j ) {
+ a_ij = a[ij];
+ a_norm += a_ij*a_ij;
+ }
+ ij++;
+ }
+ }
+
+ if( a_norm != 0.0 ) {
+
+ a_normEPS = a_norm*EPS;
+ thr = a_norm ;
+
+ // Step 4 : rotations
+ while( thr > a_normEPS && nb_iter < MAX_ITER ) {
+
+ nb_iter++;
+ thr_nn = thr / nn;
+
+ for( l=1 ; l< n; l++ ) {
+ for( m=l+1; m<=n; m++ ) {
+
+ // compute sinx and cosx
+
+ lq = (l*l-l)/2;
+ mq = (m*m-m)/2;
+
+ lm = l+mq;
+ a_lm = a[lm];
+ a_lm_2 = a_lm*a_lm;
+
+ if( a_lm_2 < thr_nn ) {
+ continue ;
+ }
+
+ ll = l+lq;
+ mm = m+mq;
+ a_ll = a[ll];
+ a_mm = a[mm];
+
+ delta = a_ll - a_mm;
+
+ if( delta == 0.0 ) {
+ x = - M_PI/4 ;
+ } else {
+ x = - atan( (a_lm+a_lm) / delta ) / 2.0 ;
+ }
+
+ sinx = sin(x) ;
+ cosx = cos(x) ;
+ sinx_2 = sinx*sinx;
+ cosx_2 = cosx*cosx;
+ sincos = sinx*cosx;
+
+ // rotate L and M columns
+
+ ilv = n*(l-1);
+ imv = n*(m-1);
+
+ for( i=1; i<=n;i++ ) {
+ if( (i!=l) && (i!=m) ) {
+ iq = (i*i-i)/2;
+
+ if( i<m ) {
+ im = i + mq;
+ } else {
+ im = m + iq;
+ }
+ a_im = a[im];
+
+ if( i<l ) {
+ il = i + lq;
+ } else {
+ il = l + iq;
+ }
+ a_il = a[il];
+
+ a[il] = a_il*cosx - a_im*sinx;
+ a[im] = a_il*sinx + a_im*cosx;
+ }
+
+ ilv++;
+ imv++;
+
+ v_ilv = v[ilv];
+ v_imv = v[imv];
+
+ v[ilv] = cosx*v_ilv - sinx*v_imv;
+ v[imv] = sinx*v_ilv + cosx*v_imv;
+ }
+
+ x = a_lm*sincos; x+=x;
+
+ a[ll] = a_ll*cosx_2 + a_mm*sinx_2 - x;
+ a[mm] = a_ll*sinx_2 + a_mm*cosx_2 + x;
+ a[lm] = 0.0;
+
+ thr = fabs( thr - a_lm_2 );
+ }
+ }
+ }
+ }
+
+ // Step 5: index conversion and copy eigen values
+
+ // back from Fortran to C++
+ a++;
+
+ for( i=0; i<n; i++ ) {
+ k = i + (i*(i+1))/2;
+ eigen_val[i] = a[k];
+ }
+
+ delete[] a;
+
+ // Step 6: sort the eigen values and eigen vectors
+
+ index = new int[n];
+ for( i=0; i<n; i++ ) {
+ index[i] = i;
+ }
+
+ for( i=0; i<(n-1); i++ ) {
+ x = eigen_val[i];
+ k = i;
+
+ for( j=i+1; j<n; j++ ) {
+ if( x < eigen_val[j] ) {
+ k = j;
+ x = eigen_val[j];
+ }
+ }
+
+ eigen_val[k] = eigen_val[i];
+ eigen_val[i] = x;
+
+ jj = index[k];
+ index[k] = index[i];
+ index[i] = jj;
+ }
+
+
+ // Step 7: save the eigen vectors
+
+ v++; // back from Fortran to to C++
+
+ ij = 0;
+ for( k=0; k<n; k++ ) {
+ ik = index[k]*n;
+ for( i=0; i<n; i++ ) {
+ eigen_vec[ij++] = v[ik++];
+ }
+ }
+
+ delete[] v ;
+ delete[] index;
+ return;
+ }
+
+//_________________________________________________________
+
+ }
+}
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
new file mode 100755
index 00000000000..a990413c403
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/matrix_util.h
@@ -0,0 +1,69 @@
+/*
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+
+#ifndef __MATRIX_UTIL__
+#define __MATRIX_UTIL__
+
+# include "../system/FreestyleConfig.h"
+
+namespace OGF {
+
+ namespace MatrixUtil {
+
+ /**
+ * computes the eigen values and eigen vectors
+ * of a semi definite symmetric matrix
+ *
+ * @param matrix is stored in column symmetric storage, i.e.
+ * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
+ * size = n(n+1)/2
+ *
+ * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
+ * where vk = vk0, vk1, ..., vkn
+ * size = n^2, must be allocated by caller
+ *
+ * @param eigen_values (return) are in decreasing order
+ * size = n, must be allocated by caller
+ */
+ LIB_GEOMETRY_EXPORT
+ void semi_definite_symmetric_eigen(
+ const double *mat, int n, double *eigen_vec, double *eigen_val
+ ) ;
+
+ }
+}
+
+#endif
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
new file mode 100755
index 00000000000..b456ced8331
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
@@ -0,0 +1,103 @@
+
+//
+// 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 "normal_cycle.h"
+#include "matrix_util.h"
+
+
+namespace OGF {
+
+//_________________________________________________________
+
+
+ NormalCycle::NormalCycle() {
+ }
+
+ void NormalCycle::begin() {
+ M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0 ;
+ }
+
+ void NormalCycle::end() {
+
+ double eigen_vectors[9] ;
+ MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_) ;
+
+ axis_[0] = Vec3r(
+ eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]
+ ) ;
+
+ axis_[1] = Vec3r(
+ eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]
+ ) ;
+
+ axis_[2] = Vec3r(
+ eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]
+ ) ;
+
+ // Normalize the eigen vectors
+
+ for(int i=0; i<3; i++) {
+ axis_[i].normalize() ;
+ }
+
+ // Sort the eigen vectors
+
+ i_[0] = 0 ;
+ i_[1] = 1 ;
+ i_[2] = 2 ;
+
+ double l0 = ::fabs(eigen_value_[0]) ;
+ double l1 = ::fabs(eigen_value_[1]) ;
+ double l2 = ::fabs(eigen_value_[2]) ;
+
+ if(l1 > l0) {
+ ogf_swap(l0 , l1 ) ;
+ ogf_swap(i_[0], i_[1]) ;
+ }
+ if(l2 > l1) {
+ ogf_swap(l1 , l2 ) ;
+ ogf_swap(i_[1], i_[2]) ;
+ }
+ if(l1 > l0) {
+ ogf_swap(l0 , l1 ) ;
+ ogf_swap(i_[0],i_[1]) ;
+ }
+
+ }
+
+ void NormalCycle::accumulate_dihedral_angle(
+ const Vec3r& edge, double beta, double neigh_area
+ ) {
+ Vec3r e = edge ;
+ e.normalize() ;
+
+ double s = edge.norm() * beta * neigh_area ;
+
+ M_[0] += s * e.x() * e.x() ;
+ M_[1] += s * e.x() * e.y() ;
+ M_[2] += s * e.y() * e.y() ;
+ M_[3] += s * e.x() * e.z() ;
+ M_[4] += s * e.y() * e.z() ;
+ M_[5] += s * e.z() * e.z() ;
+ }
+
+//_________________________________________________________
+
+}
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h
new file mode 100755
index 00000000000..41fbf7b3fab
--- /dev/null
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.h
@@ -0,0 +1,97 @@
+/*
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+
+#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__
+#define __MESH_TOOLS_MATH_NORMAL_CYCLE__
+
+# include "../system/FreestyleConfig.h"
+# include "Geom.h"
+using namespace Geometry;
+
+namespace OGF {
+
+template <class T> inline void ogf_swap(T& x, T& y) {
+ T z = x ;
+ x = y ;
+ y = z ;
+ }
+
+//_________________________________________________________
+
+ /**
+ * NormalCycle evaluates the curvature tensor in function
+ * of a set of dihedral angles and associated vectors.
+ * Reference:
+ * Restricted Delaunay Triangulation and Normal Cycle,
+ * D. Cohen-Steiner and J.M. Morvan,
+ * SOCG 2003
+ */
+ class LIB_GEOMETRY_EXPORT NormalCycle {
+ public:
+ NormalCycle() ;
+ void begin() ;
+ void end() ;
+ /**
+ * Note: the specified edge vector needs to be pre-clipped
+ * by the neighborhood.
+ */
+ void accumulate_dihedral_angle(
+ const Vec3r& edge, real angle, real neigh_area = 1.0
+ ) ;
+ const Vec3r& eigen_vector(int i) const { return axis_[i_[i]] ; }
+ real eigen_value(int i) const { return eigen_value_[i_[i]] ; }
+
+ const Vec3r& N() const { return eigen_vector(2) ; }
+ const Vec3r& Kmax() const { return eigen_vector(1) ; }
+ const Vec3r& Kmin() const { return eigen_vector(0) ; }
+
+ real n() const { return eigen_value(2) ; }
+ real kmax() const { return eigen_value(1) ; }
+ real kmin() const { return eigen_value(0) ; }
+
+ private:
+ real center_[3] ;
+ Vec3r axis_[3] ;
+ real eigen_value_[3] ;
+ real M_[6] ;
+ int i_[3] ;
+ } ;
+
+//_________________________________________________________
+
+}
+
+#endif
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.cpp b/source/blender/freestyle/intern/image/GaussianFilter.cpp
new file mode 100755
index 00000000000..3a79f5f9949
--- /dev/null
+++ b/source/blender/freestyle/intern/image/GaussianFilter.cpp
@@ -0,0 +1,96 @@
+
+//
+// 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 "GaussianFilter.h"
+#include <stdlib.h>
+
+GaussianFilter::GaussianFilter(float iSigma )
+{
+ _sigma = iSigma;
+ _mask = 0;
+ computeMask();
+}
+
+GaussianFilter::GaussianFilter(const GaussianFilter& iBrother)
+{
+ _sigma = iBrother._sigma;
+ _maskSize = iBrother._maskSize;
+ _bound = iBrother._bound;
+ _storedMaskSize = iBrother._storedMaskSize;
+ _mask = new float[_maskSize*_maskSize];
+ memcpy(_mask, iBrother._mask, _maskSize*_maskSize*sizeof(float));
+}
+
+
+GaussianFilter& GaussianFilter::operator= (const GaussianFilter& iBrother)
+{
+ _sigma = iBrother._sigma;
+ _maskSize = iBrother._maskSize;
+ _bound = iBrother._bound;
+ _storedMaskSize = iBrother._storedMaskSize;
+ _mask = new float[_storedMaskSize*_storedMaskSize];
+ memcpy(_mask, iBrother._mask, _storedMaskSize*_storedMaskSize*sizeof(float));
+ return *this;
+}
+
+
+GaussianFilter::~GaussianFilter()
+{
+ if(0!=_mask)
+ {
+ delete [] _mask;
+ }
+}
+
+int GaussianFilter::computeMaskSize(float sigma)
+{
+ int maskSize = (int)floor(4*sigma)+1;
+ if(0 == maskSize%2)
+ ++maskSize;
+
+ return maskSize;
+}
+
+void GaussianFilter::setSigma(float sigma)
+{
+ _sigma = sigma;
+ computeMask();
+}
+
+void GaussianFilter::computeMask()
+{
+ if(0 != _mask){
+ delete [] _mask;
+ }
+
+ _maskSize = computeMaskSize(_sigma);
+ _storedMaskSize = (_maskSize+1)>>1;
+ _bound = _storedMaskSize-1;
+
+ float norm = _sigma*_sigma*2.f*M_PI;
+ float invNorm = 1.0/norm;
+ _mask = new float[_storedMaskSize*_storedMaskSize*sizeof(float)];
+ for(int i=0; i<_storedMaskSize; ++i)
+ for(int j=0; j<_storedMaskSize; ++j)
+ _mask[i*_storedMaskSize+j] = invNorm*exp(-(i*i + j*j)/(2.0*_sigma*_sigma));
+ //_mask[i*_storedMaskSize+j] = exp(-(i*i + j*j)/(2.0*_sigma*_sigma));
+}
+
diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h
new file mode 100755
index 00000000000..be0e3e2bada
--- /dev/null
+++ b/source/blender/freestyle/intern/image/GaussianFilter.h
@@ -0,0 +1,146 @@
+//
+// Filename : Image.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to perform gaussian filtering operations on an image
+// Date of creation : 20/05/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 GAUSSIANFILTER_H
+# define GAUSSIANFILTER_H
+
+#include <string.h> // for memcpy
+#include <cstdlib> // for abs
+#include "../system/FreestyleConfig.h"
+
+class LIB_IMAGE_EXPORT GaussianFilter{
+protected:
+ /* the mask is a symetrical 2d array (with respect
+ to the middle point).
+ Thus, M(i,j) = M(-i,j) = M(i,-j) = M(-i,-j).
+ For this reason, to represent a NxN array (N odd), we only store
+ a ((N+1)/2)x((N+1)/2) array.
+ */
+ float _sigma;
+ float *_mask;
+ int _bound;
+ int _maskSize; // the real mask size (must be odd)(the size of the mask we store is ((_maskSize+1)/2)*((_maskSize+1)/2))
+ int _storedMaskSize; //(_maskSize+1)/2)
+
+public:
+ GaussianFilter(float iSigma = 1.f) ;
+ GaussianFilter(const GaussianFilter&) ;
+ GaussianFilter& operator= (const GaussianFilter&) ;
+ virtual ~GaussianFilter() ;
+
+ /*! Returns the value for pixel x,y of image "map" after a gaussian blur,
+ * made using the sigma value.
+ * The sigma value determines the mask size (~ 2 x sigma).
+ * \param map
+ * The image we wish to work on. The Map template must implement the
+ * foloowing methods:
+ * - float pixel(unsigned int x,unsigned int y) const;
+ * - unsigned width() const;
+ * - unsigned height() const;
+ * \param x
+ * The abscissa of the pixel where we want to evaluate the gaussian blur.
+ * \param y
+ * The ordinate of the pixel where we want to evaluate the gaussian blur.
+ * \param sigma
+ * The sigma value of the gaussian function.
+ */
+ template<class Map>
+ float getSmoothedPixel(Map * map, int x, int y) ;
+
+ /*! Compute the mask size and returns the REAL mask size ((2*_maskSize)-1)
+ * This method is provided for convenience.
+ */
+ static int computeMaskSize(float sigma) ;
+
+ /*! accessors */
+ inline float sigma() const {return _sigma;}
+ inline int maskSize() const {return _maskSize;}
+ inline int getBound() {return _bound;}
+
+ /*! modifiers */
+ void setSigma(float sigma) ;
+ // void SetMaskSize(int size) {_maskSize = size;_storedMaskSize=(_maskSize+1)>>1;}
+
+
+protected:
+ void computeMask();
+};
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+
+
+#include <math.h>
+
+#ifdef __MACH__
+#define sqrtf(x) (sqrt(x))
+#endif
+
+template<class Map>
+float GaussianFilter::getSmoothedPixel(Map * map, int x, int y)
+{
+ float sum = 0.f;
+ float L=0.f;
+ int w = (int)map->width(); //soc
+ int h = (int)map->height(); //soc
+
+ // Current pixel is x,y
+ // Sum surrounding pixels L value:
+ for(int i=-_bound; i<=_bound; ++i)
+ {
+ if((y+i < 0) || (y+i >= h))
+ continue;
+ for(int j=-_bound; j<=_bound; ++j)
+ {
+ if((x+j < 0) || (x+j >= w))
+ continue;
+
+ float tmpL = map->pixel(x+j,y+i);
+ float m = _mask[abs(i)*_storedMaskSize+abs(j)];
+ L += m*tmpL;
+ sum += m;
+ }
+ }
+ //L /= sum;
+ return L;
+}
+
+
+#endif // GAUSSIANFILTER
diff --git a/source/blender/freestyle/intern/image/Image.h b/source/blender/freestyle/intern/image/Image.h
new file mode 100755
index 00000000000..72affbc1023
--- /dev/null
+++ b/source/blender/freestyle/intern/image/Image.h
@@ -0,0 +1,389 @@
+//
+// Filename : Image.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to encapsulate an array of RGB or Gray level values
+// Date of creation : 20/05/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 IMAGE_H
+# define IMAGE_H
+
+# include <string.h> // for memcpy
+
+//
+// Image base class, for all types of images
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/*! This class allows the storing of part of an image,
+ * while allowing a normal access to its pixel values.
+ * You can for example only a rectangle of sw*sh, whose
+ * lower-left corner is at (ox, oy), of an image of
+ * size w*h, and access these pixels using x,y coordinates
+ * specified in the whole image coordinate system.
+ */
+class FrsImage
+{
+ public:
+
+ /*! Default constructor */
+ FrsImage() {
+ _storedWidth = 0;
+ _storedHeight = 0;
+ _width = 0;
+ _height = 0;
+ _Ox = 0;
+ _Oy = 0;
+ }
+
+ /*! Copy constructor */
+ FrsImage(const FrsImage& brother) {
+ _storedWidth = brother._storedWidth;
+ _storedHeight = brother._storedHeight;
+ _width = brother._width;
+ _height = brother._height;
+ _Ox = brother._Ox;
+ _Oy = brother._Oy;
+ }
+
+ /*! Builds an FrsImage from its width and height.
+ * The memory is allocated consequently.
+ */
+ FrsImage(unsigned w, unsigned h) {
+ _width = w;
+ _height = h;
+ _storedWidth = w;
+ _storedHeight = h;
+ _Ox = 0;
+ _Oy = 0;
+ }
+
+ /*! Builds a partial-storing image.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the rectangle that will actually
+ * be stored.
+ * \param sh
+ * The height of the rectangle that will actually
+ * be stored.
+ * \param ox
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ * \param oy
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ */
+ FrsImage(unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) {
+ _width = w;
+ _height = h;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = ox;
+ _Oy = oy;
+ }
+
+ /*! Operator= */
+ FrsImage& operator=(const FrsImage& brother) {
+ _width = brother._width;
+ _height = brother._height;
+ _storedWidth = brother._storedWidth;
+ _storedHeight = brother._storedHeight;
+ _Ox = brother._Ox;
+ _Oy = brother._Oy;
+ return* this;
+ }
+
+ /*! Destructor */
+ virtual ~FrsImage() {}
+
+ /*! Returns the width of the complete image */
+ inline unsigned width() const {
+ return _width;
+ }
+ /*! Returns the height of the complete image */
+ inline unsigned height() const {
+ return _height;
+ }
+
+ /*! Returns the grey value for pixel x,y */
+ virtual float pixel(unsigned x, unsigned y) const = 0;
+
+ /*! Sets the array.
+ * \param array
+ * The array containing the values we wish to store.
+ * Its size is sw*sh.
+ * \param width
+ * The width of the complete image
+ * \param height
+ * The height of the complete image
+ * \param sw
+ * The width of the rectangle that will actually
+ * be stored.
+ * \param sh
+ * The height of the rectangle that will actually
+ * be stored.
+ * \param ox
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ * \param oy
+ * The x-abscissa of the origin of the rectangle that will actually
+ * be stored.
+ * \param copy
+ * If true, the array is copied, otherwise the pointer is
+ * copied
+ */
+ virtual void setArray(float* array, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) = 0;
+
+ /*! Returns the array containing the pixels values.
+ * Its size is sw*sh, i.e. potentially a smaller
+ * rectangular part of the complete image.
+ */
+ virtual float * getArray() = 0;
+
+ protected:
+
+ unsigned _width;
+ unsigned _height;
+ unsigned _storedWidth;
+ unsigned _storedHeight;
+ unsigned _Ox; // origin of the stored part
+ unsigned _Oy; // origin of the stored part
+};
+
+
+//
+// RGBImage
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class RGBImage : public FrsImage
+{
+ public:
+
+ RGBImage() : FrsImage() {
+ _rgb = 0;
+ }
+
+ RGBImage(const RGBImage& brother) : FrsImage(brother) {
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ RGBImage(unsigned w, unsigned h) : FrsImage(w, h) {
+ _rgb = new float[3 * _width * _height];
+ }
+
+ RGBImage(float* rgb, unsigned w, unsigned h) : FrsImage(w, h) {
+ _rgb = new float[3 * _width * _height];
+ memcpy(_rgb, rgb, 3 * _width * _height * sizeof(float));
+ }
+
+ /*! Builds an RGB partial image from the useful part buffer.
+ * \param rgb
+ * The array of size 3*sw*sh containing the RGB values
+ * of the sw*sh pixels we need to stored.
+ * These sw*sh pixels constitute a rectangular part of
+ * a bigger RGB image containing w*h pixels.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the part of the image we want to store and work on
+ * \param sh
+ * The height of the part of the image we want to store and work on
+ */
+ RGBImage(float* rgb, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) {
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ }
+
+ RGBImage& operator=(const RGBImage& brother) {
+ dynamic_cast<FrsImage&>(*this) = brother;
+ _rgb = new float[3 * _storedWidth * _storedHeight];
+ memcpy(_rgb, brother._rgb, 3 * _storedWidth * _storedHeight * sizeof(float));
+ return* this;
+ }
+
+ virtual ~RGBImage() {
+ if(_rgb)
+ delete[] _rgb;
+ }
+
+ inline float getR(unsigned x, unsigned y) const {
+ return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3];
+ }
+
+ inline float getG(unsigned x, unsigned y) const {
+ return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 1];
+ }
+
+ inline float getB(unsigned x, unsigned y) const {
+ return _rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3 + 2];
+ }
+
+ virtual void setPixel(unsigned x, unsigned y, float r, float g, float b){
+ float * tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]);
+ *tmp = r;++tmp;
+ *tmp = g;++tmp;
+ *tmp = b;
+ }
+
+ virtual float pixel(unsigned x, unsigned y) const {
+ float res = 0;
+ float* tmp = &(_rgb[3 * (y-_Oy) * _storedWidth + (x-_Ox) * 3]);
+ res += 11 * (*tmp++);
+ res += 16 * (*tmp++);
+ res += 5 * (*tmp);
+ return res / 32;
+ }
+
+ /*! Sets the RGB array.
+ * copy
+ * If true, the array is copied, otherwise the pointer is
+ * copied
+ */
+ virtual void setArray(float* rgb, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) {
+ _width = width;
+ _height = height;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = x;
+ _Oy = y;
+ if(!copy) {
+ _rgb = rgb;
+ return;
+ }
+
+ memcpy(_rgb, rgb, 3 * _storedWidth * _storedHeight* sizeof(float));
+ }
+
+ virtual float * getArray() {return _rgb;}
+
+ protected:
+
+ float* _rgb;
+};
+
+
+//
+// GrayImage
+//
+///////////////////////////////////////////////////////////////////////////////
+
+class GrayImage : public FrsImage
+{
+ public:
+
+ GrayImage() : FrsImage() {
+ _lvl = 0;
+ }
+
+ GrayImage(const GrayImage& brother) : FrsImage(brother) {
+ _lvl = new float[_storedWidth*_storedHeight];
+ memcpy(_lvl, brother._lvl, _storedWidth*_storedHeight*sizeof(*_lvl));
+ }
+
+ /*! Builds an empty gray image */
+ GrayImage(unsigned w, unsigned h) : FrsImage(w, h) {
+ _lvl = new float[_width*_height];
+ }
+
+ GrayImage(float* lvl, unsigned w, unsigned h) : FrsImage(w, h) {
+ _lvl = new float[_width*_height];
+ memcpy(_lvl, lvl, _width*_height*sizeof(*_lvl));
+ }
+
+ /*! Builds a partial image from the useful part buffer.
+ * \param lvl
+ * The array of size sw*sh containing the gray values
+ * of the sw*sh pixels we need to stored.
+ * These sw*sh pixels constitute a rectangular part of
+ * a bigger gray image containing w*h pixels.
+ * \param w
+ * The width of the complete image
+ * \param h
+ * The height of the complete image
+ * \param sw
+ * The width of the part of the image we want to store and work on
+ * \param sh
+ * The height of the part of the image we want to store and work on
+ */
+ GrayImage(float* lvl, unsigned w, unsigned h, unsigned sw, unsigned sh, unsigned ox, unsigned oy) : FrsImage(w, h, sw, sh, ox, oy) {
+ _lvl = new float[_storedWidth*_storedHeight];
+ memcpy(_lvl, lvl, _storedWidth*_storedHeight*sizeof(float));
+ }
+
+ GrayImage& operator=(const GrayImage& brother) {
+ dynamic_cast<FrsImage&>(*this) = brother;
+ _lvl = new float[_storedWidth * _storedHeight];
+ memcpy(_lvl, brother._lvl, _storedWidth * _storedHeight * sizeof(float));
+ return *this;
+ }
+
+ virtual ~GrayImage() {
+ if(_lvl)
+ delete[] _lvl;
+ }
+
+ inline void setPixel(unsigned x, unsigned y, float v){
+ _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)] = v;
+ }
+
+ inline float pixel(unsigned x, unsigned y) const {
+ return _lvl[(y-_Oy) * _storedWidth+ (x-_Ox)];
+ }
+
+ /*! Sets the array.
+ * copy
+ * If true, the array is copie, otherwise the pounsigneder is
+ * copied
+ */
+ void setArray(float *lvl, unsigned width, unsigned height, unsigned sw, unsigned sh, unsigned x, unsigned y, bool copy = true) {
+ _width = width;
+ _height = height;
+ _storedWidth = sw;
+ _storedHeight = sh;
+ _Ox = x;
+ _Oy = y;
+ if(!copy) {
+ _lvl = lvl;
+ return;
+ }
+
+ memcpy(_lvl, lvl, _storedWidth * _storedHeight * sizeof(float));
+ }
+ /*! Returns the array containing the gray values. */
+ virtual float * getArray() {return _lvl;}
+
+ protected:
+
+ float *_lvl;
+};
+
+#endif // IMAGE_H
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.cpp b/source/blender/freestyle/intern/image/ImagePyramid.cpp
new file mode 100755
index 00000000000..542ab7917e3
--- /dev/null
+++ b/source/blender/freestyle/intern/image/ImagePyramid.cpp
@@ -0,0 +1,166 @@
+
+//
+// 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 "ImagePyramid.h"
+#include "Image.h"
+#include "GaussianFilter.h"
+#include <iostream>
+
+using namespace std;
+
+//ImagePyramid::ImagePyramid(const GrayImage& level0, unsigned nbLevels){
+// //BuildPyramid(level0,nbLevels);
+//}
+
+ImagePyramid::ImagePyramid(const ImagePyramid& iBrother){
+ if(!_levels.empty()){
+ for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end();
+ im!=imend;
+ ++im){
+ _levels.push_back(new GrayImage(**im));
+ }
+ }
+}
+ImagePyramid::~ImagePyramid(){
+ if(!_levels.empty()){
+ for(vector<GrayImage*>::iterator im=_levels.begin(), imend=_levels.end();
+ im!=imend;
+ ++im){
+ delete (*im);
+ }
+ _levels.clear();
+ }
+}
+
+GrayImage * ImagePyramid::getLevel(int l){
+ return _levels[l];
+}
+
+float ImagePyramid::pixel(int x, int y, int level){
+ GrayImage *img = _levels[level];
+ if(0 == level){
+ return img->pixel(x,y);
+ }
+ unsigned int i = 1<<level;
+ unsigned int sx = x>>level;
+ unsigned int sy = y>>level;
+ if(sx >= img->width())
+ sx = img->width()-1;
+ if(sy >= img->height())
+ sy = img->height()-1;
+
+ // bilinear interpolation
+ float A = i*(sx+1)-x;
+ float B = x-i*sx;
+ float C = i*(sy+1)-y;
+ float D = y-i*sy;
+
+ float P1(0), P2(0);
+ P1 = A*img->pixel(sx,sy);
+ if(sx < img->width()-1){
+ if(x%i != 0)
+ P1 += B*img->pixel(sx+1,sy);
+ }else{
+ P1 += B*img->pixel(sx,sy);
+ }
+ if(sy<img->height()-1){
+ if(y%i != 0){
+ P2 = A*img->pixel(sx,sy+1);
+ if(sx < img->width()-1){
+ if(x%i != 0)
+ P2 += B*img->pixel(sx+1,sy+1);
+ }else{
+ P2 += B*img->pixel(sx,sy+1);
+ }
+ }
+ }else{
+ P2 = P1;
+ }
+ return (1.f/(float)(1<<2*level))*(C*P1 + D*P2);
+}
+
+int ImagePyramid::width(int level){
+ return _levels[level]->width();
+}
+
+int ImagePyramid::height(int level){
+ return _levels[level]->height();
+}
+
+GaussianPyramid::GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma)
+ : ImagePyramid()
+{
+ _sigma = iSigma;
+ BuildPyramid(level0,nbLevels);
+}
+GaussianPyramid::GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma)
+ : ImagePyramid()
+{
+ _sigma = iSigma;
+ BuildPyramid(level0,nbLevels);
+}
+
+GaussianPyramid::GaussianPyramid(const GaussianPyramid& iBrother)
+: ImagePyramid(iBrother){
+ _sigma = iBrother._sigma;
+}
+void GaussianPyramid::BuildPyramid(const GrayImage& level0, unsigned nbLevels){
+ GrayImage *pLevel = new GrayImage(level0);
+ BuildPyramid(pLevel, nbLevels);
+}
+
+void GaussianPyramid::BuildPyramid(GrayImage* level0, unsigned nbLevels){
+ GrayImage *pLevel = level0;
+ _levels.push_back(pLevel);
+ GaussianFilter gf(_sigma);
+ // build the nbLevels:
+ unsigned w = pLevel->width();
+ unsigned h = pLevel->height();
+ if(nbLevels!=0)
+ {
+ for(unsigned i=0; i<nbLevels; ++i){ //soc
+ w = pLevel->width()>>1;
+ h = pLevel->height()>>1;
+ GrayImage *img = new GrayImage(w,h);
+ for(unsigned y=0; y<h; ++y){
+ for(unsigned x=0; x<w; ++x){
+ float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y);
+ img->setPixel(x,y,v);
+ }
+ }
+ _levels.push_back(img);
+ pLevel = img;
+ }
+ }else{
+ while((w>1) && (h>1)){
+ w = pLevel->width()>>1;
+ h = pLevel->height()>>1;
+ GrayImage *img = new GrayImage(w,h);
+ for(unsigned y=0; y<h; ++y){
+ for(unsigned x=0; x<w; ++x){
+ float v = gf.getSmoothedPixel<GrayImage>(pLevel, 2*x,2*y);
+ img->setPixel(x,y,v);
+ }
+ }
+ _levels.push_back(img);
+ pLevel = img;
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/image/ImagePyramid.h b/source/blender/freestyle/intern/image/ImagePyramid.h
new file mode 100755
index 00000000000..9e326757f02
--- /dev/null
+++ b/source/blender/freestyle/intern/image/ImagePyramid.h
@@ -0,0 +1,92 @@
+//
+// Filename : ImagePyramid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a pyramid of images
+// Date of creation : 25/12/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 IMAGEPYRAMID_H
+# define IMAGEPYRAMID_H
+
+#include "../system/FreestyleConfig.h"
+#include <vector>
+
+class GrayImage;
+class LIB_IMAGE_EXPORT ImagePyramid{
+protected:
+ std::vector<GrayImage*> _levels;
+
+public:
+ ImagePyramid(){}
+ ImagePyramid(const ImagePyramid& iBrother);
+ //ImagePyramid(const GrayImage& level0, unsigned nbLevels);
+ virtual ~ImagePyramid();
+
+ /*! Builds the pyramid.
+ * must be overloaded by inherited classes.
+ * if nbLevels==0, the complete pyramid is built
+ */
+ virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels) = 0;
+
+ /*! Builds a pyramid without copying the base level */
+ virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels) = 0;
+
+ virtual GrayImage * getLevel(int l);
+ /*! Returns the pixel x,y using bilinear interpolation.
+ * \param x
+ * the abscissa specified in the finest level coordinate system
+ * \param y
+ * the ordinate specified in the finest level coordinate system
+ * \param level
+ * the level from which we want the pixel to be evaluated
+ */
+ virtual float pixel(int x, int y, int level=0);
+ /*! Returns the width of the level-th level image */
+ virtual int width(int level=0);
+ /*! Returns the height of the level-th level image */
+ virtual int height(int level=0);
+ /*! Returns the number of levels in the pyramid */
+ inline int getNumberOfLevels() const { return _levels.size();}
+};
+
+class LIB_IMAGE_EXPORT GaussianPyramid : public ImagePyramid
+{
+protected:
+ float _sigma;
+public:
+ GaussianPyramid(float iSigma=1.f) : ImagePyramid() {_sigma=iSigma;}
+ GaussianPyramid(const GrayImage& level0, unsigned nbLevels, float iSigma=1.f);
+ GaussianPyramid(GrayImage* level0, unsigned nbLevels, float iSigma=1.f);
+ GaussianPyramid(const GaussianPyramid& iBrother);
+ virtual ~GaussianPyramid(){}
+
+ virtual void BuildPyramid(const GrayImage& level0, unsigned nbLevels);
+ virtual void BuildPyramid(GrayImage* level0, unsigned nbLevels);
+ /* accessors */
+ inline float getSigma() const {return _sigma;}
+ /* modifiers */
+
+};
+#endif // IMAGEPYRAMID_H
diff --git a/source/blender/freestyle/intern/python/BPy_BBox.cpp b/source/blender/freestyle/intern/python/BPy_BBox.cpp
new file mode 100644
index 00000000000..0acd32bad58
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BBox.cpp
@@ -0,0 +1,100 @@
+#include "BPy_BBox.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BBox_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &BBox_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &BBox_Type );
+ PyModule_AddObject(module, "BBox", (PyObject *)&BBox_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BBox___doc__[] =
+"Class for representing a bounding box.\n";
+
+static int BBox___init__(BPy_BBox *self, PyObject *args, PyObject *kwds)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->bb = new BBox< Vec3r>();
+ return 0;
+}
+
+static void BBox___dealloc__(BPy_BBox* self)
+{
+ delete self->bb;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * BBox___repr__(BPy_BBox* self)
+{
+ return PyUnicode_FromFormat("BBox - address: %p", self->bb );
+}
+
+/*----------------------BBox instance definitions ----------------------------*/
+static PyMethodDef BPy_BBox_methods[] = {
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_BBox type definition ------------------------------*/
+
+PyTypeObject BBox_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BBox", /* tp_name */
+ sizeof(BPy_BBox), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BBox___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BBox___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BBox___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_BBox_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BBox___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BBox.h b/source/blender/freestyle/intern/python/BPy_BBox.h
new file mode 100644
index 00000000000..f8282187da0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BBox.h
@@ -0,0 +1,38 @@
+#ifndef FREESTYLE_PYTHON_BBOX_H
+#define FREESTYLE_PYTHON_BBOX_H
+
+#include <Python.h>
+
+#include "../geometry/BBox.h"
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BBox_Type;
+
+#define BPy_BBox_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BBox_Type) )
+
+/*---------------------------Python BPy_BBox structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BBox<Vec3r> *bb;
+} BPy_BBox;
+
+/*---------------------------Python BPy_BBox visible prototypes-----------*/
+
+int BBox_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BBOX_H */
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
new file mode 100644
index 00000000000..4bc8a0cb8bb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp
@@ -0,0 +1,166 @@
+#include "BPy_BinaryPredicate0D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BinaryPredicate0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &BinaryPredicate0D_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &BinaryPredicate0D_Type );
+ PyModule_AddObject(module, "BinaryPredicate0D", (PyObject *)&BinaryPredicate0D_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BinaryPredicate0D___doc__[] =
+"Base class for binary predicates working on :class:`Interface0D`\n"
+"objects. A BinaryPredicate0D is typically an ordering relation\n"
+"between two Interface0D objects. The predicate evaluates a relation\n"
+"between the two Interface0D instances and returns a boolean value (true\n"
+"or false). It is used by invoking the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Must be overload by inherited classes. It evaluates a relation\n"
+" between two Interface0D objects.\n"
+"\n"
+" :arg inter1: The first Interface0D object.\n"
+" :type inter1: :class:`Interface0D`\n"
+" :arg inter2: The second Interface0D object.\n"
+" :type inter2: :class:`Interface0D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int BinaryPredicate0D___init__(BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->bp0D = new BinaryPredicate0D();
+ self->bp0D->py_bp0D = (PyObject *) self;
+
+ return 0;
+}
+
+static void BinaryPredicate0D___dealloc__(BPy_BinaryPredicate0D* self)
+{
+ if (self->bp0D)
+ delete self->bp0D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * BinaryPredicate0D___repr__(BPy_BinaryPredicate0D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->bp0D->getName().c_str(), self->bp0D );
+}
+
+static char BinaryPredicate0D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the binary 0D predicate.\n"
+"\n"
+" :return: The name of the binary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * BinaryPredicate0D_getName( BPy_BinaryPredicate0D *self, PyObject *args)
+{
+ return PyUnicode_FromFormat( self->bp0D->getName().c_str() );
+}
+
+static PyObject * BinaryPredicate0D___call__( BPy_BinaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ BPy_Interface0D *obj1, *obj2;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!O!", &Interface0D_Type, &obj1, &Interface0D_Type, &obj2) )
+ return NULL;
+
+ if( typeid(*(self->bp0D)) == typeid(BinaryPredicate0D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->bp0D->operator()( *(obj1->if0D) , *(obj2->if0D) ) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->bp0D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->bp0D->result );
+
+}
+
+/*----------------------BinaryPredicate0D instance definitions ----------------------------*/
+static PyMethodDef BPy_BinaryPredicate0D_methods[] = {
+ {"getName", ( PyCFunction ) BinaryPredicate0D_getName, METH_NOARGS, BinaryPredicate0D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_BinaryPredicate0D type definition ------------------------------*/
+
+PyTypeObject BinaryPredicate0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BinaryPredicate0D", /* tp_name */
+ sizeof(BPy_BinaryPredicate0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BinaryPredicate0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BinaryPredicate0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)BinaryPredicate0D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BinaryPredicate0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_BinaryPredicate0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BinaryPredicate0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h
new file mode 100644
index 00000000000..6a9a0775608
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_BINARYPREDICATE0D_H
+#define FREESTYLE_PYTHON_BINARYPREDICATE0D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BinaryPredicate0D_Type;
+
+#define BPy_BinaryPredicate0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BinaryPredicate0D_Type) )
+
+/*---------------------------Python BPy_BinaryPredicate0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BinaryPredicate0D *bp0D;
+} BPy_BinaryPredicate0D;
+
+/*---------------------------Python BPy_BinaryPredicate0D visible prototypes-----------*/
+
+int BinaryPredicate0D_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BINARYPREDICATE0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
new file mode 100644
index 00000000000..30c63e73630
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp
@@ -0,0 +1,193 @@
+#include "BPy_BinaryPredicate1D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface1D.h"
+
+#include "BinaryPredicate1D/BPy_FalseBP1D.h"
+#include "BinaryPredicate1D/BPy_Length2DBP1D.h"
+#include "BinaryPredicate1D/BPy_SameShapeIdBP1D.h"
+#include "BinaryPredicate1D/BPy_TrueBP1D.h"
+#include "BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int BinaryPredicate1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &BinaryPredicate1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &BinaryPredicate1D_Type );
+ PyModule_AddObject(module, "BinaryPredicate1D", (PyObject *)&BinaryPredicate1D_Type);
+
+ if( PyType_Ready( &FalseBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FalseBP1D_Type );
+ PyModule_AddObject(module, "FalseBP1D", (PyObject *)&FalseBP1D_Type);
+
+ if( PyType_Ready( &Length2DBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Length2DBP1D_Type );
+ PyModule_AddObject(module, "Length2DBP1D", (PyObject *)&Length2DBP1D_Type);
+
+ if( PyType_Ready( &SameShapeIdBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SameShapeIdBP1D_Type );
+ PyModule_AddObject(module, "SameShapeIdBP1D", (PyObject *)&SameShapeIdBP1D_Type);
+
+ if( PyType_Ready( &TrueBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TrueBP1D_Type );
+ PyModule_AddObject(module, "TrueBP1D", (PyObject *)&TrueBP1D_Type);
+
+ if( PyType_Ready( &ViewMapGradientNormBP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewMapGradientNormBP1D_Type );
+ PyModule_AddObject(module, "ViewMapGradientNormBP1D", (PyObject *)&ViewMapGradientNormBP1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BinaryPredicate1D___doc__[] =
+"Base class for binary predicates working on :class:`Interface1D`\n"
+"objects. A BinaryPredicate1D is typically an ordering relation\n"
+"between two Interface1D objects. The predicate evaluates a relation\n"
+"between the two Interface1D instances and returns a boolean value (true\n"
+"or false). It is used by invoking the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Must be overload by inherited classes. It evaluates a relation\n"
+" between two Interface1D objects.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int BinaryPredicate1D___init__(BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->bp1D = new BinaryPredicate1D();
+ self->bp1D->py_bp1D = (PyObject *) self;
+ return 0;
+}
+
+static void BinaryPredicate1D___dealloc__(BPy_BinaryPredicate1D* self)
+{
+ if (self->bp1D)
+ delete self->bp1D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * BinaryPredicate1D___repr__(BPy_BinaryPredicate1D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->bp1D->getName().c_str(), self->bp1D );
+}
+
+static char BinaryPredicate1D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the binary 1D predicate.\n"
+"\n"
+" :return: The name of the binary 1D predicate.\n"
+" :rtype: string\n";
+
+static PyObject *BinaryPredicate1D_getName( BPy_BinaryPredicate1D *self, PyObject *args)
+{
+ return PyUnicode_FromFormat( self->bp1D->getName().c_str() );
+}
+
+static PyObject *BinaryPredicate1D___call__( BPy_BinaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ BPy_Interface1D *obj1, *obj2;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!O!", &Interface1D_Type, &obj1, &Interface1D_Type, &obj2) )
+ return NULL;
+
+ if( typeid(*(self->bp1D)) == typeid(BinaryPredicate1D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->bp1D->operator()( *(obj1->if1D) , *(obj2->if1D) ) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->bp1D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->bp1D->result );
+}
+
+/*----------------------BinaryPredicate1D instance definitions ----------------------------*/
+static PyMethodDef BPy_BinaryPredicate1D_methods[] = {
+ {"getName", ( PyCFunction ) BinaryPredicate1D_getName, METH_NOARGS, BinaryPredicate1D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_BinaryPredicate1D type definition ------------------------------*/
+PyTypeObject BinaryPredicate1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BinaryPredicate1D", /* tp_name */
+ sizeof(BPy_BinaryPredicate1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)BinaryPredicate1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)BinaryPredicate1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)BinaryPredicate1D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BinaryPredicate1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_BinaryPredicate1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BinaryPredicate1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h
new file mode 100644
index 00000000000..5a993f84f5b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_BINARYPREDICATE1D_H
+#define FREESTYLE_PYTHON_BINARYPREDICATE1D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject BinaryPredicate1D_Type;
+
+#define BPy_BinaryPredicate1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BinaryPredicate1D_Type) )
+
+/*---------------------------Python BPy_BinaryPredicate1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ BinaryPredicate1D *bp1D;
+} BPy_BinaryPredicate1D;
+
+/*---------------------------Python BPy_BinaryPredicate1D visible prototypes-----------*/
+
+int BinaryPredicate1D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BINARYPREDICATE1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
new file mode 100644
index 00000000000..1d290b486f9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.cpp
@@ -0,0 +1,262 @@
+#include "BPy_ContextFunctions.h"
+#include "BPy_Convert.h"
+
+#include "../stroke/ContextFunctions.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+static char ContextFunctions_GetTimeStampCF___doc__[] =
+".. function:: GetTimeStampCF()\n"
+"\n"
+" Returns the system time stamp.\n"
+"\n"
+" :return: The system time stamp.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_GetTimeStampCF( PyObject* self )
+{
+ return PyLong_FromLong( ContextFunctions::GetTimeStampCF() );
+}
+
+static char ContextFunctions_GetCanvasWidthCF___doc__[] =
+".. method:: GetCanvasWidthCF()\n"
+"\n"
+" Returns the canvas width.\n"
+"\n"
+" :return: The canvas width.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_GetCanvasWidthCF( PyObject* self )
+{
+ return PyLong_FromLong( ContextFunctions::GetCanvasWidthCF() );
+}
+
+static char ContextFunctions_GetCanvasHeightCF___doc__[] =
+".. method:: GetCanvasHeightCF()\n"
+"\n"
+" Returns the canvas height.\n"
+"\n"
+" :return: The canvas height.\n"
+" :rtype: int\n";
+
+static PyObject *
+ContextFunctions_GetCanvasHeightCF( PyObject* self )
+{
+ return PyLong_FromLong( ContextFunctions::GetCanvasHeightCF() );
+}
+
+static char ContextFunctions_LoadMapCF___doc__[] =
+".. function:: LoadMapCF(iFileName, iMapName, iNbLevels=4, iSigma=1.0)\n"
+"\n"
+" Loads an image map for further reading.\n"
+"\n"
+" :arg iFileName: The name of the image file.\n"
+" :type iFileName: string\n"
+" :arg iMapName: The name that will be used to access this image.\n"
+" :type iMapName: string\n"
+" :arg iNbLevels: The number of levels in the map pyramid\n"
+" (default = 4). If iNbLevels == 0, the complete pyramid is\n"
+" built.\n"
+" :type iNbLevels: int\n"
+" :arg iSigma: The sigma value of the gaussian function.\n"
+" :type iSigma: float\n";
+
+static PyObject *
+ContextFunctions_LoadMapCF( PyObject *self, PyObject *args )
+{
+ char *fileName, *mapName;
+ unsigned nbLevels;
+ float sigma;
+
+ if( !PyArg_ParseTuple(args, "ssIf", &fileName, &mapName, &nbLevels, &sigma) )
+ return NULL;
+
+ ContextFunctions::LoadMapCF(fileName, mapName, nbLevels, sigma);
+
+ Py_RETURN_NONE;
+}
+
+static char ContextFunctions_ReadMapPixelCF___doc__[] =
+".. function:: ReadMapPixelCF(iMapName, level, x, y)\n"
+"\n"
+" Reads a pixel in a user-defined map.\n"
+"\n"
+" :arg iMapName: The name of the map.\n"
+" :type iMapName: string\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_ReadMapPixelCF( PyObject *self, PyObject *args )
+{
+ char *mapName;
+ int level;
+ unsigned x, y;
+
+ if( !PyArg_ParseTuple(args, "siII", &mapName, &level, &x, &y) )
+ return NULL;
+
+ float f = ContextFunctions::ReadMapPixelCF(mapName, level, x, y);
+
+ return PyFloat_FromDouble( f );
+}
+
+static char ContextFunctions_ReadCompleteViewMapPixelCF___doc__[] =
+".. function:: ReadCompleteViewMapPixelCF(level, x, y)\n"
+"\n"
+" Reads a pixel in the complete view map.\n"
+"\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_ReadCompleteViewMapPixelCF( PyObject *self, PyObject *args )
+{
+ int level;
+ unsigned x, y;
+
+ if( !PyArg_ParseTuple(args, "iII", &level, &x, &y) )
+ return NULL;
+
+ float f = ContextFunctions::ReadCompleteViewMapPixelCF(level, x, y);
+
+ return PyFloat_FromDouble( f );
+}
+
+static char ContextFunctions_ReadDirectionalViewMapPixelCF___doc__[] =
+".. function:: ReadDirectionalViewMapPixelCF(iOrientation, level, x, y)\n"
+"\n"
+" Reads a pixel in one of the oriented view map images.\n"
+"\n"
+" :arg iOrientation: The number telling which orientation we want to\n"
+" check.\n"
+" :type iOrientation: int\n"
+" :arg level: The level of the pyramid in which we wish to read the\n"
+" pixel.\n"
+" :type level: int\n"
+" :arg x: The x coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type x: int\n"
+" :arg y: The y coordinate of the pixel we wish to read. The origin\n"
+" is in the lower-left corner.\n"
+" :type y: int\n"
+" :return: The floating-point value stored for that pixel.\n"
+" :rtype: float\n";
+
+static PyObject *
+ContextFunctions_ReadDirectionalViewMapPixelCF( PyObject *self, PyObject *args )
+{
+ int orientation, level;
+ unsigned x, y;
+
+ if( !PyArg_ParseTuple(args, "iiII", &orientation, &level, &x, &y) )
+ return NULL;
+
+ float f = ContextFunctions::ReadDirectionalViewMapPixelCF(orientation, level, x, y);
+
+ return PyFloat_FromDouble( f );
+}
+
+static char ContextFunctions_GetSelectedFEdgeCF___doc__[] =
+".. function:: GetSelectedFEdgeCF()\n"
+"\n"
+" Returns the selected FEdge.\n"
+"\n"
+" :return: The selected FEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject *
+ContextFunctions_GetSelectedFEdgeCF( PyObject *self )
+{
+ FEdge *fe = ContextFunctions::GetSelectedFEdgeCF();
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+/*-----------------------ContextFunctions module docstring-------------------------------*/
+
+static char module_docstring[] = "The Blender Freestyle.ContextFunctions submodule\n\n";
+
+/*-----------------------ContextFunctions module functions definitions-------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"GetTimeStampCF", (PyCFunction)ContextFunctions_GetTimeStampCF, METH_NOARGS, ContextFunctions_GetTimeStampCF___doc__},
+ {"GetCanvasWidthCF", (PyCFunction)ContextFunctions_GetCanvasWidthCF, METH_NOARGS, ContextFunctions_GetCanvasWidthCF___doc__},
+ {"GetCanvasHeightCF", (PyCFunction)ContextFunctions_GetCanvasHeightCF, METH_NOARGS, ContextFunctions_GetCanvasHeightCF___doc__},
+ {"LoadMapCF", (PyCFunction)ContextFunctions_LoadMapCF, METH_VARARGS, ContextFunctions_LoadMapCF___doc__},
+ {"ReadMapPixelCF", (PyCFunction)ContextFunctions_ReadMapPixelCF, METH_VARARGS, ContextFunctions_ReadMapPixelCF___doc__},
+ {"ReadCompleteViewMapPixelCF", (PyCFunction)ContextFunctions_ReadCompleteViewMapPixelCF, METH_VARARGS, ContextFunctions_ReadCompleteViewMapPixelCF___doc__},
+ {"ReadDirectionalViewMapPixelCF", (PyCFunction)ContextFunctions_ReadDirectionalViewMapPixelCF, METH_VARARGS, ContextFunctions_ReadDirectionalViewMapPixelCF___doc__},
+ {"GetSelectedFEdgeCF", (PyCFunction)ContextFunctions_GetSelectedFEdgeCF, METH_NOARGS, ContextFunctions_GetSelectedFEdgeCF___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------ContextFunctions module definition--------------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle.ContextFunctions",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+//------------------- MODULE INITIALIZATION --------------------------------
+
+int ContextFunctions_Init( PyObject *module )
+{
+ PyObject *m, *d, *f;
+
+ if( module == NULL )
+ return -1;
+
+ m = PyModule_Create(&module_definition);
+ if (m == NULL)
+ return -1;
+ Py_INCREF(m);
+ PyModule_AddObject(module, "ContextFunctions", m);
+
+ // from ContextFunctions import *
+ d = PyModule_GetDict(m);
+ for (PyMethodDef *p = module_functions; p->ml_name; p++) {
+ f = PyDict_GetItemString(d, p->ml_name);
+ Py_INCREF(f);
+ PyModule_AddObject(module, p->ml_name, f);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ContextFunctions.h b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h
new file mode 100644
index 00000000000..fafeff3e974
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ContextFunctions.h
@@ -0,0 +1,18 @@
+#ifndef FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H
+#define FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------Python BPy_ContextFunctions visible prototypes-----------*/
+
+int ContextFunctions_Init( PyObject *module );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CONTEXTFUNCTIONS_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp
new file mode 100644
index 00000000000..e3f979fea8f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp
@@ -0,0 +1,609 @@
+#include "BPy_Convert.h"
+
+#include "BPy_BBox.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_Id.h"
+#include "BPy_IntegrationType.h"
+#include "BPy_Interface0D.h"
+#include "Interface0D/BPy_CurvePoint.h"
+#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
+#include "Interface0D/ViewVertex/BPy_TVertex.h"
+#include "BPy_Interface1D.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "Interface1D/Curve/BPy_Chain.h"
+#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
+#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
+#include "BPy_Nature.h"
+#include "BPy_MediumType.h"
+#include "BPy_SShape.h"
+#include "BPy_StrokeAttribute.h"
+#include "BPy_ViewShape.h"
+
+#include "Iterator/BPy_AdjacencyIterator.h"
+#include "Iterator/BPy_ChainPredicateIterator.h"
+#include "Iterator/BPy_ChainSilhouetteIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_CurvePointIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Iterator/BPy_SVertexIterator.h"
+#include "Iterator/BPy_StrokeVertexIterator.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_orientedViewEdgeIterator.h"
+
+#include "../stroke/StrokeRep.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//==============================
+// C++ => Python
+//==============================
+
+
+PyObject * PyBool_from_bool( bool b ){
+ return PyBool_FromLong( b ? 1 : 0);
+}
+
+
+PyObject * Vector_from_Vec2f( Vec2f& vec ) {
+ float vec_data[2]; // because vec->_coord is protected
+
+ vec_data[0] = vec.x(); vec_data[1] = vec.y();
+ return newVectorObject( vec_data, 2, Py_NEW, NULL);
+}
+
+PyObject * Vector_from_Vec3f( Vec3f& vec ) {
+ float vec_data[3]; // because vec->_coord is protected
+
+ vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z();
+ return newVectorObject( vec_data, 3, Py_NEW, NULL);
+}
+
+PyObject * Vector_from_Vec3r( Vec3r& vec ) {
+ float vec_data[3]; // because vec->_coord is protected
+
+ vec_data[0] = vec.x(); vec_data[1] = vec.y(); vec_data[2] = vec.z();
+ return newVectorObject( vec_data, 3, Py_NEW, NULL);
+}
+
+PyObject * BPy_Id_from_Id( Id& id ) {
+ PyObject *py_id = Id_Type.tp_new( &Id_Type, 0, 0 );
+ ((BPy_Id *) py_id)->id = new Id( id.getFirst(), id.getSecond() );
+
+ return py_id;
+}
+
+PyObject * Any_BPy_Interface0D_from_Interface0D( Interface0D& if0D ) {
+ if (typeid(if0D) == typeid(CurvePoint)) {
+ return BPy_CurvePoint_from_CurvePoint(dynamic_cast<CurvePoint&>(if0D));
+ } else if (typeid(if0D) == typeid(StrokeVertex)) {
+ return BPy_StrokeVertex_from_StrokeVertex(dynamic_cast<StrokeVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(SVertex)) {
+ return BPy_SVertex_from_SVertex(dynamic_cast<SVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(ViewVertex)) {
+ return BPy_ViewVertex_from_ViewVertex(dynamic_cast<ViewVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(NonTVertex)) {
+ return BPy_NonTVertex_from_NonTVertex(dynamic_cast<NonTVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(TVertex)) {
+ return BPy_TVertex_from_TVertex(dynamic_cast<TVertex&>(if0D));
+ } else if (typeid(if0D) == typeid(Interface0D)) {
+ return BPy_Interface0D_from_Interface0D(if0D);
+ }
+ string msg("unexpected type: " + if0D.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * Any_BPy_Interface1D_from_Interface1D( Interface1D& if1D ) {
+ if (typeid(if1D) == typeid(ViewEdge)) {
+ return BPy_ViewEdge_from_ViewEdge(dynamic_cast<ViewEdge&>(if1D));
+ } else if (typeid(if1D) == typeid(Chain)) {
+ return BPy_Chain_from_Chain(dynamic_cast<Chain&>(if1D));
+ } else if (typeid(if1D) == typeid(Stroke)) {
+ return BPy_Stroke_from_Stroke(dynamic_cast<Stroke&>(if1D));
+ } else if (typeid(if1D) == typeid(FEdgeSharp)) {
+ return BPy_FEdgeSharp_from_FEdgeSharp(dynamic_cast<FEdgeSharp&>(if1D));
+ } else if (typeid(if1D) == typeid(FEdgeSmooth)) {
+ return BPy_FEdgeSmooth_from_FEdgeSmooth(dynamic_cast<FEdgeSmooth&>(if1D));
+ } else if (typeid(if1D) == typeid(FEdge)) {
+ return BPy_FEdge_from_FEdge(dynamic_cast<FEdge&>(if1D));
+ } else if (typeid(if1D) == typeid(Interface1D)) {
+ return BPy_Interface1D_from_Interface1D( if1D );
+ }
+ string msg("unexpected type: " + if1D.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * Any_BPy_FEdge_from_FEdge( FEdge& fe ) {
+ if (typeid(fe) == typeid(FEdgeSharp)) {
+ return BPy_FEdgeSharp_from_FEdgeSharp( dynamic_cast<FEdgeSharp&>(fe) );
+ } else if (typeid(fe) == typeid(FEdgeSmooth)) {
+ return BPy_FEdgeSmooth_from_FEdgeSmooth( dynamic_cast<FEdgeSmooth&>(fe) );
+ } else if (typeid(fe) == typeid(FEdge)) {
+ return BPy_FEdge_from_FEdge( fe );
+ }
+ string msg("unexpected type: " + fe.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * Any_BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ) {
+ if (typeid(vv) == typeid(NonTVertex)) {
+ return BPy_NonTVertex_from_NonTVertex( dynamic_cast<NonTVertex&>(vv) );
+ } else if (typeid(vv) == typeid(TVertex)) {
+ return BPy_TVertex_from_TVertex( dynamic_cast<TVertex&>(vv) );
+ } else if (typeid(vv) == typeid(ViewVertex)) {
+ return BPy_ViewVertex_from_ViewVertex( vv );
+ }
+ string msg("unexpected type: " + vv.getExactTypeName());
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+}
+
+PyObject * BPy_Interface0D_from_Interface0D( Interface0D& if0D ) {
+ PyObject *py_if0D = Interface0D_Type.tp_new( &Interface0D_Type, 0, 0 );
+ ((BPy_Interface0D *) py_if0D)->if0D = &if0D;
+ ((BPy_Interface0D *) py_if0D)->borrowed = 1;
+
+ return py_if0D;
+}
+
+PyObject * BPy_Interface1D_from_Interface1D( Interface1D& if1D ) {
+ PyObject *py_if1D = Interface1D_Type.tp_new( &Interface1D_Type, 0, 0 );
+ ((BPy_Interface1D *) py_if1D)->if1D = &if1D;
+ ((BPy_Interface1D *) py_if1D)->borrowed = 1;
+
+ return py_if1D;
+}
+
+PyObject * BPy_SVertex_from_SVertex( SVertex& sv ) {
+ PyObject *py_sv = SVertex_Type.tp_new( &SVertex_Type, 0, 0 );
+ ((BPy_SVertex *) py_sv)->sv = &sv;
+ ((BPy_SVertex *) py_sv)->py_if0D.if0D = ((BPy_SVertex *) py_sv)->sv;
+ ((BPy_SVertex *) py_sv)->py_if0D.borrowed = 1;
+
+ return py_sv;
+}
+
+PyObject * BPy_FEdgeSharp_from_FEdgeSharp( FEdgeSharp& fes ) {
+ PyObject *py_fe = FEdgeSharp_Type.tp_new( &FEdgeSharp_Type, 0, 0 );
+ ((BPy_FEdgeSharp *) py_fe)->fes = &fes;
+ ((BPy_FEdgeSharp *) py_fe)->py_fe.fe = ((BPy_FEdgeSharp *) py_fe)->fes;
+ ((BPy_FEdgeSharp *) py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSharp *) py_fe)->fes;
+ ((BPy_FEdgeSharp *) py_fe)->py_fe.py_if1D.borrowed = 1;
+
+ return py_fe;
+}
+
+PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth( FEdgeSmooth& fes ) {
+ PyObject *py_fe = FEdgeSmooth_Type.tp_new( &FEdgeSmooth_Type, 0, 0 );
+ ((BPy_FEdgeSmooth *) py_fe)->fes = &fes;
+ ((BPy_FEdgeSmooth *) py_fe)->py_fe.fe = ((BPy_FEdgeSmooth *) py_fe)->fes;
+ ((BPy_FEdgeSmooth *) py_fe)->py_fe.py_if1D.if1D = ((BPy_FEdgeSmooth *) py_fe)->fes;
+ ((BPy_FEdgeSmooth *) py_fe)->py_fe.py_if1D.borrowed = 1;
+
+ return py_fe;
+}
+
+PyObject * BPy_FEdge_from_FEdge( FEdge& fe ) {
+ PyObject *py_fe = FEdge_Type.tp_new( &FEdge_Type, 0, 0 );
+ ((BPy_FEdge *) py_fe)->fe = &fe;
+ ((BPy_FEdge *) py_fe)->py_if1D.if1D = ((BPy_FEdge *) py_fe)->fe;
+ ((BPy_FEdge *) py_fe)->py_if1D.borrowed = 1;
+
+ return py_fe;
+}
+
+PyObject * BPy_Nature_from_Nature( unsigned short n ) {
+ PyObject *py_n;
+
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SetItem( args, 0, PyLong_FromLong(n) );
+ py_n = Nature_Type.tp_new(&Nature_Type, args, NULL);
+ Py_DECREF(args);
+
+ return py_n;
+}
+
+PyObject * BPy_Stroke_from_Stroke( Stroke& s ) {
+ PyObject *py_s = Stroke_Type.tp_new( &Stroke_Type, 0, 0 );
+ ((BPy_Stroke *) py_s)->s = &s;
+ ((BPy_Stroke *) py_s)->py_if1D.if1D = ((BPy_Stroke *) py_s)->s;
+ ((BPy_Stroke *) py_s)->py_if1D.borrowed = 1;
+
+ return py_s;
+}
+
+PyObject * BPy_StrokeAttribute_from_StrokeAttribute( StrokeAttribute& sa ) {
+ PyObject *py_sa = StrokeAttribute_Type.tp_new( &StrokeAttribute_Type, 0, 0 );
+ ((BPy_StrokeAttribute *) py_sa)->sa = &sa;
+ ((BPy_StrokeAttribute *) py_sa)->borrowed = 1;
+ return py_sa;
+}
+
+PyObject * BPy_MediumType_from_MediumType( Stroke::MediumType n ) {
+ PyObject *py_mt;
+
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SetItem( args, 0, PyLong_FromLong(n) );
+ py_mt = MediumType_Type.tp_new( &MediumType_Type, args, NULL );
+ Py_DECREF(args);
+
+ return py_mt;
+}
+
+PyObject * BPy_StrokeVertex_from_StrokeVertex( StrokeVertex& sv ) {
+ PyObject *py_sv = StrokeVertex_Type.tp_new( &StrokeVertex_Type, 0, 0 );
+ ((BPy_StrokeVertex *) py_sv)->sv = &sv;
+ ((BPy_StrokeVertex *) py_sv)->py_cp.cp = ((BPy_StrokeVertex *) py_sv)->sv;
+ ((BPy_StrokeVertex *) py_sv)->py_cp.py_if0D.if0D = ((BPy_StrokeVertex *) py_sv)->sv;
+ ((BPy_StrokeVertex *) py_sv)->py_cp.py_if0D.borrowed = 1;
+
+ return py_sv;
+}
+
+PyObject * BPy_ViewVertex_from_ViewVertex( ViewVertex& vv ) {
+ PyObject *py_vv = ViewVertex_Type.tp_new( &ViewVertex_Type, 0, 0 );
+ ((BPy_ViewVertex *) py_vv)->vv = &vv;
+ ((BPy_ViewVertex *) py_vv)->py_if0D.if0D = ((BPy_ViewVertex *) py_vv)->vv;
+ ((BPy_ViewVertex *) py_vv)->py_if0D.borrowed = 1;
+
+ return py_vv;
+}
+
+PyObject * BPy_NonTVertex_from_NonTVertex( NonTVertex& ntv ) {
+ PyObject *py_ntv = NonTVertex_Type.tp_new( &NonTVertex_Type, 0, 0 );
+ ((BPy_NonTVertex *) py_ntv)->ntv = &ntv;
+ ((BPy_NonTVertex *) py_ntv)->py_vv.vv = ((BPy_NonTVertex *) py_ntv)->ntv;
+ ((BPy_NonTVertex *) py_ntv)->py_vv.py_if0D.if0D = ((BPy_NonTVertex *) py_ntv)->ntv;
+ ((BPy_NonTVertex *) py_ntv)->py_vv.py_if0D.borrowed = 1;
+
+ return py_ntv;
+}
+
+PyObject * BPy_TVertex_from_TVertex( TVertex& tv ) {
+ PyObject *py_tv = TVertex_Type.tp_new( &TVertex_Type, 0, 0 );
+ ((BPy_TVertex *) py_tv)->tv = &tv;
+ ((BPy_TVertex *) py_tv)->py_vv.vv = ((BPy_TVertex *) py_tv)->tv;
+ ((BPy_TVertex *) py_tv)->py_vv.py_if0D.if0D = ((BPy_TVertex *) py_tv)->tv;
+ ((BPy_TVertex *) py_tv)->py_vv.py_if0D.borrowed = 1;
+
+ return py_tv;
+}
+
+PyObject * BPy_BBox_from_BBox( BBox< Vec3r > &bb ) {
+ PyObject *py_bb = BBox_Type.tp_new( &BBox_Type, 0, 0 );
+ ((BPy_BBox *) py_bb)->bb = new BBox< Vec3r >( bb );
+
+ return py_bb;
+}
+
+PyObject * BPy_ViewEdge_from_ViewEdge( ViewEdge& ve ) {
+ PyObject *py_ve = ViewEdge_Type.tp_new( &ViewEdge_Type, 0, 0 );
+ ((BPy_ViewEdge *) py_ve)->ve = &ve;
+ ((BPy_ViewEdge *) py_ve)->py_if1D.if1D = ((BPy_ViewEdge *) py_ve)->ve;
+ ((BPy_ViewEdge *) py_ve)->py_if1D.borrowed = 1;
+
+ return py_ve;
+}
+
+PyObject * BPy_Chain_from_Chain( Chain& c ) {
+ PyObject *py_c = Chain_Type.tp_new( &Chain_Type, 0, 0 );
+ ((BPy_Chain *) py_c)->c = &c;
+ ((BPy_Chain *) py_c)->py_c.c = ((BPy_Chain *) py_c)->c;
+ ((BPy_Chain *) py_c)->py_c.py_if1D.if1D = ((BPy_Chain *) py_c)->c;
+ ((BPy_Chain *) py_c)->py_c.py_if1D.borrowed = 1;
+ return py_c;
+}
+
+PyObject * BPy_SShape_from_SShape( SShape& ss ) {
+ PyObject *py_ss = SShape_Type.tp_new( &SShape_Type, 0, 0 );
+ ((BPy_SShape *) py_ss)->ss = &ss;
+ ((BPy_SShape *) py_ss)->borrowed = 1;
+
+ return py_ss;
+}
+
+PyObject * BPy_ViewShape_from_ViewShape( ViewShape& vs ) {
+ PyObject *py_vs = ViewShape_Type.tp_new( &ViewShape_Type, 0, 0 );
+ ((BPy_ViewShape *) py_vs)->vs = &vs;
+ ((BPy_ViewShape *) py_vs)->borrowed = 1;
+
+ return py_vs;
+}
+
+PyObject * BPy_FrsMaterial_from_FrsMaterial( FrsMaterial& m ){
+ PyObject *py_m = FrsMaterial_Type.tp_new( &FrsMaterial_Type, 0, 0 );
+ ((BPy_FrsMaterial*) py_m)->m = &m;
+ ((BPy_FrsMaterial*) py_m)->borrowed = 1;
+
+ return py_m;
+}
+
+PyObject * BPy_IntegrationType_from_IntegrationType( IntegrationType i ) {
+ PyObject *py_it;
+
+ PyObject *args = PyTuple_New(1);
+ PyTuple_SetItem( args, 0, PyLong_FromLong(i) );
+ py_it = IntegrationType_Type.tp_new( &IntegrationType_Type, args, NULL );
+ Py_DECREF(args);
+
+ return py_it;
+}
+
+PyObject * BPy_CurvePoint_from_CurvePoint( CurvePoint& cp ) {
+ PyObject *py_cp = CurvePoint_Type.tp_new( &CurvePoint_Type, 0, 0 );
+ ((BPy_CurvePoint*) py_cp)->cp = &cp;
+ ((BPy_CurvePoint*) py_cp)->py_if0D.if0D = ((BPy_CurvePoint*) py_cp)->cp;
+ ((BPy_CurvePoint*) py_cp)->py_if0D.borrowed = 1;
+
+ return py_cp;
+}
+
+PyObject * BPy_directedViewEdge_from_directedViewEdge( ViewVertex::directedViewEdge& dve ) {
+ PyObject *py_dve = PyTuple_New(2);
+
+ PyTuple_SetItem( py_dve, 0, BPy_ViewEdge_from_ViewEdge(*(dve.first)) );
+ PyTuple_SetItem( py_dve, 1, PyBool_from_bool(dve.second) );
+
+ return py_dve;
+}
+
+//==============================
+// Iterators
+//==============================
+
+PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator( AdjacencyIterator& a_it ) {
+ PyObject *py_a_it = AdjacencyIterator_Type.tp_new( &AdjacencyIterator_Type, 0, 0 );
+ ((BPy_AdjacencyIterator *) py_a_it)->a_it = new AdjacencyIterator( a_it );
+ ((BPy_AdjacencyIterator *) py_a_it)->py_it.it = ((BPy_AdjacencyIterator *) py_a_it)->a_it;
+
+ return py_a_it;
+}
+
+PyObject * BPy_Interface0DIterator_from_Interface0DIterator( Interface0DIterator& if0D_it, int reversed ) {
+ PyObject *py_if0D_it = Interface0DIterator_Type.tp_new( &Interface0DIterator_Type, 0, 0 );
+ ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it = new Interface0DIterator( if0D_it );
+ ((BPy_Interface0DIterator *) py_if0D_it)->py_it.it = ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it;
+ ((BPy_Interface0DIterator *) py_if0D_it)->reversed = reversed;
+
+ return py_if0D_it;
+}
+
+PyObject * BPy_CurvePointIterator_from_CurvePointIterator( CurveInternal::CurvePointIterator& cp_it ) {
+ PyObject *py_cp_it = CurvePointIterator_Type.tp_new( &CurvePointIterator_Type, 0, 0 );
+ ((BPy_CurvePointIterator *) py_cp_it)->cp_it = new CurveInternal::CurvePointIterator( cp_it );
+ ((BPy_CurvePointIterator *) py_cp_it)->py_it.it = ((BPy_CurvePointIterator *) py_cp_it)->cp_it;
+
+ return py_cp_it;
+}
+
+PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator( StrokeInternal::StrokeVertexIterator& sv_it, int reversed) {
+ PyObject *py_sv_it = StrokeVertexIterator_Type.tp_new( &StrokeVertexIterator_Type, 0, 0 );
+ ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it = new StrokeInternal::StrokeVertexIterator( sv_it );
+ ((BPy_StrokeVertexIterator *) py_sv_it)->py_it.it = ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it;
+ ((BPy_StrokeVertexIterator *) py_sv_it)->reversed = reversed;
+
+ return py_sv_it;
+}
+
+PyObject * BPy_SVertexIterator_from_SVertexIterator( ViewEdgeInternal::SVertexIterator& sv_it ) {
+ PyObject *py_sv_it = SVertexIterator_Type.tp_new( &SVertexIterator_Type, 0, 0 );
+ ((BPy_SVertexIterator *) py_sv_it)->sv_it = new ViewEdgeInternal::SVertexIterator( sv_it );
+ ((BPy_SVertexIterator *) py_sv_it)->py_it.it = ((BPy_SVertexIterator *) py_sv_it)->sv_it;
+
+ return py_sv_it;
+}
+
+
+PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed ) {
+ PyObject *py_ove_it = orientedViewEdgeIterator_Type.tp_new( &orientedViewEdgeIterator_Type, 0, 0 );
+ ((BPy_orientedViewEdgeIterator *) py_ove_it)->ove_it = new ViewVertexInternal::orientedViewEdgeIterator( ove_it );
+ ((BPy_orientedViewEdgeIterator *) py_ove_it)->py_it.it = ((BPy_orientedViewEdgeIterator *) py_ove_it)->ove_it;
+ ((BPy_orientedViewEdgeIterator *) py_ove_it)->reversed = reversed;
+
+ return py_ove_it;
+}
+
+PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator( ViewEdgeInternal::ViewEdgeIterator& ve_it ) {
+ PyObject *py_ve_it = ViewEdgeIterator_Type.tp_new( &ViewEdgeIterator_Type, 0, 0 );
+ ((BPy_ViewEdgeIterator *) py_ve_it)->ve_it = new ViewEdgeInternal::ViewEdgeIterator( ve_it );
+ ((BPy_ViewEdgeIterator *) py_ve_it)->py_it.it = ((BPy_ViewEdgeIterator *) py_ve_it)->ve_it;
+
+ return py_ve_it;
+}
+
+PyObject * BPy_ChainingIterator_from_ChainingIterator( ChainingIterator& c_it ) {
+ PyObject *py_c_it = ChainingIterator_Type.tp_new( &ChainingIterator_Type, 0, 0 );
+ ((BPy_ChainingIterator *) py_c_it)->c_it = new ChainingIterator( c_it );
+ ((BPy_ChainingIterator *) py_c_it)->py_ve_it.py_it.it = ((BPy_ChainingIterator *) py_c_it)->c_it;
+
+ return py_c_it;
+}
+
+PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator( ChainPredicateIterator& cp_it ) {
+ PyObject *py_cp_it = ChainPredicateIterator_Type.tp_new( &ChainPredicateIterator_Type, 0, 0 );
+ ((BPy_ChainPredicateIterator *) py_cp_it)->cp_it = new ChainPredicateIterator( cp_it );
+ ((BPy_ChainPredicateIterator *) py_cp_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainPredicateIterator *) py_cp_it)->cp_it;
+
+ return py_cp_it;
+}
+
+PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( ChainSilhouetteIterator& cs_it ) {
+ PyObject *py_cs_it = ChainSilhouetteIterator_Type.tp_new( &ChainSilhouetteIterator_Type, 0, 0 );
+ ((BPy_ChainSilhouetteIterator *) py_cs_it)->cs_it = new ChainSilhouetteIterator( cs_it );
+ ((BPy_ChainSilhouetteIterator *) py_cs_it)->py_c_it.py_ve_it.py_it.it = ((BPy_ChainSilhouetteIterator *) py_cs_it)->cs_it;
+
+ return py_cs_it;
+}
+
+
+//==============================
+// Python => C++
+//==============================
+
+bool bool_from_PyBool( PyObject *b ) {
+ return PyObject_IsTrue(b) != 0;
+}
+
+IntegrationType IntegrationType_from_BPy_IntegrationType( PyObject* obj ) {
+ return static_cast<IntegrationType>( PyLong_AsLong(obj) );
+}
+
+Stroke::MediumType MediumType_from_BPy_MediumType( PyObject* obj ) {
+ return static_cast<Stroke::MediumType>( PyLong_AsLong(obj) );
+}
+
+Nature::EdgeNature EdgeNature_from_BPy_Nature( PyObject* obj ) {
+ return static_cast<Nature::EdgeNature>( PyLong_AsLong(obj) );
+}
+
+Vec2f * Vec2f_ptr_from_PyObject( PyObject* obj ) {
+ Vec2f *v;
+ if( (v = Vec2f_ptr_from_Vector( obj )) )
+ return v;
+ if( (v = Vec2f_ptr_from_PyList( obj )) )
+ return v;
+ if( (v = Vec2f_ptr_from_PyTuple( obj )) )
+ return v;
+ return NULL;
+}
+
+Vec3f * Vec3f_ptr_from_PyObject( PyObject* obj ) {
+ Vec3f *v;
+ if( (v = Vec3f_ptr_from_Vector( obj )) )
+ return v;
+ if( (v = Vec3f_ptr_from_PyList( obj )) )
+ return v;
+ if( (v = Vec3f_ptr_from_PyTuple( obj )) )
+ return v;
+ return NULL;
+}
+
+Vec3r * Vec3r_ptr_from_PyObject( PyObject* obj ) {
+ Vec3r *v;
+ if( (v = Vec3r_ptr_from_Vector( obj )) )
+ return v;
+ if( (v = Vec3r_ptr_from_PyList( obj )) )
+ return v;
+ if( (v = Vec3r_ptr_from_PyTuple( obj )) )
+ return v;
+ return NULL;
+}
+
+Vec2f * Vec2f_ptr_from_Vector( PyObject* obj ) {
+ PyObject *v;
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 2)
+ return NULL;
+ v = PyObject_GetAttrString(obj,"x");
+ float x = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"y");
+ float y = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+
+ return new Vec2f(x,y);
+}
+
+Vec3f * Vec3f_ptr_from_Vector( PyObject* obj ) {
+ PyObject *v;
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3)
+ return NULL;
+ v = PyObject_GetAttrString(obj,"x");
+ float x = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"y");
+ float y = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"z");
+ float z = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+
+ return new Vec3f(x,y,z);
+}
+
+Vec3r * Vec3r_ptr_from_Vector( PyObject* obj ) {
+ PyObject *v;
+ if (!VectorObject_Check(obj) || ((VectorObject *)obj)->size != 3)
+ return NULL;
+ v = PyObject_GetAttrString(obj,"x");
+ double x = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"y");
+ double y = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+ v = PyObject_GetAttrString(obj,"z");
+ double z = PyFloat_AsDouble( v );
+ Py_DECREF( v );
+
+ return new Vec3r(x,y,z);
+}
+
+Vec2f * Vec2f_ptr_from_PyList( PyObject* obj ) {
+ if( !PyList_Check(obj) || PyList_Size(obj) != 2 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyList_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyList_GetItem(obj, 1));
+ return new Vec2f(x,y);
+}
+
+Vec3f * Vec3f_ptr_from_PyList( PyObject* obj ) {
+ if( !PyList_Check(obj) || PyList_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyList_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyList_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyList_GetItem(obj, 2));
+ return new Vec3f(x,y,z);
+}
+
+Vec3r * Vec3r_ptr_from_PyList( PyObject* obj ) {
+ if( !PyList_Check(obj) || PyList_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyList_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyList_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyList_GetItem(obj, 2));
+ return new Vec3r(x,y,z);
+}
+
+Vec2f * Vec2f_ptr_from_PyTuple( PyObject* obj ) {
+ if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 2 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1));
+ return new Vec2f(x,y);
+}
+
+Vec3f * Vec3f_ptr_from_PyTuple( PyObject* obj ) {
+ if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyTuple_GetItem(obj, 2));
+ return new Vec3f(x,y,z);
+}
+
+Vec3r * Vec3r_ptr_from_PyTuple( PyObject* obj ) {
+ if( !PyTuple_Check(obj) || PyTuple_Size(obj) != 3 )
+ return NULL;
+ float x = PyFloat_AsDouble(PyTuple_GetItem(obj, 0));
+ float y = PyFloat_AsDouble(PyTuple_GetItem(obj, 1));
+ float z = PyFloat_AsDouble(PyTuple_GetItem(obj, 2));
+ return new Vec3r(x,y,z);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h
new file mode 100644
index 00000000000..7e4e07472d8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Convert.h
@@ -0,0 +1,147 @@
+#ifndef FREESTYLE_PYTHON_CONVERT_H
+#define FREESTYLE_PYTHON_CONVERT_H
+
+#include <Python.h>
+#include <typeinfo>
+
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+// BBox
+#include "../geometry/BBox.h"
+
+// FEdge, FEdgeSharp, FEdgeSmooth, SShape, SVertex, FEdgeInternal::SVertexIterator
+#include "../view_map/Silhouette.h"
+
+// Id
+#include "../system/Id.h"
+
+// Interface0D, Interface0DIteratorNested, Interface0DIterator
+#include "../view_map/Interface0D.h"
+
+// Interface1D
+#include "../view_map/Interface1D.h"
+
+// FrsMaterial
+#include "../scene_graph/FrsMaterial.h"
+
+// Nature::VertexNature, Nature::EdgeNature
+#include "../winged_edge/Nature.h"
+
+// Stroke, StrokeAttribute, StrokeVertex
+#include "../stroke/Stroke.h"
+
+// NonTVertex, TVertex, ViewEdge, ViewMap, ViewShape, ViewVertex
+#include "../view_map/ViewMap.h"
+
+// CurvePoint, Curve
+#include "../stroke/Curve.h"
+
+// Chain
+#include "../stroke/Chain.h"
+
+//====== ITERATORS
+
+// AdjacencyIterator, ChainingIterator, ChainSilhouetteIterator, ChainPredicateIterator
+#include "../stroke/ChainingIterators.h"
+
+// ViewVertexInternal::orientedViewEdgeIterator
+// ViewEdgeInternal::SVertexIterator
+// ViewEdgeInternal::ViewEdgeIterator
+#include "../view_map/ViewMapIterators.h"
+
+// StrokeInternal::StrokeVertexIterator
+#include "../stroke/StrokeIterators.h"
+
+// CurveInternal::CurvePointIterator
+#include "../stroke/CurveIterators.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include "generic/mathutils.h"
+
+//==============================
+// C++ => Python
+//==============================
+
+PyObject * PyBool_from_bool( bool b );
+PyObject * Vector_from_Vec2f( Vec2f& v );
+PyObject * Vector_from_Vec3f( Vec3f& v );
+PyObject * Vector_from_Vec3r( Vec3r& v );
+
+PyObject * Any_BPy_Interface0D_from_Interface0D( Interface0D& if0D );
+PyObject * Any_BPy_Interface1D_from_Interface1D( Interface1D& if1D );
+PyObject * Any_BPy_FEdge_from_FEdge( FEdge& fe );
+PyObject * Any_BPy_ViewVertex_from_ViewVertex( ViewVertex& vv );
+
+PyObject * BPy_BBox_from_BBox( BBox< Vec3r > &bb );
+PyObject * BPy_CurvePoint_from_CurvePoint( CurvePoint& cp );
+PyObject * BPy_directedViewEdge_from_directedViewEdge( ViewVertex::directedViewEdge& dve );
+PyObject * BPy_FEdge_from_FEdge( FEdge& fe );
+PyObject * BPy_FEdgeSharp_from_FEdgeSharp( FEdgeSharp& fes );
+PyObject * BPy_FEdgeSmooth_from_FEdgeSmooth( FEdgeSmooth& fes );
+PyObject * BPy_Id_from_Id( Id& id );
+PyObject * BPy_Interface0D_from_Interface0D( Interface0D& if0D );
+PyObject * BPy_Interface1D_from_Interface1D( Interface1D& if1D );
+PyObject * BPy_IntegrationType_from_IntegrationType( IntegrationType i );
+PyObject * BPy_FrsMaterial_from_FrsMaterial( FrsMaterial& m );
+PyObject * BPy_Nature_from_Nature( unsigned short n );
+PyObject * BPy_MediumType_from_MediumType( Stroke::MediumType n );
+PyObject * BPy_SShape_from_SShape( SShape& ss );
+PyObject * BPy_Stroke_from_Stroke( Stroke& s );
+PyObject * BPy_StrokeAttribute_from_StrokeAttribute( StrokeAttribute& sa );
+PyObject * BPy_StrokeVertex_from_StrokeVertex( StrokeVertex& sv );
+PyObject * BPy_SVertex_from_SVertex( SVertex& sv );
+PyObject * BPy_ViewVertex_from_ViewVertex( ViewVertex& vv );
+PyObject * BPy_NonTVertex_from_NonTVertex( NonTVertex& ntv );
+PyObject * BPy_TVertex_from_TVertex( TVertex& tv );
+PyObject * BPy_ViewEdge_from_ViewEdge( ViewEdge& ve );
+PyObject * BPy_Chain_from_Chain( Chain& c );
+PyObject * BPy_ViewShape_from_ViewShape( ViewShape& vs );
+
+PyObject * BPy_AdjacencyIterator_from_AdjacencyIterator( AdjacencyIterator& a_it );
+PyObject * BPy_Interface0DIterator_from_Interface0DIterator( Interface0DIterator& if0D_it, int reversed );
+PyObject * BPy_CurvePointIterator_from_CurvePointIterator( CurveInternal::CurvePointIterator& cp_it );
+PyObject * BPy_StrokeVertexIterator_from_StrokeVertexIterator( StrokeInternal::StrokeVertexIterator& sv_it, int reversed);
+PyObject * BPy_SVertexIterator_from_SVertexIterator( ViewEdgeInternal::SVertexIterator& sv_it );
+PyObject * BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ViewVertexInternal::orientedViewEdgeIterator& ove_it, int reversed );
+PyObject * BPy_ViewEdgeIterator_from_ViewEdgeIterator( ViewEdgeInternal::ViewEdgeIterator& ve_it );
+PyObject * BPy_ChainingIterator_from_ChainingIterator( ChainingIterator& c_it );
+PyObject * BPy_ChainPredicateIterator_from_ChainPredicateIterator( ChainPredicateIterator& cp_it );
+PyObject * BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( ChainSilhouetteIterator& cs_it );
+
+//==============================
+// Python => C++
+//==============================
+
+bool bool_from_PyBool( PyObject *b );
+IntegrationType IntegrationType_from_BPy_IntegrationType( PyObject* obj );
+Stroke::MediumType MediumType_from_BPy_MediumType( PyObject* obj );
+Nature::EdgeNature EdgeNature_from_BPy_Nature( PyObject* obj );
+Vec2f * Vec2f_ptr_from_PyObject( PyObject* obj );
+Vec3f * Vec3f_ptr_from_PyObject( PyObject* obj );
+Vec3r * Vec3r_ptr_from_PyObject( PyObject* obj );
+Vec2f * Vec2f_ptr_from_Vector( PyObject* obj );
+Vec3f * Vec3f_ptr_from_Vector( PyObject* obj );
+Vec3r * Vec3r_ptr_from_Vector( PyObject* obj );
+Vec2f * Vec2f_ptr_from_PyList( PyObject* obj );
+Vec3f * Vec3f_ptr_from_PyList( PyObject* obj );
+Vec3r * Vec3r_ptr_from_PyList( PyObject* obj );
+Vec2f * Vec2f_ptr_from_PyTuple( PyObject* obj );
+Vec3f * Vec3f_ptr_from_PyTuple( PyObject* obj );
+Vec3r * Vec3r_ptr_from_PyTuple( PyObject* obj );
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONVERT_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
new file mode 100644
index 00000000000..082ca32ddc7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp
@@ -0,0 +1,125 @@
+#include "BPy_Freestyle.h"
+
+#include "BPy_BBox.h"
+#include "BPy_BinaryPredicate0D.h"
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_ContextFunctions.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_FrsNoise.h"
+#include "BPy_Id.h"
+#include "BPy_IntegrationType.h"
+#include "BPy_Interface0D.h"
+#include "BPy_Interface1D.h"
+#include "BPy_Iterator.h"
+#include "BPy_MediumType.h"
+#include "BPy_Nature.h"
+#include "BPy_Operators.h"
+#include "BPy_SShape.h"
+#include "BPy_StrokeAttribute.h"
+#include "BPy_StrokeShader.h"
+#include "BPy_UnaryFunction0D.h"
+#include "BPy_UnaryFunction1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "BPy_ViewMap.h"
+#include "BPy_ViewShape.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+#include "FRS_freestyle.h"
+#include "bpy_rna.h" /* pyrna_struct_CreatePyObject() */
+
+static char Freestyle_getCurrentScene___doc__[] =
+".. function:: getCurrentScene()\n"
+"\n"
+" Returns the current scene.\n"
+"\n"
+" :return: The current scene.\n"
+" :rtype: :class:`bpy.types.Scene`\n";
+
+static PyObject *Freestyle_getCurrentScene( PyObject *self )
+{
+ if (!freestyle_scene) {
+ PyErr_SetString(PyExc_TypeError, "current scene not available");
+ return NULL;
+ }
+ PointerRNA ptr_scene;
+ RNA_pointer_create(NULL, &RNA_Scene, freestyle_scene, &ptr_scene);
+ return pyrna_struct_CreatePyObject(&ptr_scene);
+}
+
+/*-----------------------Freestyle module docstring----------------------------*/
+
+static char module_docstring[] = "The Blender Freestyle module\n\n";
+
+/*-----------------------Freestyle module method def---------------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"getCurrentScene", ( PyCFunction ) Freestyle_getCurrentScene, METH_NOARGS, Freestyle_getCurrentScene___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------Freestyle module definition---------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+//-------------------MODULE INITIALIZATION--------------------------------
+PyObject *Freestyle_Init( void )
+{
+ PyObject *module;
+
+ // initialize modules
+ module = PyModule_Create(&module_definition);
+ if (!module)
+ return NULL;
+ PyDict_SetItemString(PySys_GetObject("modules"), module_definition.m_name, module);
+
+ // attach its classes (adding the object types to the module)
+
+ // those classes have to be initialized before the others
+ MediumType_Init( module );
+ Nature_Init( module );
+
+ BBox_Init( module );
+ BinaryPredicate0D_Init( module );
+ BinaryPredicate1D_Init( module );
+ ContextFunctions_Init( module );
+ FrsMaterial_Init( module );
+ FrsNoise_Init( module );
+ Id_Init( module );
+ IntegrationType_Init( module );
+ Interface0D_Init( module );
+ Interface1D_Init( module );
+ Iterator_Init( module );
+ Operators_Init( module );
+ SShape_Init( module );
+ StrokeAttribute_Init( module );
+ StrokeShader_Init( module );
+ UnaryFunction0D_Init( module );
+ UnaryFunction1D_Init( module );
+ UnaryPredicate0D_Init( module );
+ UnaryPredicate1D_Init( module );
+ ViewMap_Init( module );
+ ViewShape_Init( module );
+
+ return module;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.h b/source/blender/freestyle/intern/python/BPy_Freestyle.h
new file mode 100644
index 00000000000..8ade4b5ff4d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Freestyle.h
@@ -0,0 +1,22 @@
+#ifndef FREESTYLE_PYTHON_FREESTYLE_H
+#define FREESTYLE_PYTHON_FREESTYLE_H
+
+#include <Python.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*---------------------------Python BPy_Freestyle visible prototypes-----------*/
+
+PyObject *Freestyle_Init( void );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FREESTYLE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
new file mode 100644
index 00000000000..27582b7f25e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp
@@ -0,0 +1,599 @@
+#include "BPy_FrsMaterial.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int FrsMaterial_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &FrsMaterial_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &FrsMaterial_Type );
+ PyModule_AddObject(module, "FrsMaterial", (PyObject *)&FrsMaterial_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FrsMaterial___doc__[] =
+"Class defining a material.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(m)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg m: A Material object.\n"
+" :type m: :class:`FrsMaterial`\n"
+"\n"
+".. method:: __init__(iDiffuse, iAmbiant, iSpecular, iEmission, iShininess)\n"
+"\n"
+" Builds a Material from its diffuse, ambiant, specular, emissive\n"
+" colors and a shininess coefficient.\n"
+"\n"
+" :arg iDiffuse: The diffuse color.\n"
+" :type iDiffuse: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iAmbiant: The ambiant color.\n"
+" :type iAmbiant: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iSpecular: The specular color.\n"
+" :type iSpecular: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iEmission: The emissive color.\n"
+" :type iEmission: :class:`mathutils.Vector`, list of tuple of 4 float values\n"
+" :arg iShininess: The shininess coefficient.\n"
+" :type iShininess: :class:`mathutils.Vector`, list of tuple of 4 float values\n";
+
+static int Vec4(PyObject *obj, float *v)
+{
+ if (VectorObject_Check(obj) && ((VectorObject *)obj)->size == 4) {
+ for (int i = 0; i < 4; i++)
+ v[i] = ((VectorObject *)obj)->vec[i];
+ } else if( PyList_Check(obj) && PyList_Size(obj) == 4 ) {
+ for (int i = 0; i < 4; i++)
+ v[i] = PyFloat_AsDouble(PyList_GetItem(obj, i));
+ } else if( PyTuple_Check(obj) && PyTuple_Size(obj) == 4 ) {
+ for (int i = 0; i < 4; i++)
+ v[i] = PyFloat_AsDouble(PyTuple_GetItem(obj, i));
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static int FrsMaterial___init__(BPy_FrsMaterial *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+ float f1[4], f2[4], f3[4], f4[4], f5 = 0.;
+
+ if (! PyArg_ParseTuple(args, "|OOOOf", &obj1, &obj2, &obj3, &obj4, &f5) )
+ return -1;
+
+ if( !obj1 ){
+ self->m = new FrsMaterial();
+
+ } else if( BPy_FrsMaterial_Check(obj1) && !obj2 ) {
+ FrsMaterial *m = ((BPy_FrsMaterial *) obj1)->m;
+ if( !m ) {
+ PyErr_SetString(PyExc_RuntimeError, "invalid FrsMaterial object");
+ return -1;
+ }
+ self->m = new FrsMaterial( *m );
+
+ } else if( Vec4(obj1, f1) && obj2 && Vec4(obj2, f2) && obj3 && Vec4(obj3, f3) && obj4 && Vec4(obj4, f4) ) {
+ self->m = new FrsMaterial(f1, f2, f3, f4, f5);
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+ self->borrowed = 0;
+
+ return 0;
+}
+
+static void FrsMaterial___dealloc__( BPy_FrsMaterial* self)
+{
+ if( self->m && !self->borrowed )
+ delete self->m;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * FrsMaterial___repr__( BPy_FrsMaterial* self)
+{
+ return PyUnicode_FromFormat("FrsMaterial - address: %p", self->m );
+}
+
+static char FrsMaterial_diffuse___doc__[] =
+".. method:: diffuse()\n"
+"\n"
+" Returns the diffuse color.\n"
+"\n"
+" :return: The diffuse color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_diffuse( BPy_FrsMaterial* self) {
+ const float *diffuse = self->m->diffuse();
+ PyObject *py_diffuse = PyTuple_New(4);
+
+ PyTuple_SetItem( py_diffuse, 0, PyFloat_FromDouble( diffuse[0] ) );
+ PyTuple_SetItem( py_diffuse, 1, PyFloat_FromDouble( diffuse[1] ) );
+ PyTuple_SetItem( py_diffuse, 2, PyFloat_FromDouble( diffuse[2] ) );
+ PyTuple_SetItem( py_diffuse, 3, PyFloat_FromDouble( diffuse[3] ) );
+
+ return py_diffuse;
+}
+
+static char FrsMaterial_diffuseR___doc__[] =
+".. method:: diffuseR()\n"
+"\n"
+" Returns the red component of the diffuse color.\n"
+"\n"
+" :return: The red component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseR() );
+}
+
+static char FrsMaterial_diffuseG___doc__[] =
+".. method:: diffuseG()\n"
+"\n"
+" Returns the green component of the diffuse color.\n"
+"\n"
+" :return: The green component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseG() );
+}
+
+static char FrsMaterial_diffuseB___doc__[] =
+".. method:: diffuseB()\n"
+"\n"
+" Returns the blue component of the diffuse color.\n"
+"\n"
+" :return: The blue component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseB() );
+}
+
+static char FrsMaterial_diffuseA___doc__[] =
+".. method:: diffuseA()\n"
+"\n"
+" Returns the alpha component of the diffuse color.\n"
+"\n"
+" :return: The alpha component of the diffuse color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_diffuseA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->diffuseA() );
+}
+
+static char FrsMaterial_specular___doc__[] =
+".. method:: specular()\n"
+"\n"
+" Returns the specular color.\n"
+"\n"
+" :return: The specular color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_specular( BPy_FrsMaterial* self) {
+ const float *specular = self->m->specular();
+ PyObject *py_specular = PyTuple_New(4);
+
+ PyTuple_SetItem( py_specular, 0, PyFloat_FromDouble( specular[0] ) );
+ PyTuple_SetItem( py_specular, 1, PyFloat_FromDouble( specular[1] ) );
+ PyTuple_SetItem( py_specular, 2, PyFloat_FromDouble( specular[2] ) );
+ PyTuple_SetItem( py_specular, 3, PyFloat_FromDouble( specular[3] ) );
+
+ return py_specular;
+}
+
+static char FrsMaterial_specularR___doc__[] =
+".. method:: specularR()\n"
+"\n"
+" Returns the red component of the specular color.\n"
+"\n"
+" :return: The red component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularR() );
+}
+
+static char FrsMaterial_specularG___doc__[] =
+".. method:: specularG()\n"
+"\n"
+" Returns the green component of the specular color.\n"
+"\n"
+" :return: The green component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularG() );
+}
+
+static char FrsMaterial_specularB___doc__[] =
+".. method:: specularB()\n"
+"\n"
+" Returns the blue component of the specular color.\n"
+"\n"
+" :return: The blue component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularB() );
+}
+
+static char FrsMaterial_specularA___doc__[] =
+".. method:: specularA()\n"
+"\n"
+" Returns the alpha component of the specular color.\n"
+"\n"
+" :return: The alpha component of the specular color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_specularA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->specularA() );
+}
+
+static char FrsMaterial_ambient___doc__[] =
+".. method:: ambient()\n"
+"\n"
+" Returns the ambiant color.\n"
+"\n"
+" :return: The ambiant color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_ambient( BPy_FrsMaterial* self) {
+ const float *ambient = self->m->ambient();
+ PyObject *py_ambient = PyTuple_New(4);
+
+ PyTuple_SetItem( py_ambient, 0, PyFloat_FromDouble( ambient[0] ) );
+ PyTuple_SetItem( py_ambient, 1, PyFloat_FromDouble( ambient[1] ) );
+ PyTuple_SetItem( py_ambient, 2, PyFloat_FromDouble( ambient[2] ) );
+ PyTuple_SetItem( py_ambient, 3, PyFloat_FromDouble( ambient[3] ) );
+
+ return py_ambient;
+}
+
+static char FrsMaterial_ambientR___doc__[] =
+".. method:: ambientR()\n"
+"\n"
+" Returns the red component of the ambiant color.\n"
+"\n"
+" :return: The red component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientR() );
+}
+
+static char FrsMaterial_ambientG___doc__[] =
+".. method:: ambientG()\n"
+"\n"
+" Returns the green component of the ambiant color.\n"
+"\n"
+" :return: The green component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientG() );
+}
+
+static char FrsMaterial_ambientB___doc__[] =
+".. method:: ambientB()\n"
+"\n"
+" Returns the blue component of the ambiant color.\n"
+"\n"
+" :return: The blue component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientB() );
+}
+
+static char FrsMaterial_ambientA___doc__[] =
+".. method:: ambientA()\n"
+"\n"
+" Returns the alpha component of the ambiant color.\n"
+"\n"
+" :return: The alpha component of the ambiant color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_ambientA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->ambientA() );
+}
+
+static char FrsMaterial_emission___doc__[] =
+".. method:: emission()\n"
+"\n"
+" Returns the emissive color.\n"
+"\n"
+" :return: the emissive color.\n"
+" :rtype: Tuple of 4 float values\n";
+
+static PyObject * FrsMaterial_emission( BPy_FrsMaterial* self) {
+ const float *emission = self->m->emission();
+ PyObject *py_emission = PyTuple_New(4);
+
+ PyTuple_SetItem( py_emission, 0, PyFloat_FromDouble( emission[0] ) );
+ PyTuple_SetItem( py_emission, 1, PyFloat_FromDouble( emission[1] ) );
+ PyTuple_SetItem( py_emission, 2, PyFloat_FromDouble( emission[2] ) );
+ PyTuple_SetItem( py_emission, 3, PyFloat_FromDouble( emission[3] ) );
+
+ return py_emission;
+}
+
+static char FrsMaterial_emissionR___doc__[] =
+".. method:: emissionR()\n"
+"\n"
+" Returns the red component of the emissive color.\n"
+"\n"
+" :return: The red component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionR( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionR() );
+}
+
+static char FrsMaterial_emissionG___doc__[] =
+".. method:: emissionG()\n"
+"\n"
+" Returns the green component of the emissive color.\n"
+"\n"
+" :return: The green component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionG( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionG() );
+}
+
+static char FrsMaterial_emissionB___doc__[] =
+".. method:: emissionB()\n"
+"\n"
+" Returns the blue component of the emissive color.\n"
+"\n"
+" :return: The blue component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionB( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionB() );
+}
+
+static char FrsMaterial_emissionA___doc__[] =
+".. method:: emissionA()\n"
+"\n"
+" Returns the alpha component of the emissive color.\n"
+"\n"
+" :return: The alpha component of the emissive color.\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_emissionA( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->emissionA() );
+}
+
+static char FrsMaterial_shininess___doc__[] =
+".. method:: shininess()\n"
+"\n"
+" Returns the shininess coefficient.\n"
+"\n"
+" :return: Shininess\n"
+" :rtype: float\n";
+
+static PyObject * FrsMaterial_shininess( BPy_FrsMaterial* self) {
+ return PyFloat_FromDouble( self->m->shininess() );
+}
+
+static char FrsMaterial_setDiffuse___doc__[] =
+".. method:: setDiffuse(r, g, b, a)\n"
+"\n"
+" Sets the diffuse color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setDiffuse( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setDiffuse(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setSpecular___doc__[] =
+".. method:: setSpecular(r, g, b, a)\n"
+"\n"
+" Sets the specular color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setSpecular( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setSpecular(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setAmbient___doc__[] =
+".. method:: setAmbient(r, g, b, a)\n"
+"\n"
+" Sets the ambiant color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setAmbient( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setAmbient(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setEmission___doc__[] =
+".. method:: setEmission(r, g, b, a)\n"
+"\n"
+" Sets the emissive color.\n"
+"\n"
+" :arg r: Red component.\n"
+" :type r: float\n"
+" :arg g: Green component.\n"
+" :type g: float\n"
+" :arg b: Blue component.\n"
+" :type b: float\n"
+" :arg a: Alpha component.\n"
+" :type a: float\n";
+
+static PyObject * FrsMaterial_setEmission( BPy_FrsMaterial *self, PyObject *args ) {
+ float f1, f2, f3, f4;
+
+ if(!( PyArg_ParseTuple(args, "ffff", &f1, &f2, &f3, &f4) ))
+ return NULL;
+
+ self->m->setEmission(f1, f2, f3, f4);
+
+ Py_RETURN_NONE;
+}
+
+static char FrsMaterial_setShininess___doc__[] =
+".. method:: setShininess(s)\n"
+"\n"
+" Sets the shininess.\n"
+"\n"
+" :arg s: Shininess.\n"
+" :type s: float\n";
+
+static PyObject * FrsMaterial_setShininess( BPy_FrsMaterial *self, PyObject *args ) {
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ self->m->setShininess(f);
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FrsMaterial instance definitions ----------------------------*/
+static PyMethodDef BPy_FrsMaterial_methods[] = {
+ {"diffuse", ( PyCFunction ) FrsMaterial_diffuse, METH_NOARGS, FrsMaterial_diffuse___doc__},
+ {"diffuseR", ( PyCFunction ) FrsMaterial_diffuseR, METH_NOARGS, FrsMaterial_diffuseR___doc__},
+ {"diffuseG", ( PyCFunction ) FrsMaterial_diffuseG, METH_NOARGS, FrsMaterial_diffuseG___doc__},
+ {"diffuseB", ( PyCFunction ) FrsMaterial_diffuseB, METH_NOARGS, FrsMaterial_diffuseB___doc__},
+ {"diffuseA", ( PyCFunction ) FrsMaterial_diffuseA, METH_NOARGS, FrsMaterial_diffuseA___doc__},
+ {"specular", ( PyCFunction ) FrsMaterial_specular, METH_NOARGS, FrsMaterial_specular___doc__},
+ {"specularR", ( PyCFunction ) FrsMaterial_specularR, METH_NOARGS, FrsMaterial_specularR___doc__},
+ {"specularG", ( PyCFunction ) FrsMaterial_specularG, METH_NOARGS, FrsMaterial_specularG___doc__},
+ {"specularB", ( PyCFunction ) FrsMaterial_specularB, METH_NOARGS, FrsMaterial_specularB___doc__},
+ {"specularA", ( PyCFunction ) FrsMaterial_specularA, METH_NOARGS, FrsMaterial_specularA___doc__},
+ {"ambient", ( PyCFunction ) FrsMaterial_ambient, METH_NOARGS, FrsMaterial_ambient___doc__},
+ {"ambientR", ( PyCFunction ) FrsMaterial_ambientR, METH_NOARGS, FrsMaterial_ambientR___doc__},
+ {"ambientG", ( PyCFunction ) FrsMaterial_ambientG, METH_NOARGS, FrsMaterial_ambientG___doc__},
+ {"ambientB", ( PyCFunction ) FrsMaterial_ambientB, METH_NOARGS, FrsMaterial_ambientB___doc__},
+ {"ambientA", ( PyCFunction ) FrsMaterial_ambientA, METH_NOARGS, FrsMaterial_ambientA___doc__},
+ {"emission", ( PyCFunction ) FrsMaterial_emission, METH_NOARGS, FrsMaterial_emission___doc__},
+ {"emissionR", ( PyCFunction ) FrsMaterial_emissionR, METH_NOARGS, FrsMaterial_emissionR___doc__},
+ {"emissionG", ( PyCFunction ) FrsMaterial_emissionG, METH_NOARGS, FrsMaterial_emissionG___doc__},
+ {"emissionB", ( PyCFunction ) FrsMaterial_emissionB, METH_NOARGS, FrsMaterial_emissionB___doc__},
+ {"emissionA", ( PyCFunction ) FrsMaterial_emissionA, METH_NOARGS, FrsMaterial_emissionA___doc__},
+ {"shininess", ( PyCFunction ) FrsMaterial_shininess, METH_NOARGS, FrsMaterial_shininess___doc__},
+ {"setDiffuse", ( PyCFunction ) FrsMaterial_setDiffuse, METH_NOARGS, FrsMaterial_setDiffuse___doc__},
+ {"setSpecular", ( PyCFunction ) FrsMaterial_setSpecular, METH_NOARGS, FrsMaterial_setSpecular___doc__},
+ {"setAmbient", ( PyCFunction ) FrsMaterial_setAmbient, METH_NOARGS, FrsMaterial_setAmbient___doc__},
+ {"setEmission", ( PyCFunction ) FrsMaterial_setEmission, METH_NOARGS, FrsMaterial_setEmission___doc__},
+ {"setShininess", ( PyCFunction ) FrsMaterial_setShininess, METH_NOARGS, FrsMaterial_setShininess___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsMaterial type definition ------------------------------*/
+
+PyTypeObject FrsMaterial_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FrsMaterial", /* tp_name */
+ sizeof(BPy_FrsMaterial), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)FrsMaterial___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)FrsMaterial___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FrsMaterial___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsMaterial_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsMaterial___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.h b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h
new file mode 100644
index 00000000000..f541e1bb529
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_FRSMATERIAL_H
+#define FREESTYLE_PYTHON_FRSMATERIAL_H
+
+#include <Python.h>
+
+#include "../scene_graph/FrsMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject FrsMaterial_Type;
+
+#define BPy_FrsMaterial_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsMaterial_Type) )
+
+/*---------------------------Python BPy_FrsMaterial structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ FrsMaterial *m;
+ int borrowed; /* non-zero if *m is a borrowed object */
+} BPy_FrsMaterial;
+
+/*---------------------------Python BPy_FrsMaterial visible prototypes-----------*/
+
+int FrsMaterial_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_FRSMATERIAL_H */
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
new file mode 100644
index 00000000000..d9d2540c1e8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp
@@ -0,0 +1,274 @@
+#include "BPy_FrsNoise.h"
+#include "BPy_Convert.h"
+
+#include <sstream>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int FrsNoise_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &FrsNoise_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &FrsNoise_Type );
+ PyModule_AddObject(module, "FrsNoise", (PyObject *)&FrsNoise_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FrsNoise___doc__[] =
+"Class to provide Perlin noise functionalities.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a Noise object.\n";
+
+static int FrsNoise___init__(BPy_FrsNoise *self, PyObject *args, PyObject *kwds)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->n = new Noise();
+ return 0;
+}
+
+static void FrsNoise___dealloc__(BPy_FrsNoise* self)
+{
+ delete self->n;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * FrsNoise___repr__(BPy_FrsNoise* self)
+{
+ return PyUnicode_FromFormat("FrsNoise - address: %p", self->n );
+}
+
+static char FrsNoise_turbulence1___doc__[] =
+".. method:: turbulence1(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 1D element.\n"
+"\n"
+" :arg v: One-dimensional sample point.\n"
+" :type v: float\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_turbulence1( BPy_FrsNoise *self , PyObject *args) {
+ float f1, f2, f3;
+ unsigned int i = 4;
+
+ if(!( PyArg_ParseTuple(args, "fff|I", &f1, &f2, &f3, &i) ))
+ return NULL;
+
+ return PyFloat_FromDouble( self->n->turbulence1(f1, f2, f3, i) );
+}
+
+static char FrsNoise_turbulence2___doc__[] =
+".. method:: turbulence2(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 2D element.\n"
+"\n"
+" :arg v: Two-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_turbulence2( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj1;
+ float f2, f3;
+ unsigned int i = 4;
+
+ if(!( PyArg_ParseTuple(args, "Off|I", &obj1, &f2, &f3, &i) ))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->turbulence2(*v, f2, f3, i);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+static char FrsNoise_turbulence3___doc__[] =
+".. method:: turbulence3(v, freq, amp, oct=4)\n"
+"\n"
+" Returns a noise value for a 3D element.\n"
+"\n"
+" :arg v: Three-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :arg freq: Noise frequency.\n"
+" :type freq: float\n"
+" :arg amp: Amplitude.\n"
+" :type amp: float\n"
+" :arg oct: Number of octaves.\n"
+" :type oct: int\n"
+" :return: A noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_turbulence3( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj1;
+ float f2, f3;
+ unsigned int i = 4;
+
+ if(!( PyArg_ParseTuple(args, "Off|I", &obj1, &f2, &f3, &i) ))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->turbulence3(*v, f2, f3, i);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+static char FrsNoise_smoothNoise1___doc__[] =
+".. method:: smoothNoise1(v)\n"
+"\n"
+" Returns a smooth noise value for a 1D element.\n"
+"\n"
+" :arg v: One-dimensional sample point.\n"
+" :type v: float\n"
+" :return: A smooth noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_smoothNoise1( BPy_FrsNoise *self , PyObject *args) {
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ return PyFloat_FromDouble( self->n->smoothNoise1(f) );
+}
+
+static char FrsNoise_smoothNoise2___doc__[] =
+".. method:: smoothNoise2(v)\n"
+"\n"
+" Returns a smooth noise value for a 2D element.\n"
+"\n"
+" :arg v: Two-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n"
+" :return: A smooth noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_smoothNoise2( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->smoothNoise2(*v);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+static char FrsNoise_smoothNoise3___doc__[] =
+".. method:: smoothNoise3(v)\n"
+"\n"
+" Returns a smooth noise value for a 3D element.\n"
+"\n"
+" :arg v: Three-dimensional sample point.\n"
+" :type v: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n"
+" :return: A smooth noise value.\n"
+" :rtype: float\n";
+
+static PyObject * FrsNoise_smoothNoise3( BPy_FrsNoise *self , PyObject *args) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ float t = self->n->smoothNoise3(*v);
+ delete v;
+ return PyFloat_FromDouble( t );
+}
+
+/*----------------------FrsNoise instance definitions ----------------------------*/
+static PyMethodDef BPy_FrsNoise_methods[] = {
+ {"turbulence1", ( PyCFunction ) FrsNoise_turbulence1, METH_VARARGS, FrsNoise_turbulence1___doc__},
+ {"turbulence2", ( PyCFunction ) FrsNoise_turbulence2, METH_VARARGS, FrsNoise_turbulence2___doc__},
+ {"turbulence3", ( PyCFunction ) FrsNoise_turbulence3, METH_VARARGS, FrsNoise_turbulence3___doc__},
+ {"smoothNoise1", ( PyCFunction ) FrsNoise_smoothNoise1, METH_VARARGS, FrsNoise_smoothNoise1___doc__},
+ {"smoothNoise2", ( PyCFunction ) FrsNoise_smoothNoise2, METH_VARARGS, FrsNoise_smoothNoise2___doc__},
+ {"smoothNoise3", ( PyCFunction ) FrsNoise_smoothNoise3, METH_VARARGS, FrsNoise_smoothNoise3___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsNoise type definition ------------------------------*/
+
+PyTypeObject FrsNoise_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FrsNoise", /* tp_name */
+ sizeof(BPy_FrsNoise), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)FrsNoise___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)FrsNoise___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FrsNoise___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsNoise_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsNoise___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
new file mode 100644
index 00000000000..00b4f3375bc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_FRSNOISE_H
+#define FREESTYLE_PYTHON_FRSNOISE_H
+
+#include <Python.h>
+
+#include "../geometry/Noise.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject FrsNoise_Type;
+
+#define BPy_FrsNoise_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsNoise_Type) )
+
+/*---------------------------Python BPy_FrsNoise structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Noise *n;
+} BPy_FrsNoise;
+
+/*---------------------------Python BPy_FrsNoise visible prototypes-----------*/
+
+int FrsNoise_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_FRSNOISE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp
new file mode 100644
index 00000000000..9254badd95d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Id.cpp
@@ -0,0 +1,222 @@
+#include "BPy_Id.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Id_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Id_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &Id_Type );
+ PyModule_AddObject(module, "Id", (PyObject *)&Id_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Id___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An Id object.\n"
+" :type iBrother: :class:`Id`\n"
+"\n"
+".. method:: __init__(iFirst)\n"
+"\n"
+" Builds an Id from an integer. The second number is set to 0.\n"
+"\n"
+" :arg iFirst: The first Id number.\n"
+" :type iFirst: int\n"
+"\n"
+".. method:: __init__(iFirst, iSecond)\n"
+"\n"
+" Builds the Id from the two numbers.\n"
+"\n"
+" :arg iFirst: The first Id number.\n"
+" :type iFirst: int\n"
+" :arg iSecond: The second Id number.\n"
+" :type iSecond: int\n";
+
+static int Id___init__(BPy_Id *self, PyObject *args, PyObject *kwds)
+{
+ int first = 0, second = 0;
+ static char *kwlist[] = {"first", "second", NULL};
+
+ if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &first, &second) )
+ return -1;
+
+ self->id = new Id( first, second );
+
+ return 0;
+}
+
+static void Id___dealloc__(BPy_Id* self)
+{
+ delete self->id;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Id___repr__(BPy_Id* self)
+{
+ return PyUnicode_FromFormat("[ first: %i, second: %i ](BPy_Id)", self->id->getFirst(), self->id->getSecond() );
+}
+
+static char Id_getFirst___doc__[] =
+".. method:: getFirst()\n"
+"\n"
+" Returns the first Id number.\n"
+"\n"
+" :return: The first Id number.\n"
+" :rtype: int\n";
+
+static PyObject *Id_getFirst( BPy_Id *self ) {
+ return PyLong_FromLong( self->id->getFirst() );
+}
+
+static char Id_getSecond___doc__[] =
+".. method:: getSecond()\n"
+"\n"
+" Returns the second Id number.\n"
+"\n"
+" :return: The second Id number.\n"
+" :rtype: int\n";
+
+static PyObject *Id_getSecond( BPy_Id *self) {
+ return PyLong_FromLong( self->id->getSecond() );
+}
+
+static char Id_setFirst___doc__[] =
+".. method:: setFirst(iFirst)\n"
+"\n"
+" Sets the first number constituting the Id.\n"
+"\n"
+" :arg iFirst: The first number constituting the Id.\n"
+" :type iFirst: int\n";
+
+static PyObject *Id_setFirst( BPy_Id *self , PyObject *args) {
+ unsigned int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return NULL;
+
+ self->id->setFirst( i );
+
+ Py_RETURN_NONE;
+}
+
+static char Id_setSecond___doc__[] =
+".. method:: setSecond(iSecond)\n"
+"\n"
+" Sets the second number constituting the Id.\n"
+"\n"
+" :arg iSecond: The second number constituting the Id.\n"
+" :type iSecond: int\n";
+
+static PyObject *Id_setSecond( BPy_Id *self , PyObject *args) {
+ unsigned int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return NULL;
+
+ self->id->setSecond( i );
+
+ Py_RETURN_NONE;
+}
+
+static PyObject * Id_RichCompare(BPy_Id *o1, BPy_Id *o2, int opid) {
+ switch(opid){
+ case Py_LT:
+ return PyBool_from_bool( o1->id->operator<(*(o2->id)) );
+ break;
+ case Py_LE:
+ return PyBool_from_bool( o1->id->operator<(*(o2->id)) || o1->id->operator<(*(o2->id)) );
+ break;
+ case Py_EQ:
+ return PyBool_from_bool( o1->id->operator==(*(o2->id)) );
+ break;
+ case Py_NE:
+ return PyBool_from_bool( o1->id->operator!=(*(o2->id)) );
+ break;
+ case Py_GT:
+ return PyBool_from_bool(!( o1->id->operator<(*(o2->id)) || o1->id->operator<(*(o2->id)) ));
+ break;
+ case Py_GE:
+ return PyBool_from_bool(!( o1->id->operator<(*(o2->id)) ));
+ break;
+ }
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------Id instance definitions ----------------------------*/
+static PyMethodDef BPy_Id_methods[] = {
+ {"getFirst", ( PyCFunction ) Id_getFirst, METH_NOARGS, Id_getFirst___doc__},
+ {"getSecond", ( PyCFunction ) Id_getSecond, METH_NOARGS, Id_getSecond___doc__},
+ {"setFirst", ( PyCFunction ) Id_setFirst, METH_VARARGS, Id_setFirst___doc__},
+ {"setSecond", ( PyCFunction ) Id_setSecond, METH_VARARGS, Id_setSecond___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Id type definition ------------------------------*/
+
+PyTypeObject Id_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Id", /* tp_name */
+ sizeof(BPy_Id), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Id___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Id___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Id___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ (richcmpfunc)Id_RichCompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Id_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Id___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_Id.h b/source/blender/freestyle/intern/python/BPy_Id.h
new file mode 100644
index 00000000000..10f370f8a80
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Id.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_ID_H
+#define FREESTYLE_PYTHON_ID_H
+
+#include <Python.h>
+#include <iostream>
+using namespace std;
+
+#include "../system/Id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Id_Type;
+
+#define BPy_Id_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Id_Type) )
+
+/*---------------------------Python BPy_Id structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Id *id;
+} BPy_Id;
+
+/*---------------------------Python BPy_Id visible prototypes-----------*/
+
+int Id_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ID_H */
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
new file mode 100644
index 00000000000..050f75a2668
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp
@@ -0,0 +1,248 @@
+#include "BPy_IntegrationType.h"
+
+#include "BPy_Convert.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------ MODULE FUNCTIONS ----------------------------------
+
+static char Integrator_integrate___doc__[] =
+".. function:: integrate(fun, it, it_end, integration_type)\n"
+"\n"
+" Returns a single value from a set of values evaluated at each 0D\n"
+" element of this 1D element.\n"
+"\n"
+" :arg fun: The UnaryFunction0D used to compute a value at each\n"
+" Interface0D.\n"
+" :type fun: :class:`UnaryFunction0D`\n"
+" :arg it: The Interface0DIterator used to iterate over the 0D\n"
+" elements of this 1D element. The integration will occur over\n"
+" the 0D elements starting from the one pointed by it.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :arg it_end: The Interface0DIterator pointing the end of the 0D\n"
+" elements of the 1D element.\n"
+" :type it_end: :class:`Interface0DIterator`\n"
+" :arg integration_type: The integration method used to compute a\n"
+" single value from a set of values.\n"
+" :type integration_type: :class:`IntegrationType`\n"
+" :return: The single value obtained for the 1D element. The return\n"
+" value type is float if fun is of the :class:`UnaryFunction0DDouble`\n"
+" or :class:`UnaryFunction0DFloat` type, and int if fun is of the\n"
+" :class:`UnaryFunction0DUnsigned` type.\n"
+" :rtype: int or float\n";
+
+static PyObject * Integrator_integrate( PyObject *self, PyObject *args )
+{
+ PyObject *obj1, *obj4 = 0;
+ BPy_Interface0DIterator *obj2, *obj3;
+
+#if 1
+ if(!( PyArg_ParseTuple(args, "O!O!O!|O!", &UnaryFunction0D_Type, &obj1,
+ &Interface0DIterator_Type, &obj2, &Interface0DIterator_Type, &obj3,
+ &IntegrationType_Type, &obj4) ))
+ return NULL;
+#else
+ if(!( PyArg_ParseTuple(args, "OOO|O", &obj1, &obj2, &obj3, &obj4) ))
+ return NULL;
+ if(!BPy_UnaryFunction0D_Check(obj1)) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a UnaryFunction0D object");
+ return NULL;
+ }
+ if(!BPy_Interface0DIterator_Check(obj2)) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a Interface0DIterator object");
+ return NULL;
+ }
+ if(!BPy_Interface0DIterator_Check(obj3)) {
+ PyErr_SetString(PyExc_TypeError, "argument 3 must be a Interface0DIterator object");
+ return NULL;
+ }
+ if(obj4 && !BPy_IntegrationType_Check(obj4)) {
+ PyErr_SetString(PyExc_TypeError, "argument 4 must be a IntegrationType object");
+ return NULL;
+ }
+#endif
+
+ Interface0DIterator it(*(obj2->if0D_it)), it_end(*(obj3->if0D_it));
+ IntegrationType t = ( obj4 ) ? IntegrationType_from_BPy_IntegrationType( obj4 ) : MEAN;
+
+ if( BPy_UnaryFunction0DDouble_Check(obj1) ) {
+ UnaryFunction0D<double> *fun = ((BPy_UnaryFunction0DDouble *)obj1)->uf0D_double;
+ double res = integrate( *fun, it, it_end, t );
+ return PyFloat_FromDouble( res );
+
+ } else if( BPy_UnaryFunction0DFloat_Check(obj1) ) {
+ UnaryFunction0D<float> *fun = ((BPy_UnaryFunction0DFloat *)obj1)->uf0D_float;
+ float res = integrate( *fun, it, it_end, t );
+ return PyFloat_FromDouble( res );
+
+ } else if( BPy_UnaryFunction0DUnsigned_Check(obj1) ) {
+ UnaryFunction0D<unsigned int> *fun = ((BPy_UnaryFunction0DUnsigned *)obj1)->uf0D_unsigned;
+ unsigned int res = integrate( *fun, it, it_end, t );
+ return PyLong_FromLong( res );
+
+ } else {
+ string msg("unsupported function type: " + string(obj1->ob_type->tp_name));
+ PyErr_SetString(PyExc_TypeError, msg.c_str());
+ return NULL;
+ }
+}
+
+/*-----------------------Integrator module docstring---------------------------------------*/
+
+static char module_docstring[] = "The Blender Freestyle.Integrator submodule\n\n";
+
+/*-----------------------Integrator module functions definitions---------------------------*/
+
+static PyMethodDef module_functions[] = {
+ {"integrate", (PyCFunction) Integrator_integrate, METH_VARARGS, Integrator_integrate___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------Integrator module definition--------------------------------------*/
+
+static PyModuleDef module_definition = {
+ PyModuleDef_HEAD_INIT,
+ "Freestyle.Integrator",
+ module_docstring,
+ -1,
+ module_functions
+};
+
+/*-----------------------BPy_IntegrationType type definition ------------------------------*/
+
+static char IntegrationType___doc__[] =
+"Different integration methods that can be invoked to integrate into a\n"
+"single value the set of values obtained from each 0D element of an 1D\n"
+"element:\n"
+"\n"
+"* IntegrationType.MEAN: The value computed for the 1D element is the\n"
+" mean of the values obtained for the 0D elements.\n"
+"* IntegrationType.MIN: The value computed for the 1D element is the\n"
+" minimum of the values obtained for the 0D elements.\n"
+"* IntegrationType.MAX: The value computed for the 1D element is the\n"
+" maximum of the values obtained for the 0D elements.\n"
+"* IntegrationType.FIRST: The value computed for the 1D element is the\n"
+" first of the values obtained for the 0D elements.\n"
+"* IntegrationType.LAST: The value computed for the 1D element is the\n"
+" last of the values obtained for the 0D elements.\n";
+
+PyTypeObject IntegrationType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IntegrationType", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ IntegrationType___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
+
+static PyLongObject _IntegrationType_MEAN = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MEAN }
+};
+static PyLongObject _IntegrationType_MIN = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MIN }
+};
+static PyLongObject _IntegrationType_MAX = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { MAX }
+};
+static PyLongObject _IntegrationType_FIRST = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { FIRST }
+};
+static PyLongObject _IntegrationType_LAST = {
+ PyVarObject_HEAD_INIT(&IntegrationType_Type, 1)
+ { LAST }
+};
+
+#define BPy_IntegrationType_MEAN ((PyObject *)&_IntegrationType_MEAN)
+#define BPy_IntegrationType_MIN ((PyObject *)&_IntegrationType_MIN)
+#define BPy_IntegrationType_MAX ((PyObject *)&_IntegrationType_MAX)
+#define BPy_IntegrationType_FIRST ((PyObject *)&_IntegrationType_FIRST)
+#define BPy_IntegrationType_LAST ((PyObject *)&_IntegrationType_LAST)
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int IntegrationType_Init( PyObject *module )
+{
+ PyObject *m, *d, *f;
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &IntegrationType_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IntegrationType_Type );
+ PyModule_AddObject(module, "IntegrationType", (PyObject *)&IntegrationType_Type);
+
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "MEAN", BPy_IntegrationType_MEAN);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "MIN", BPy_IntegrationType_MIN);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "MAX", BPy_IntegrationType_MAX);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "FIRST", BPy_IntegrationType_FIRST);
+ PyDict_SetItemString( IntegrationType_Type.tp_dict, "LAST", BPy_IntegrationType_LAST);
+
+ m = PyModule_Create(&module_definition);
+ if (m == NULL)
+ return -1;
+ Py_INCREF(m);
+ PyModule_AddObject(module, "Integrator", m);
+
+ // from Integrator import *
+ d = PyModule_GetDict(m);
+ for (PyMethodDef *p = module_functions; p->ml_name; p++) {
+ f = PyDict_GetItemString(d, p->ml_name);
+ Py_INCREF(f);
+ PyModule_AddObject(module, p->ml_name, f);
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.h b/source/blender/freestyle/intern/python/BPy_IntegrationType.h
new file mode 100644
index 00000000000..f15ae8309e3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.h
@@ -0,0 +1,28 @@
+#ifndef FREESTYLE_PYTHON_INTEGRATIONTYPE_H
+#define FREESTYLE_PYTHON_INTEGRATIONTYPE_H
+
+#include <Python.h>
+
+#include "../view_map/Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject IntegrationType_Type;
+
+#define BPy_IntegrationType_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IntegrationType_Type) )
+
+/*---------------------------Python BPy_IntegrationType visible prototypes-----------*/
+
+int IntegrationType_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTEGRATIONTYPE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp
new file mode 100644
index 00000000000..adf26def931
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp
@@ -0,0 +1,354 @@
+#include "BPy_Interface0D.h"
+
+#include "BPy_Convert.h"
+#include "Interface0D/BPy_CurvePoint.h"
+#include "Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface0D/ViewVertex/BPy_NonTVertex.h"
+#include "Interface0D/ViewVertex/BPy_TVertex.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Interface0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Interface0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Interface0D_Type );
+ PyModule_AddObject(module, "Interface0D", (PyObject *)&Interface0D_Type);
+
+ if( PyType_Ready( &CurvePoint_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurvePoint_Type );
+ PyModule_AddObject(module, "CurvePoint", (PyObject *)&CurvePoint_Type);
+
+ if( PyType_Ready( &SVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SVertex_Type );
+ PyModule_AddObject(module, "SVertex", (PyObject *)&SVertex_Type);
+
+ if( PyType_Ready( &ViewVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewVertex_Type );
+ PyModule_AddObject(module, "ViewVertex", (PyObject *)&ViewVertex_Type);
+
+ if( PyType_Ready( &StrokeVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeVertex_Type );
+ PyModule_AddObject(module, "StrokeVertex", (PyObject *)&StrokeVertex_Type);
+
+ if( PyType_Ready( &NonTVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &NonTVertex_Type );
+ PyModule_AddObject(module, "NonTVertex", (PyObject *)&NonTVertex_Type);
+
+ if( PyType_Ready( &TVertex_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TVertex_Type );
+ PyModule_AddObject(module, "TVertex", (PyObject *)&TVertex_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Interface0D___doc__[] =
+"Base class for any 0D element.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int Interface0D___init__(BPy_Interface0D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->if0D = new Interface0D();
+ self->borrowed = 0;
+ return 0;
+}
+
+static void Interface0D___dealloc__(BPy_Interface0D* self)
+{
+ if( self->if0D && !self->borrowed )
+ delete self->if0D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Interface0D___repr__(BPy_Interface0D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->if0D->getExactTypeName().c_str(), self->if0D );
+}
+
+static char Interface0D_getExactTypeName___doc__[] =
+".. method:: getExactTypeName()\n"
+"\n"
+" Returns the name of the 0D element.\n"
+"\n"
+" :return: Name of the interface.\n"
+" :rtype: string\n";
+
+static PyObject *Interface0D_getExactTypeName( BPy_Interface0D *self ) {
+ return PyUnicode_FromFormat( self->if0D->getExactTypeName().c_str() );
+}
+
+static char Interface0D_getX___doc__[] =
+".. method:: getX()\n"
+"\n"
+" Returns the X coordinate of the 3D point of the 0D element.\n"
+"\n"
+" :return: The X coordinate of the 3D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getX( BPy_Interface0D *self ) {
+ double x = self->if0D->getX();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( x );
+}
+
+static char Interface0D_getY___doc__[] =
+".. method:: getY()\n"
+"\n"
+" Returns the Y coordinate of the 3D point of the 0D element.\n"
+"\n"
+" :return: The Y coordinate of the 3D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getY( BPy_Interface0D *self ) {
+ double y = self->if0D->getY();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( y );
+}
+
+static char Interface0D_getZ___doc__[] =
+".. method:: getZ()\n"
+"\n"
+" Returns the Z coordinate of the 3D point of the 0D element.\n"
+"\n"
+" :return: The Z coordinate of the 3D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getZ( BPy_Interface0D *self ) {
+ double z = self->if0D->getZ();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( z );
+}
+
+static char Interface0D_getPoint3D___doc__[] =
+".. method:: getPoint3D()\n"
+"\n"
+" Returns the location of the 0D element in the 3D space.\n"
+"\n"
+" :return: The 3D point of the 0D element.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Interface0D_getPoint3D( BPy_Interface0D *self ) {
+ Vec3f v( self->if0D->getPoint3D() );
+ if (PyErr_Occurred())
+ return NULL;
+ return Vector_from_Vec3f( v );
+}
+
+static char Interface0D_getProjectedX___doc__[] =
+".. method:: getProjectedX()\n"
+"\n"
+" Returns the X coordinate of the 2D point of the 0D element.\n"
+"\n"
+" :return: The X coordinate of the 2D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getProjectedX( BPy_Interface0D *self ) {
+ double x = self->if0D->getProjectedX();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( x );
+}
+
+static char Interface0D_getProjectedY___doc__[] =
+".. method:: getProjectedY()\n"
+"\n"
+" Returns the Y coordinate of the 2D point of the 0D element.\n"
+"\n"
+" :return: The Y coordinate of the 2D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getProjectedY( BPy_Interface0D *self ) {
+ double y = self->if0D->getProjectedY();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( y );
+}
+
+static char Interface0D_getProjectedZ___doc__[] =
+".. method:: getProjectedZ()\n"
+"\n"
+" Returns the Z coordinate of the 2D point of the 0D element.\n"
+"\n"
+" :return: The Z coordinate of the 2D point.\n"
+" :rtype: float\n";
+
+static PyObject *Interface0D_getProjectedZ( BPy_Interface0D *self ) {
+ double z = self->if0D->getProjectedZ();
+ if (PyErr_Occurred())
+ return NULL;
+ return PyFloat_FromDouble( z );
+}
+
+static char Interface0D_getPoint2D___doc__[] =
+".. method:: getPoint2D()\n"
+"\n"
+" Returns the location of the 0D element in the 2D space.\n"
+"\n"
+" :return: The 2D point of the 0D element.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *Interface0D_getPoint2D( BPy_Interface0D *self ) {
+ Vec2f v( self->if0D->getPoint2D() );
+ if (PyErr_Occurred())
+ return NULL;
+ return Vector_from_Vec2f( v );
+}
+
+static char Interface0D_getFEdge___doc__[] =
+".. method:: getFEdge(inter)\n"
+"\n"
+" Returns the FEdge that lies between this 0D element and the 0D\n"
+" element given as the argument.\n"
+"\n"
+" :arg inter: A 0D element.\n"
+" :type inter: :class:`Interface0D`\n"
+" :return: The FEdge lying between the two 0D elements.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject *Interface0D_getFEdge( BPy_Interface0D *self, PyObject *args ) {
+ PyObject *py_if0D;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Interface0D_Type, &py_if0D) ))
+ return NULL;
+
+ FEdge *fe = self->if0D->getFEdge(*( ((BPy_Interface0D *) py_if0D)->if0D ));
+ if (PyErr_Occurred())
+ return NULL;
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+static char Interface0D_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the identifier of the 0D element.\n"
+"\n"
+" :return: The identifier of the 0D element.\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject *Interface0D_getId( BPy_Interface0D *self ) {
+ Id id( self->if0D->getId() );
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Id_from_Id( id );
+}
+
+static char Interface0D_getNature___doc__[] =
+".. method:: getNature()\n"
+"\n"
+" Returns the nature of the 0D element.\n"
+"\n"
+" :return: The nature of the 0D element.\n"
+" :rtype: :class:`Nature`\n";
+
+static PyObject *Interface0D_getNature( BPy_Interface0D *self ) {
+ Nature::VertexNature nature = self->if0D->getNature();
+ if (PyErr_Occurred())
+ return NULL;
+ return BPy_Nature_from_Nature( nature );
+}
+
+/*----------------------Interface0D instance definitions ----------------------------*/
+static PyMethodDef BPy_Interface0D_methods[] = {
+ {"getExactTypeName", ( PyCFunction ) Interface0D_getExactTypeName, METH_NOARGS, Interface0D_getExactTypeName___doc__},
+ {"getX", ( PyCFunction ) Interface0D_getX, METH_NOARGS, Interface0D_getX___doc__},
+ {"getY", ( PyCFunction ) Interface0D_getY, METH_NOARGS, Interface0D_getY___doc__},
+ {"getZ", ( PyCFunction ) Interface0D_getZ, METH_NOARGS, Interface0D_getZ___doc__},
+ {"getPoint3D", ( PyCFunction ) Interface0D_getPoint3D, METH_NOARGS, Interface0D_getPoint3D___doc__},
+ {"getProjectedX", ( PyCFunction ) Interface0D_getProjectedX, METH_NOARGS, Interface0D_getProjectedX___doc__},
+ {"getProjectedY", ( PyCFunction ) Interface0D_getProjectedY, METH_NOARGS, Interface0D_getProjectedY___doc__},
+ {"getProjectedZ", ( PyCFunction ) Interface0D_getProjectedZ, METH_NOARGS, Interface0D_getProjectedZ___doc__},
+ {"getPoint2D", ( PyCFunction ) Interface0D_getPoint2D, METH_NOARGS, Interface0D_getPoint2D___doc__},
+ {"getFEdge", ( PyCFunction ) Interface0D_getFEdge, METH_VARARGS, Interface0D_getFEdge___doc__},
+ {"getId", ( PyCFunction ) Interface0D_getId, METH_NOARGS, Interface0D_getId___doc__},
+ {"getNature", ( PyCFunction ) Interface0D_getNature, METH_NOARGS, Interface0D_getNature___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Interface0D type definition ------------------------------*/
+
+PyTypeObject Interface0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface0D", /* tp_name */
+ sizeof(BPy_Interface0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Interface0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Interface0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Interface0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Interface0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0 /* tp_del */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.h b/source/blender/freestyle/intern/python/BPy_Interface0D.h
new file mode 100644
index 00000000000..25134db5352
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface0D.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_INTERFACE0D_H
+#define FREESTYLE_PYTHON_INTERFACE0D_H
+
+#include <Python.h>
+
+#include "../view_map/Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Interface0D_Type;
+
+#define BPy_Interface0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface0D_Type) )
+
+/*---------------------------Python BPy_Interface0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Interface0D *if0D;
+ int borrowed; /* non-zero if *if0D is a borrowed object */
+} BPy_Interface0D;
+
+/*---------------------------Python BPy_Interface0D visible prototypes-----------*/
+
+int Interface0D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTERFACE0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.cpp b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp
new file mode 100644
index 00000000000..f35ef62030d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp
@@ -0,0 +1,337 @@
+#include "BPy_Interface1D.h"
+
+#include "BPy_Convert.h"
+#include "Interface1D/BPy_FrsCurve.h"
+#include "Interface1D/Curve/BPy_Chain.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/FEdge/BPy_FEdgeSharp.h"
+#include "Interface1D/FEdge/BPy_FEdgeSmooth.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+
+#include "BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Interface1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Interface1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Interface1D_Type );
+ PyModule_AddObject(module, "Interface1D", (PyObject *)&Interface1D_Type);
+
+ if( PyType_Ready( &FrsCurve_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FrsCurve_Type );
+ PyModule_AddObject(module, "FrsCurve", (PyObject *)&FrsCurve_Type);
+
+ if( PyType_Ready( &Chain_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Chain_Type );
+ PyModule_AddObject(module, "Chain", (PyObject *)&Chain_Type);
+
+ if( PyType_Ready( &FEdge_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FEdge_Type );
+ PyModule_AddObject(module, "FEdge", (PyObject *)&FEdge_Type);
+
+ if( PyType_Ready( &FEdgeSharp_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FEdgeSharp_Type );
+ PyModule_AddObject(module, "FEdgeSharp", (PyObject *)&FEdgeSharp_Type);
+
+ if( PyType_Ready( &FEdgeSmooth_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FEdgeSmooth_Type );
+ PyModule_AddObject(module, "FEdgeSmooth", (PyObject *)&FEdgeSmooth_Type);
+
+ if( PyType_Ready( &Stroke_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Stroke_Type );
+ PyModule_AddObject(module, "Stroke", (PyObject *)&Stroke_Type);
+
+ PyDict_SetItemString( Stroke_Type.tp_dict, "DRY_MEDIUM", BPy_MediumType_DRY_MEDIUM );
+ PyDict_SetItemString( Stroke_Type.tp_dict, "HUMID_MEDIUM", BPy_MediumType_HUMID_MEDIUM );
+ PyDict_SetItemString( Stroke_Type.tp_dict, "OPAQUE_MEDIUM", BPy_MediumType_OPAQUE_MEDIUM );
+
+ if( PyType_Ready( &ViewEdge_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewEdge_Type );
+ PyModule_AddObject(module, "ViewEdge", (PyObject *)&ViewEdge_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Interface1D___doc__[] =
+"Base class for any 1D element.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int Interface1D___init__(BPy_Interface1D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->if1D = new Interface1D();
+ self->borrowed = 0;
+ return 0;
+}
+
+static void Interface1D___dealloc__(BPy_Interface1D* self)
+{
+ if( self->if1D && !self->borrowed )
+ delete self->if1D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Interface1D___repr__(BPy_Interface1D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->if1D->getExactTypeName().c_str(), self->if1D );
+}
+
+static char Interface1D_getExactTypeName___doc__[] =
+".. method:: getExactTypeName()\n"
+"\n"
+" Returns the string of the name of the 1D element.\n"
+"\n"
+" :return: The name of the 1D element.\n"
+" :rtype: string\n";
+
+static PyObject *Interface1D_getExactTypeName( BPy_Interface1D *self ) {
+ return PyUnicode_FromFormat( self->if1D->getExactTypeName().c_str() );
+}
+
+#if 0
+static PyObject *Interface1D_getVertices( BPy_Interface1D *self ) {
+ return PyList_New(0);
+}
+
+static PyObject *Interface1D_getPoints( BPy_Interface1D *self ) {
+ return PyList_New(0);
+}
+#endif
+
+static char Interface1D_getLength2D___doc__[] =
+".. method:: getLength2D()\n"
+"\n"
+" Returns the 2D length of the 1D element.\n"
+"\n"
+" :return: The 2D length of the 1D element.\n"
+" :rtype: float\n";
+
+static PyObject *Interface1D_getLength2D( BPy_Interface1D *self ) {
+ return PyFloat_FromDouble( (double) self->if1D->getLength2D() );
+}
+
+static char Interface1D_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the Id of the 1D element .\n"
+"\n"
+" :return: The Id of the 1D element .\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject *Interface1D_getId( BPy_Interface1D *self ) {
+ Id id( self->if1D->getId() );
+ return BPy_Id_from_Id( id );
+}
+
+static char Interface1D_getNature___doc__[] =
+".. method:: getNature()\n"
+"\n"
+" Returns the nature of the 1D element.\n"
+"\n"
+" :return: The nature of the 1D element.\n"
+" :rtype: :class:`Nature`\n";
+
+static PyObject *Interface1D_getNature( BPy_Interface1D *self ) {
+ return BPy_Nature_from_Nature( self->if1D->getNature() );
+}
+
+static char Interface1D_getTimeStamp___doc__[] =
+".. method:: getTimeStamp()\n"
+"\n"
+" Returns the time stamp of the 1D element. Mainly used for selection.\n"
+"\n"
+" :return: The time stamp of the 1D element.\n"
+" :rtype: int\n";
+
+static PyObject *Interface1D_getTimeStamp( BPy_Interface1D *self ) {
+ return PyLong_FromLong( self->if1D->getTimeStamp() );
+}
+
+static char Interface1D_setTimeStamp___doc__[] =
+".. method:: setTimeStamp(iTimeStamp)\n"
+"\n"
+" Sets the time stamp for the 1D element.\n"
+"\n"
+" :arg iTimeStamp: A time stamp.\n"
+" :type iTimeStamp: int\n";
+
+static PyObject *Interface1D_setTimeStamp( BPy_Interface1D *self, PyObject *args) {
+ int timestamp = 0 ;
+
+ if( !PyArg_ParseTuple(args, "i", &timestamp) )
+ return NULL;
+
+ self->if1D->setTimeStamp( timestamp );
+
+ Py_RETURN_NONE;
+}
+
+static char Interface1D_verticesBegin___doc__[] =
+".. method:: verticesBegin()\n"
+"\n"
+" Returns an iterator over the Interface1D vertices, pointing to the\n"
+" first vertex.\n"
+"\n"
+" :return: An Interface0DIterator pointing to the first vertex.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_verticesBegin( BPy_Interface1D *self ) {
+ Interface0DIterator if0D_it( self->if1D->verticesBegin() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 0 );
+}
+
+static char Interface1D_verticesEnd___doc__[] =
+".. method:: verticesEnd()\n"
+"\n"
+" Returns an iterator over the Interface1D vertices, pointing after\n"
+" the last vertex.\n"
+"\n"
+" :return: An Interface0DIterator pointing after the last vertex.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_verticesEnd( BPy_Interface1D *self ) {
+ Interface0DIterator if0D_it( self->if1D->verticesEnd() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 1 );
+}
+
+static char Interface1D_pointsBegin___doc__[] =
+".. method:: pointsBegin(t=0.0)\n"
+"\n"
+" Returns an iterator over the Interface1D points, pointing to the\n"
+" first point. The difference with verticesBegin() is that here we can\n"
+" iterate over points of the 1D element at a any given sampling.\n"
+" Indeed, for each iteration, a virtual point is created.\n"
+"\n"
+" :arg t: A sampling with which we want to iterate over points of\n"
+" this 1D element.\n"
+" :type t: float\n"
+" :return: An Interface0DIterator pointing to the first point.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_pointsBegin( BPy_Interface1D *self, PyObject *args ) {
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return NULL;
+
+ Interface0DIterator if0D_it( self->if1D->pointsBegin(f) );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 0 );
+}
+
+static char Interface1D_pointsEnd___doc__[] =
+".. method:: pointsEnd(t=0.0)\n"
+"\n"
+" Returns an iterator over the Interface1D points, pointing after the\n"
+" last point. The difference with verticesEnd() is that here we can\n"
+" iterate over points of the 1D element at a given sampling. Indeed,\n"
+" for each iteration, a virtual point is created.\n"
+"\n"
+" :arg t: A sampling with which we want to iterate over points of\n"
+" this 1D element.\n"
+" :type t: float\n"
+" :return: An Interface0DIterator pointing after the last point.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * Interface1D_pointsEnd( BPy_Interface1D *self, PyObject *args ) {
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return NULL;
+
+ Interface0DIterator if0D_it( self->if1D->pointsEnd(f) );
+ return BPy_Interface0DIterator_from_Interface0DIterator( if0D_it, 1 );
+}
+
+/*----------------------Interface1D instance definitions ----------------------------*/
+static PyMethodDef BPy_Interface1D_methods[] = {
+ {"getExactTypeName", ( PyCFunction ) Interface1D_getExactTypeName, METH_NOARGS, Interface1D_getExactTypeName___doc__},
+#if 0
+ {"getVertices", ( PyCFunction ) Interface1D_getVertices, METH_NOARGS, "Returns the vertices"},
+ {"getPoints", ( PyCFunction ) Interface1D_getPoints, METH_NOARGS, "Returns the points. The difference with getVertices() is that here we can iterate over points of the 1D element at any given sampling. At each call, a virtual point is created."},
+#endif
+ {"getLength2D", ( PyCFunction ) Interface1D_getLength2D, METH_NOARGS, Interface1D_getLength2D___doc__},
+ {"getId", ( PyCFunction ) Interface1D_getId, METH_NOARGS, Interface1D_getId___doc__},
+ {"getNature", ( PyCFunction ) Interface1D_getNature, METH_NOARGS, Interface1D_getNature___doc__},
+ {"getTimeStamp", ( PyCFunction ) Interface1D_getTimeStamp, METH_NOARGS, Interface1D_getTimeStamp___doc__},
+ {"setTimeStamp", ( PyCFunction ) Interface1D_setTimeStamp, METH_VARARGS, Interface1D_setTimeStamp___doc__},
+ {"verticesBegin", ( PyCFunction ) Interface1D_verticesBegin, METH_NOARGS, Interface1D_verticesBegin___doc__},
+ {"verticesEnd", ( PyCFunction ) Interface1D_verticesEnd, METH_NOARGS, Interface1D_verticesEnd___doc__},
+ {"pointsBegin", ( PyCFunction ) Interface1D_pointsBegin, METH_VARARGS, Interface1D_pointsBegin___doc__},
+ {"pointsEnd", ( PyCFunction ) Interface1D_pointsEnd, METH_VARARGS, Interface1D_pointsEnd___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Interface1D type definition ------------------------------*/
+
+PyTypeObject Interface1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface1D", /* tp_name */
+ sizeof(BPy_Interface1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Interface1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Interface1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Interface1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Interface1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.h b/source/blender/freestyle/intern/python/BPy_Interface1D.h
new file mode 100644
index 00000000000..75eefa1836f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Interface1D.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_INTERFACE1D_H
+#define FREESTYLE_PYTHON_INTERFACE1D_H
+
+#include <Python.h>
+
+#include "../view_map/Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Interface1D_Type;
+
+#define BPy_Interface1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface1D_Type) )
+
+/*---------------------------Python BPy_Interface1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Interface1D *if1D;
+ int borrowed; /* non-zero if *if1D is a borrowed object */
+} BPy_Interface1D;
+
+/*---------------------------Python BPy_Interface1D visible prototypes-----------*/
+
+int Interface1D_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTERFACE1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.cpp b/source/blender/freestyle/intern/python/BPy_Iterator.cpp
new file mode 100644
index 00000000000..83601c05b1a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Iterator.cpp
@@ -0,0 +1,229 @@
+#include "BPy_Iterator.h"
+
+#include "BPy_Convert.h"
+#include "Iterator/BPy_AdjacencyIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Iterator/BPy_CurvePointIterator.h"
+#include "Iterator/BPy_StrokeVertexIterator.h"
+#include "Iterator/BPy_SVertexIterator.h"
+#include "Iterator/BPy_orientedViewEdgeIterator.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_ChainPredicateIterator.h"
+#include "Iterator/BPy_ChainSilhouetteIterator.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Iterator_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Iterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Iterator_Type );
+ PyModule_AddObject(module, "Iterator", (PyObject *)&Iterator_Type);
+
+ if( PyType_Ready( &AdjacencyIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &AdjacencyIterator_Type );
+ PyModule_AddObject(module, "AdjacencyIterator", (PyObject *)&AdjacencyIterator_Type);
+
+ if( PyType_Ready( &Interface0DIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Interface0DIterator_Type );
+ PyModule_AddObject(module, "Interface0DIterator", (PyObject *)&Interface0DIterator_Type);
+
+ if( PyType_Ready( &CurvePointIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurvePointIterator_Type );
+ PyModule_AddObject(module, "CurvePointIterator", (PyObject *)&CurvePointIterator_Type);
+
+ if( PyType_Ready( &StrokeVertexIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeVertexIterator_Type );
+ PyModule_AddObject(module, "StrokeVertexIterator", (PyObject *)&StrokeVertexIterator_Type);
+
+ if( PyType_Ready( &SVertexIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SVertexIterator_Type );
+ PyModule_AddObject(module, "SVertexIterator", (PyObject *)&SVertexIterator_Type);
+
+ if( PyType_Ready( &orientedViewEdgeIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &orientedViewEdgeIterator_Type );
+ PyModule_AddObject(module, "orientedViewEdgeIterator", (PyObject *)&orientedViewEdgeIterator_Type);
+
+ if( PyType_Ready( &ViewEdgeIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ViewEdgeIterator_Type );
+ PyModule_AddObject(module, "ViewEdgeIterator", (PyObject *)&ViewEdgeIterator_Type);
+
+ if( PyType_Ready( &ChainingIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainingIterator_Type );
+ PyModule_AddObject(module, "ChainingIterator", (PyObject *)&ChainingIterator_Type);
+
+ if( PyType_Ready( &ChainPredicateIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainPredicateIterator_Type );
+ PyModule_AddObject(module, "ChainPredicateIterator", (PyObject *)&ChainPredicateIterator_Type);
+
+ if( PyType_Ready( &ChainSilhouetteIterator_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainSilhouetteIterator_Type );
+ PyModule_AddObject(module, "ChainSilhouetteIterator", (PyObject *)&ChainSilhouetteIterator_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Iterator___doc__[] =
+"Base class to define iterators.\n";
+
+static void Iterator___dealloc__(BPy_Iterator* self)
+{
+ if (self->it)
+ delete self->it;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * Iterator___repr__(BPy_Iterator* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->it->getExactTypeName().c_str(), self->it );
+}
+
+static char Iterator_getExactTypeName___doc__[] =
+".. method:: getExactTypeName()\n"
+"\n"
+" Returns the name of the iterator.\n"
+"\n"
+" :return: The name of the iterator.\n"
+" :rtype: string\n";
+
+static PyObject * Iterator_getExactTypeName(BPy_Iterator* self) {
+ return PyUnicode_FromFormat( self->it->getExactTypeName().c_str() );
+}
+
+static char Iterator_increment___doc__[] =
+".. method:: increment()\n"
+"\n"
+" Makes the iterator point the next element.\n";
+
+static PyObject * Iterator_increment(BPy_Iterator* self) {
+ if (self->it->isEnd()) {
+ PyErr_SetString(PyExc_RuntimeError , "cannot increment any more");
+ return NULL;
+ }
+ self->it->increment();
+
+ Py_RETURN_NONE;
+}
+
+static char Iterator_decrement___doc__[] =
+".. method:: decrement()\n"
+"\n"
+" Makes the iterator point the previous element.\n";
+
+static PyObject * Iterator_decrement(BPy_Iterator* self) {
+ if (self->it->isBegin()) {
+ PyErr_SetString(PyExc_RuntimeError , "cannot decrement any more");
+ return NULL;
+ }
+ self->it->decrement();
+
+ Py_RETURN_NONE;
+}
+
+static char Iterator_isBegin___doc__[] =
+".. method:: isBegin()\n"
+"\n"
+" Returns true if the interator points the first element.\n"
+"\n"
+" :return: True if the interator points the first element.\n"
+" :rtype: bool\n";
+
+static PyObject * Iterator_isBegin(BPy_Iterator* self) {
+ return PyBool_from_bool( self->it->isBegin() );
+}
+
+static char Iterator_isEnd___doc__[] =
+".. method:: isEnd()\n"
+"\n"
+" Returns true if the interator points the last element.\n"
+"\n"
+" :return: True if the interator points the last element.\n"
+" :rtype: bool\n";
+
+static PyObject * Iterator_isEnd(BPy_Iterator* self) {
+ return PyBool_from_bool( self->it->isEnd() );
+}
+
+/*----------------------Iterator instance definitions ----------------------------*/
+static PyMethodDef BPy_Iterator_methods[] = {
+ {"getExactTypeName", ( PyCFunction ) Iterator_getExactTypeName, METH_NOARGS, Iterator_getExactTypeName___doc__},
+ {"increment", ( PyCFunction ) Iterator_increment, METH_NOARGS, Iterator_increment___doc__},
+ {"decrement", ( PyCFunction ) Iterator_decrement, METH_NOARGS, Iterator_decrement___doc__},
+ {"isBegin", ( PyCFunction ) Iterator_isBegin, METH_NOARGS, Iterator_isBegin___doc__},
+ {"isEnd", ( PyCFunction ) Iterator_isEnd, METH_NOARGS, Iterator_isEnd___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Iterator type definition ------------------------------*/
+
+PyTypeObject Iterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Iterator", /* tp_name */
+ sizeof(BPy_Iterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Iterator___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)Iterator___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Iterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Iterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.h b/source/blender/freestyle/intern/python/BPy_Iterator.h
new file mode 100644
index 00000000000..0bdb52ef9a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Iterator.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_ITERATOR_H
+#define FREESTYLE_PYTHON_ITERATOR_H
+
+#include <Python.h>
+
+#include "../system/Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Iterator_Type;
+
+#define BPy_Iterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Iterator_Type) )
+
+/*---------------------------Python BPy_Iterator structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ Iterator *it;
+} BPy_Iterator;
+
+/*---------------------------Python BPy_Iterator visible prototypes-----------*/
+
+int Iterator_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.cpp b/source/blender/freestyle/intern/python/BPy_MediumType.cpp
new file mode 100644
index 00000000000..63a889e4786
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_MediumType.cpp
@@ -0,0 +1,97 @@
+#include "BPy_MediumType.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+/*-----------------------BPy_MediumType type definition ------------------------------*/
+
+static char MediumType___doc__[] =
+"The different blending modes available to similate the interaction\n"
+"media-medium:\n"
+"\n"
+"* Stroke.DRY_MEDIUM: To simulate a dry medium such as Pencil or Charcoal.\n"
+"* Stroke.HUMID_MEDIUM: To simulate ink painting (color substraction blending).\n"
+"* Stroke.OPAQUE_MEDIUM: To simulate an opaque medium (oil, spray...).\n";
+
+PyTypeObject MediumType_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "MediumType", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ MediumType___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_IntegrationType instance definitions -------------------------*/
+
+PyLongObject _BPy_MediumType_DRY_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::DRY_MEDIUM }
+};
+PyLongObject _BPy_MediumType_HUMID_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::HUMID_MEDIUM }
+};
+PyLongObject _BPy_MediumType_OPAQUE_MEDIUM = {
+ PyVarObject_HEAD_INIT(&MediumType_Type, 1)
+ { Stroke::OPAQUE_MEDIUM }
+};
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int MediumType_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &MediumType_Type ) < 0 )
+ return -1;
+ Py_INCREF( &MediumType_Type );
+ PyModule_AddObject(module, "MediumType", (PyObject *)&MediumType_Type);
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.h b/source/blender/freestyle/intern/python/BPy_MediumType.h
new file mode 100644
index 00000000000..3bc50477295
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_MediumType.h
@@ -0,0 +1,42 @@
+#ifndef FREESTYLE_PYTHON_MEDIUMTYPE_H
+#define FREESTYLE_PYTHON_MEDIUMTYPE_H
+
+#include <Python.h>
+
+#include "../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject MediumType_Type;
+
+#define BPy_MediumType_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &MediumType_Type) )
+
+/*---------------------------Python BPy_MediumType structure definition----------*/
+typedef struct {
+ PyLongObject i;
+} BPy_MediumType;
+
+/*---------------------------Python BPy_MediumType visible prototypes-----------*/
+
+int MediumType_Init( PyObject *module );
+
+// internal constants
+extern PyLongObject _BPy_MediumType_DRY_MEDIUM;
+extern PyLongObject _BPy_MediumType_HUMID_MEDIUM;
+extern PyLongObject _BPy_MediumType_OPAQUE_MEDIUM;
+// public constants
+#define BPy_MediumType_DRY_MEDIUM ((PyObject *)&_BPy_MediumType_DRY_MEDIUM)
+#define BPy_MediumType_HUMID_MEDIUM ((PyObject *)&_BPy_MediumType_HUMID_MEDIUM)
+#define BPy_MediumType_OPAQUE_MEDIUM ((PyObject *)&_BPy_MediumType_OPAQUE_MEDIUM)
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_MEDIUMTYPE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Nature.cpp b/source/blender/freestyle/intern/python/BPy_Nature.cpp
new file mode 100644
index 00000000000..3907ea75a66
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Nature.cpp
@@ -0,0 +1,296 @@
+#include "BPy_Nature.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+static PyObject *BPy_Nature___and__(PyObject *a, PyObject *b);
+static PyObject *BPy_Nature___xor__(PyObject *a, PyObject *b);
+static PyObject *BPy_Nature___or__(PyObject *a, PyObject *b);
+static int BPy_Nature_bool(PyObject *v);
+
+/*-----------------------BPy_Nature number method definitions --------------------*/
+
+PyNumberMethods nature_as_number = {
+ 0, /* binaryfunc nb_add */
+ 0, /* binaryfunc nb_subtract */
+ 0, /* binaryfunc nb_multiply */
+ 0, /* binaryfunc nb_remainder */
+ 0, /* binaryfunc nb_divmod */
+ 0, /* ternaryfunc nb_power */
+ 0, /* unaryfunc nb_negative */
+ 0, /* unaryfunc nb_positive */
+ 0, /* unaryfunc nb_absolute */
+ (inquiry)BPy_Nature_bool, /* inquiry nb_bool */
+ 0, /* unaryfunc nb_invert */
+ 0, /* binaryfunc nb_lshift */
+ 0, /* binaryfunc nb_rshift */
+ (binaryfunc)BPy_Nature___and__, /* binaryfunc nb_and */
+ (binaryfunc)BPy_Nature___xor__, /* binaryfunc nb_xor */
+ (binaryfunc)BPy_Nature___or__, /* binaryfunc nb_or */
+ 0, /* unaryfunc nb_int */
+ 0, /* void *nb_reserved */
+ 0, /* unaryfunc nb_float */
+ 0, /* binaryfunc nb_inplace_add */
+ 0, /* binaryfunc nb_inplace_subtract */
+ 0, /* binaryfunc nb_inplace_multiply */
+ 0, /* binaryfunc nb_inplace_remainder */
+ 0, /* ternaryfunc nb_inplace_power */
+ 0, /* binaryfunc nb_inplace_lshift */
+ 0, /* binaryfunc nb_inplace_rshift */
+ 0, /* binaryfunc nb_inplace_and */
+ 0, /* binaryfunc nb_inplace_xor */
+ 0, /* binaryfunc nb_inplace_or */
+ 0, /* binaryfunc nb_floor_divide */
+ 0, /* binaryfunc nb_true_divide */
+ 0, /* binaryfunc nb_inplace_floor_divide */
+ 0, /* binaryfunc nb_inplace_true_divide */
+ 0, /* unaryfunc nb_index */
+};
+
+/*-----------------------BPy_Nature docstring ------------------------------------*/
+
+static char Nature___doc__[] =
+"Different possible natures of 0D and 1D elements of the ViewMap.\n"
+"\n"
+"Vertex natures:\n"
+"\n"
+"* Nature.POINT: True for any 0D element.\n"
+"* Nature.S_VERTEX: True for SVertex.\n"
+"* Nature.VIEW_VERTEX: True for ViewVertex.\n"
+"* Nature.NON_T_VERTEX: True for NonTVertex.\n"
+"* Nature.T_VERTEX: True for TVertex.\n"
+"* Nature.CUSP: True for CUSP.\n"
+"\n"
+"Edge natures:\n"
+"\n"
+"* Nature.NO_FEATURE: True for non feature edges (always false for 1D\n"
+" elements of the ViewMap).\n"
+"* Nature.SILHOUETTE: True for silhouettes.\n"
+"* Nature.BORDER: True for borders.\n"
+"* Nature.CREASE: True for creases.\n"
+"* Nature.RIDGE: True for ridges.\n"
+"* Nature.VALLEY: True for valleys.\n"
+"* Nature.SUGGESTIVE_CONTOUR: True for suggestive contours.\n";
+
+/*-----------------------BPy_Nature type definition ------------------------------*/
+
+PyTypeObject Nature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Nature", /* tp_name */
+ sizeof(PyLongObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ &nature_as_number, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Nature___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyLong_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+/*-----------------------BPy_Nature instance definitions ----------------------------------*/
+
+static PyLongObject _Nature_POINT = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::POINT }
+};
+static PyLongObject _Nature_S_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::S_VERTEX }
+};
+static PyLongObject _Nature_VIEW_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::VIEW_VERTEX }
+};
+static PyLongObject _Nature_NON_T_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::NON_T_VERTEX }
+};
+static PyLongObject _Nature_T_VERTEX = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::T_VERTEX }
+};
+static PyLongObject _Nature_CUSP = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::CUSP }
+};
+static PyLongObject _Nature_NO_FEATURE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::NO_FEATURE }
+};
+static PyLongObject _Nature_SILHOUETTE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::SILHOUETTE }
+};
+static PyLongObject _Nature_BORDER = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::BORDER }
+};
+static PyLongObject _Nature_CREASE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::CREASE }
+};
+static PyLongObject _Nature_RIDGE = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::RIDGE }
+};
+static PyLongObject _Nature_VALLEY = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::VALLEY }
+};
+static PyLongObject _Nature_SUGGESTIVE_CONTOUR = {
+ PyVarObject_HEAD_INIT(&Nature_Type, 1)
+ { Nature::SUGGESTIVE_CONTOUR }
+};
+
+#define BPy_Nature_POINT ((PyObject *)&_Nature_POINT)
+#define BPy_Nature_S_VERTEX ((PyObject *)&_Nature_S_VERTEX)
+#define BPy_Nature_VIEW_VERTEX ((PyObject *)&_Nature_VIEW_VERTEX)
+#define BPy_Nature_NON_T_VERTEX ((PyObject *)&_Nature_NON_T_VERTEX)
+#define BPy_Nature_T_VERTEX ((PyObject *)&_Nature_T_VERTEX)
+#define BPy_Nature_CUSP ((PyObject *)&_Nature_CUSP)
+#define BPy_Nature_NO_FEATURE ((PyObject *)&_Nature_NO_FEATURE)
+#define BPy_Nature_SILHOUETTE ((PyObject *)&_Nature_SILHOUETTE)
+#define BPy_Nature_BORDER ((PyObject *)&_Nature_BORDER)
+#define BPy_Nature_CREASE ((PyObject *)&_Nature_CREASE)
+#define BPy_Nature_RIDGE ((PyObject *)&_Nature_RIDGE)
+#define BPy_Nature_VALLEY ((PyObject *)&_Nature_VALLEY)
+#define BPy_Nature_SUGGESTIVE_CONTOUR ((PyObject *)&_Nature_SUGGESTIVE_CONTOUR)
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Nature_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Nature_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Nature_Type );
+ PyModule_AddObject(module, "Nature", (PyObject *)&Nature_Type);
+
+ // VertexNature
+ PyDict_SetItemString( Nature_Type.tp_dict, "POINT", BPy_Nature_POINT);
+ PyDict_SetItemString( Nature_Type.tp_dict, "S_VERTEX", BPy_Nature_S_VERTEX);
+ PyDict_SetItemString( Nature_Type.tp_dict, "VIEW_VERTEX", BPy_Nature_VIEW_VERTEX );
+ PyDict_SetItemString( Nature_Type.tp_dict, "NON_T_VERTEX", BPy_Nature_NON_T_VERTEX );
+ PyDict_SetItemString( Nature_Type.tp_dict, "T_VERTEX", BPy_Nature_T_VERTEX );
+ PyDict_SetItemString( Nature_Type.tp_dict, "CUSP", BPy_Nature_CUSP );
+
+ // EdgeNature
+ PyDict_SetItemString( Nature_Type.tp_dict, "NO_FEATURE", BPy_Nature_NO_FEATURE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "SILHOUETTE", BPy_Nature_SILHOUETTE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "BORDER", BPy_Nature_BORDER );
+ PyDict_SetItemString( Nature_Type.tp_dict, "CREASE", BPy_Nature_CREASE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "RIDGE", BPy_Nature_RIDGE );
+ PyDict_SetItemString( Nature_Type.tp_dict, "VALLEY", BPy_Nature_VALLEY );
+ PyDict_SetItemString( Nature_Type.tp_dict, "SUGGESTIVE_CONTOUR", BPy_Nature_SUGGESTIVE_CONTOUR );
+
+ return 0;
+}
+
+static PyObject *
+BPy_Nature_bitwise(PyObject *a, int op, PyObject *b)
+{
+ BPy_Nature *result;
+
+ if (!BPy_Nature_Check(a) || !BPy_Nature_Check(b)) {
+ PyErr_SetString(PyExc_TypeError, "operands must be a Nature object");
+ return NULL;
+ }
+ if (Py_SIZE(a) != 1) {
+ stringstream msg;
+ msg << "operand 1: unexpected Nature byte length: " << Py_SIZE(a);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ if (Py_SIZE(b) != 1) {
+ stringstream msg;
+ msg << "operand 2: unexpected Nature byte length: " << Py_SIZE(b);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ result = PyObject_NewVar(BPy_Nature, &Nature_Type, 1);
+ if (!result)
+ return NULL;
+ if (Py_SIZE(result) != 1) {
+ stringstream msg;
+ msg << "unexpected Nature byte length: " << Py_SIZE(result);
+ PyErr_SetString(PyExc_TypeError, msg.str().c_str());
+ return NULL;
+ }
+ switch (op) {
+ case '&':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) & (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ case '^':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) ^ (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ case '|':
+ result->i.ob_digit[0] = (((PyLongObject *)a)->ob_digit[0]) | (((PyLongObject *)b)->ob_digit)[0];
+ break;
+ }
+ return (PyObject *)result;
+}
+
+static PyObject *
+BPy_Nature___and__(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '&', b);
+}
+
+static PyObject *
+BPy_Nature___xor__(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '^', b);
+}
+
+static PyObject *
+BPy_Nature___or__(PyObject *a, PyObject *b)
+{
+ return BPy_Nature_bitwise(a, '|', b);
+}
+
+static int
+BPy_Nature_bool(PyObject *v)
+{
+ return ((PyLongObject *)v)->ob_digit[0] != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_Nature.h b/source/blender/freestyle/intern/python/BPy_Nature.h
new file mode 100644
index 00000000000..8c38415242e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Nature.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_NATURE_H
+#define FREESTYLE_PYTHON_NATURE_H
+
+#include <Python.h>
+
+#include "../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Nature_Type;
+
+#define BPy_Nature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Nature_Type) )
+
+/*---------------------------Python BPy_Nature structure definition----------*/
+typedef struct {
+ PyLongObject i;
+} BPy_Nature;
+
+/*---------------------------Python BPy_Nature visible prototypes-----------*/
+
+int Nature_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NATURE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp
new file mode 100644
index 00000000000..79c3fb64a82
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp
@@ -0,0 +1,612 @@
+#include "BPy_Operators.h"
+
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+#include "Iterator/BPy_ViewEdgeIterator.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int Operators_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &Operators_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &Operators_Type );
+ PyModule_AddObject(module, "Operators", (PyObject *)&Operators_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Operators___doc__[] =
+"Class defining the operators used in a style module. There are five\n"
+"types of operators: Selection, chaining, splitting, sorting and\n"
+"creation. All these operators are user controlled through functors,\n"
+"predicates and shaders that are taken as arguments.\n";
+
+static void Operators___dealloc__(BPy_Operators* self)
+{
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static char Operators_select___doc__[] =
+".. staticmethod:: select(pred)\n"
+"\n"
+" Selects the ViewEdges of the ViewMap verifying a specified\n"
+" condition.\n"
+"\n"
+" :arg pred: The predicate expressing this condition.\n"
+" :type pred: UnaryPredicate1D\n";
+
+static PyObject * Operators_select(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!", &UnaryPredicate1D_Type, &obj) )
+ return NULL;
+ if ( !((BPy_UnaryPredicate1D *) obj)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.select(): 1st argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+
+ if (Operators::select(*( ((BPy_UnaryPredicate1D *) obj)->up1D )) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.select() failed");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_chain___doc__[] =
+".. staticmethod:: chain(it, pred, modifier)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list starts a new chain. The chaining\n"
+" operator then iterates over the ViewEdges of the ViewMap using the\n"
+" user specified iterator. This operator only iterates using the\n"
+" increment operator and is therefore unidirectional.\n"
+"\n"
+" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
+" the chaining rule.\n"
+" :type it: :class:`ViewEdgeIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg modifier: A function that takes a ViewEdge as argument and\n"
+" that is used to modify the processed ViewEdge state (the\n"
+" timestamp incrementation is a typical illustration of such a\n"
+" modifier).\n"
+" :type modifier: :class:`UnaryFunction1DVoid`\n"
+"\n"
+".. staticmethod:: chain(it, pred)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list starts a new chain. The chaining\n"
+" operator then iterates over the ViewEdges of the ViewMap using the\n"
+" user specified iterator. This operator only iterates using the\n"
+" increment operator and is therefore unidirectional. This chaining\n"
+" operator is different from the previous one because it doesn't take\n"
+" any modifier as argument. Indeed, the time stamp (insuring that a\n"
+" ViewEdge is processed one time) is automatically managed in this\n"
+" case.\n"
+"\n"
+" :arg it: The iterator on the ViewEdges of the ViewMap. It contains\n"
+" the chaining rule. \n"
+" :type it: :class:`ViewEdgeIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n";
+
+// CHANGE: first parameter is a chaining iterator, not just a view
+
+static PyObject * Operators_chain(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!O!|O!", &ChainingIterator_Type, &obj1,
+ &UnaryPredicate1D_Type, &obj2,
+ &UnaryFunction1DVoid_Type, &obj3) )
+ return NULL;
+ if ( !((BPy_ChainingIterator *) obj1)->c_it ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 1st argument: invalid ChainingIterator object");
+ return NULL;
+ }
+ if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+
+ if( !obj3 ) {
+
+ if (Operators::chain( *( ((BPy_ChainingIterator *) obj1)->c_it ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( !((BPy_UnaryFunction1DVoid *) obj3)->uf1D_void ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.chain(): 3rd argument: invalid UnaryFunction1DVoid object");
+ return NULL;
+ }
+ if (Operators::chain( *( ((BPy_ChainingIterator *) obj1)->c_it ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ),
+ *( ((BPy_UnaryFunction1DVoid *) obj3)->uf1D_void ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.chain() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_bidirectionalChain___doc__[] =
+".. staticmethod:: bidirectionalChain(it, pred)\n"
+"\n"
+" Builds a set of chains from the current set of ViewEdges. Each\n"
+" ViewEdge of the current list potentially starts a new chain. The\n"
+" chaining operator then iterates over the ViewEdges of the ViewMap\n"
+" using the user specified iterator. This operator iterates both using\n"
+" the increment and decrement operators and is therefore bidirectional.\n"
+" This operator works with a ChainingIterator which contains the\n"
+" chaining rules. It is this last one which can be told to chain only\n"
+" edges that belong to the selection or not to process twice a ViewEdge\n"
+" during the chaining. Each time a ViewEdge is added to a chain, its\n"
+" chaining time stamp is incremented. This allows you to keep track of\n"
+" the number of chains to which a ViewEdge belongs to.\n"
+"\n"
+" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
+" contains the chaining rule.\n"
+" :type it: :class:`ChainingIterator`\n"
+" :arg pred: The predicate on the ViewEdge that expresses the\n"
+" stopping condition.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+"\n"
+".. staticmethod:: bidirectionalChain(it)\n"
+"\n"
+" The only difference with the above bidirectional chaining algorithm\n"
+" is that we don't need to pass a stopping criterion. This might be\n"
+" desirable when the stopping criterion is already contained in the\n"
+" iterator definition. Builds a set of chains from the current set of\n"
+" ViewEdges. Each ViewEdge of the current list potentially starts a new\n"
+" chain. The chaining operator then iterates over the ViewEdges of the\n"
+" ViewMap using the user specified iterator. This operator iterates\n"
+" both using the increment and decrement operators and is therefore\n"
+" bidirectional. This operator works with a ChainingIterator which\n"
+" contains the chaining rules. It is this last one which can be told to\n"
+" chain only edges that belong to the selection or not to process twice\n"
+" a ViewEdge during the chaining. Each time a ViewEdge is added to a\n"
+" chain, its chaining time stamp is incremented. This allows you to\n"
+" keep track of the number of chains to which a ViewEdge belongs to.\n"
+"\n"
+" :arg it: The ChainingIterator on the ViewEdges of the ViewMap. It\n"
+" contains the chaining rule.\n"
+" :type it: :class:`ChainingIterator`\n";
+
+static PyObject * Operators_bidirectionalChain(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if( !PyArg_ParseTuple(args, "O!|O!", &ChainingIterator_Type, &obj1, &UnaryPredicate1D_Type, &obj2) )
+ return NULL;
+ if ( !((BPy_ChainingIterator *) obj1)->c_it ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.bidirectionalChain(): 1st argument: invalid ChainingIterator object");
+ return NULL;
+ }
+
+ if( !obj2 ) {
+
+ if (Operators::bidirectionalChain( *( ((BPy_ChainingIterator *) obj1)->c_it ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectionalChain() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.bidirectionalChain(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if (Operators::bidirectionalChain( *( ((BPy_ChainingIterator *) obj1)->c_it ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ) ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.bidirectionalChain() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_sequentialSplit___doc__[] =
+".. staticmethod:: sequentialSplit(startingPred, stoppingPred, sampling=0.0)\n"
+"\n"
+" Splits each chain of the current set of chains in a sequential way.\n"
+" The points of each chain are processed (with a specified sampling)\n"
+" sequentially. Each time a user specified starting condition is\n"
+" verified, a new chain begins and ends as soon as a user-defined\n"
+" stopping predicate is verified. This allows chains overlapping rather\n"
+" than chains partitioning. The first point of the initial chain is the\n"
+" first point of one of the resulting chains. The splitting ends when\n"
+" no more chain can start.\n"
+"\n"
+" :arg startingPred: The predicate on a point that expresses the\n"
+" starting condition.\n"
+" :type startingPred: :class:`UnaryPredicate0D`\n"
+" :arg stoppingPred: The predicate on a point that expresses the\n"
+" stopping condition.\n"
+" :type stoppingPred: :class:`UnaryPredicate0D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled;\n"
+" a virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n"
+"\n"
+".. staticmethod:: sequentialSplit(pred, sampling=0.0)\n"
+"\n"
+" Splits each chain of the current set of chains in a sequential way.\n"
+" The points of each chain are processed (with a specified sampling)\n"
+" sequentially and each time a user specified condition is verified,\n"
+" the chain is split into two chains. The resulting set of chains is a\n"
+" partition of the initial chain\n"
+"\n"
+" :arg pred: The predicate on a point that expresses the splitting\n"
+" condition.\n"
+" :type pred: :class:`UnaryPredicate0D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicate evaluation. (The chain is not actually resampled; a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n";
+
+static PyObject * Operators_sequentialSplit(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+ float f = 0.0;
+
+ if( !PyArg_ParseTuple(args, "O!|Of", &UnaryPredicate0D_Type, &obj1, &obj2, &f) )
+ return NULL;
+ if ( !((BPy_UnaryPredicate0D *) obj1)->up0D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): 1st argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+
+ if( obj2 && BPy_UnaryPredicate0D_Check(obj2) ) {
+
+ if ( !((BPy_UnaryPredicate0D *) obj2)->up0D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): 2nd argument: invalid UnaryPredicate0D object");
+ return NULL;
+ }
+ if (Operators::sequentialSplit( *( ((BPy_UnaryPredicate0D *) obj1)->up0D ),
+ *( ((BPy_UnaryPredicate0D *) obj2)->up0D ),
+ f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sequentialSplit() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( obj2 ) {
+ if ( !PyFloat_Check(obj2) ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sequentialSplit(): invalid 2nd argument");
+ return NULL;
+ }
+ f = PyFloat_AsDouble(obj2);
+ }
+ if (Operators::sequentialSplit( *( ((BPy_UnaryPredicate0D *) obj1)->up0D ), f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sequentialSplit() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_recursiveSplit___doc__[] =
+".. staticmethod:: recursiveSplit(func, pred, sampling=0.0)\n"
+"\n"
+" Splits the current set of chains in a recursive way. We process the\n"
+" points of each chain (with a specified sampling) to find the point\n"
+" minimizing a specified function. The chain is split in two at this\n"
+" point and the two new chains are processed in the same way. The\n"
+" recursivity level is controlled through a predicate 1D that expresses\n"
+" a stopping condition on the chain that is about to be processed.\n"
+"\n"
+" :arg func: The Unary Function evaluated at each point of the chain.\n"
+" The splitting point is the point minimizing this function.\n"
+" :type func: :class:`UnaryFunction0DDouble`\n"
+" :arg pred: The Unary Predicate expressing the recursivity stopping\n"
+" condition. This predicate is evaluated for each curve before it\n"
+" actually gets split. If pred(chain) is true, the curve won't be\n"
+" split anymore.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled, a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n"
+"\n"
+".. staticmethod:: recursiveSplit(func, pred0d, pred, sampling=0.0)\n"
+"\n"
+" Splits the current set of chains in a recursive way. We process the\n"
+" points of each chain (with a specified sampling) to find the point\n"
+" minimizing a specified function. The chain is split in two at this\n"
+" point and the two new chains are processed in the same way. The user\n"
+" can specify a 0D predicate to make a first selection on the points\n"
+" that can potentially be split. A point that doesn't verify the 0D\n"
+" predicate won't be candidate in realizing the min. The recursivity\n"
+" level is controlled through a predicate 1D that expresses a stopping\n"
+" condition on the chain that is about to be processed.\n"
+"\n"
+" :arg func: The Unary Function evaluated at each point of the chain.\n"
+" The splitting point is the point minimizing this function.\n"
+" :type func: :class:`UnaryFunction0DDouble`\n"
+" :arg pred0d: The Unary Predicate 0D used to select the candidate\n"
+" points where the split can occur. For example, it is very likely\n"
+" that would rather have your chain splitting around its middle\n"
+" point than around one of its extremities. A 0D predicate working\n"
+" on the curvilinear abscissa allows to add this kind of constraints.\n"
+" :type pred0d: :class:`UnaryPredicate0D`\n"
+" :arg pred: The Unary Predicate expressing the recursivity stopping\n"
+" condition. This predicate is evaluated for each curve before it\n"
+" actually gets split. If pred(chain) is true, the curve won't be\n"
+" split anymore.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg sampling: The resolution used to sample the chain for the\n"
+" predicates evaluation. (The chain is not actually resampled; a\n"
+" virtual point only progresses along the curve using this\n"
+" resolution.)\n"
+" :type sampling: float\n";
+
+static PyObject * Operators_recursiveSplit(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+ float f = 0.0;
+
+ if ( !PyArg_ParseTuple(args, "O!O|Of", &UnaryFunction0DDouble_Type, &obj1, &obj2, &obj3, &f) )
+ return NULL;
+ if ( !((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): 1st argument: invalid UnaryFunction0DDouble object");
+ return NULL;
+ }
+
+ if ( BPy_UnaryPredicate1D_Check(obj2) ) {
+
+ if ( !((BPy_UnaryPredicate1D *) obj2)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): 2nd argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+ if ( obj3 ) {
+ if ( !PyFloat_Check(obj3) ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 3rd argument");
+ return NULL;
+ }
+ f = PyFloat_AsDouble(obj3);
+ }
+ if (Operators::recursiveSplit( *( ((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ),
+ *( ((BPy_UnaryPredicate1D *) obj2)->up1D ),
+ f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.recursiveSplit() failed");
+ return NULL;
+ }
+
+ } else {
+
+ if ( !BPy_UnaryPredicate0D_Check(obj2) || !((BPy_UnaryPredicate0D *) obj2)->up0D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 2nd argument");
+ return NULL;
+ }
+ if ( !BPy_UnaryPredicate1D_Check(obj3) || !((BPy_UnaryPredicate1D *) obj3)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.recursiveSplit(): invalid 3rd argument");
+ return NULL;
+ }
+ if (Operators::recursiveSplit( *( ((BPy_UnaryFunction0DDouble *) obj1)->uf0D_double ),
+ *( ((BPy_UnaryPredicate0D *) obj2)->up0D ),
+ *( ((BPy_UnaryPredicate1D *) obj3)->up1D ),
+ f ) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.recursiveSplit() failed");
+ return NULL;
+ }
+
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_sort___doc__[] =
+".. staticmethod:: sort(pred)\n"
+"\n"
+" Sorts the current set of chains (or viewedges) according to the\n"
+" comparison predicate given as argument.\n"
+"\n"
+" :arg pred: The binary predicate used for the comparison.\n"
+" :type pred: BinaryPredicate1D\n";
+
+static PyObject * Operators_sort(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!", &BinaryPredicate1D_Type, &obj) )
+ return NULL;
+ if ( !((BPy_BinaryPredicate1D *) obj)->bp1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.sort(): 1st argument: invalid BinaryPredicate1D object");
+ return NULL;
+ }
+
+ if (Operators::sort(*( ((BPy_BinaryPredicate1D *) obj)->bp1D )) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.sort() failed");
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static char Operators_create___doc__[] =
+".. staticmethod:: create(pred, shaders)\n"
+"\n"
+" Creates and shades the strokes from the current set of chains. A\n"
+" predicate can be specified to make a selection pass on the chains.\n"
+"\n"
+" :arg pred: The predicate that a chain must verify in order to be\n"
+" transform as a stroke.\n"
+" :type pred: :class:`UnaryPredicate1D`\n"
+" :arg shaders: The list of shaders used to shade the strokes.\n"
+" :type shaders: List of StrokeShader objects\n";
+
+static PyObject * Operators_create(BPy_Operators* self, PyObject *args)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if ( !PyArg_ParseTuple(args, "O!O!", &UnaryPredicate1D_Type, &obj1, &PyList_Type, &obj2) )
+ return NULL;
+ if ( !((BPy_UnaryPredicate1D *) obj1)->up1D ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.create(): 1st argument: invalid UnaryPredicate1D object");
+ return NULL;
+ }
+
+ vector<StrokeShader *> shaders;
+ for( int i = 0; i < PyList_Size(obj2); i++) {
+ PyObject *py_ss = PyList_GetItem(obj2,i);
+
+ if ( !BPy_StrokeShader_Check(py_ss) ) {
+ PyErr_SetString(PyExc_TypeError, "Operators.create() 2nd argument must be a list of StrokeShader objects");
+ return NULL;
+ }
+ shaders.push_back( ((BPy_StrokeShader *) py_ss)->ss );
+ }
+
+ if (Operators::create( *( ((BPy_UnaryPredicate1D *) obj1)->up1D ), shaders) < 0) {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_RuntimeError, "Operators.create() failed");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Operators_getViewEdgesSize___doc__[] =
+".. staticmethod:: getViewEdgesSize()\n"
+"\n"
+" Returns the number of ViewEdges.\n"
+"\n"
+" :return: The number of ViewEdges.\n"
+" :rtype: int\n";
+
+static PyObject * Operators_getViewEdgesSize( BPy_Operators* self) {
+ return PyLong_FromLong( Operators::getViewEdgesSize() );
+}
+
+static char Operators_getChainsSize___doc__[] =
+".. staticmethod:: getChainsSize()\n"
+"\n"
+" Returns the number of Chains.\n"
+"\n"
+" :return: The number of Chains.\n"
+" :rtype: int\n";
+
+static PyObject * Operators_getChainsSize( BPy_Operators* self ) {
+ return PyLong_FromLong( Operators::getChainsSize() );
+}
+
+static char Operators_getStrokesSize___doc__[] =
+".. staticmethod:: getStrokesSize()\n"
+"\n"
+" Returns the number of Strokes.\n"
+"\n"
+" :return: The number of Strokes.\n"
+" :rtype: int\n";
+
+static PyObject * Operators_getStrokesSize( BPy_Operators* self) {
+ return PyLong_FromLong( Operators::getStrokesSize() );
+}
+
+/*----------------------Operators instance definitions ----------------------------*/
+static PyMethodDef BPy_Operators_methods[] = {
+ {"select", ( PyCFunction ) Operators_select, METH_VARARGS | METH_STATIC, Operators_select___doc__},
+ {"chain", ( PyCFunction ) Operators_chain, METH_VARARGS | METH_STATIC, Operators_chain___doc__},
+ {"bidirectionalChain", ( PyCFunction ) Operators_bidirectionalChain, METH_VARARGS | METH_STATIC, Operators_bidirectionalChain___doc__},
+ {"sequentialSplit", ( PyCFunction ) Operators_sequentialSplit, METH_VARARGS | METH_STATIC, Operators_sequentialSplit___doc__},
+ {"recursiveSplit", ( PyCFunction ) Operators_recursiveSplit, METH_VARARGS | METH_STATIC, Operators_recursiveSplit___doc__},
+ {"sort", ( PyCFunction ) Operators_sort, METH_VARARGS | METH_STATIC, Operators_sort___doc__},
+ {"create", ( PyCFunction ) Operators_create, METH_VARARGS | METH_STATIC, Operators_create___doc__},
+ {"getViewEdgesSize", ( PyCFunction ) Operators_getViewEdgesSize, METH_NOARGS | METH_STATIC, Operators_getViewEdgesSize___doc__},
+ {"getChainsSize", ( PyCFunction ) Operators_getChainsSize, METH_NOARGS | METH_STATIC, Operators_getChainsSize___doc__},
+ {"getStrokesSize", ( PyCFunction ) Operators_getStrokesSize, METH_NOARGS | METH_STATIC, Operators_getStrokesSize___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Operators type definition ------------------------------*/
+
+PyTypeObject Operators_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Operators", /* tp_name */
+ sizeof(BPy_Operators), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)Operators___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Operators___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Operators_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_Operators.h b/source/blender/freestyle/intern/python/BPy_Operators.h
new file mode 100644
index 00000000000..5e01d6bb1fe
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_Operators.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_OPERATORS_H
+#define FREESTYLE_PYTHON_OPERATORS_H
+
+#include <Python.h>
+
+#include "../stroke/Operators.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject Operators_Type;
+
+#define BPy_Operators_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Operators_Type) )
+
+/*---------------------------Python BPy_Operators structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+} BPy_Operators;
+
+/*---------------------------Python BPy_Operators visible prototypes-----------*/
+
+int Operators_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_OPERATORS_H */
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp
new file mode 100644
index 00000000000..512a19359a5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp
@@ -0,0 +1,297 @@
+#include "BPy_SShape.h"
+
+#include "BPy_Convert.h"
+#include "BPy_BBox.h"
+#include "BPy_Id.h"
+#include "Interface0D/BPy_SVertex.h"
+#include "Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int SShape_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &SShape_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &SShape_Type );
+ PyModule_AddObject(module, "SShape", (PyObject *)&SShape_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SShape___doc__[] =
+"Class to define a feature shape. It is the gathering of feature\n"
+"elements from an identified input shape.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An SShape object.\n"
+" :type iBrother: :class:`SShape`\n";
+
+static int SShape___init__(BPy_SShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj = NULL;
+
+ if (! PyArg_ParseTuple(args, "|O!", &SShape_Type, &obj) )
+ return -1;
+
+ if( !obj ) {
+ self->ss = new SShape();
+
+ } else {
+ self->ss = new SShape(*( ((BPy_SShape *) obj)->ss ));
+ }
+ self->borrowed = 0;
+
+ return 0;
+}
+
+static void SShape___dealloc__(BPy_SShape *self)
+{
+ if( self->ss && !self->borrowed )
+ delete self->ss;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * SShape___repr__(BPy_SShape *self)
+{
+ return PyUnicode_FromFormat("SShape - address: %p", self->ss );
+}
+
+static char SShape_AddEdge___doc__[] =
+".. method:: AddEdge(iEdge)\n"
+"\n"
+" Adds an FEdge to the list of FEdges.\n"
+"\n"
+" :arg iEdge: An FEdge object.\n"
+" :type iEdge: :class:`FEdge`\n";
+
+static PyObject * SShape_AddEdge( BPy_SShape *self , PyObject *args) {
+ PyObject *py_fe = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->ss->AddEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_AddNewVertex___doc__[] =
+".. method:: AddNewVertex(iv)\n"
+"\n"
+" Adds an SVertex to the list of SVertex of this Shape. The SShape\n"
+" attribute of the SVertex is also set to this SShape.\n"
+"\n"
+" :arg iv: An SVertex object.\n"
+" :type iv: :class:`SVertex`\n";
+
+static PyObject * SShape_AddNewVertex( BPy_SShape *self , PyObject *args) {
+ PyObject *py_sv = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->ss->AddNewVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_setBBox___doc__[] =
+".. method:: setBBox(iBBox)\n"
+"\n"
+" Sets the bounding box of the SShape.\n"
+"\n"
+" :arg iBBox: The bounding box of the SShape.\n"
+" :type iBBox: :class:`BBox`\n";
+
+static PyObject * SShape_setBBox( BPy_SShape *self , PyObject *args) {
+ PyObject *py_bb = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &BBox_Type, &py_bb) ))
+ return NULL;
+
+ self->ss->setBBox(*( ((BPy_BBox*) py_bb)->bb ));
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_ComputeBBox___doc__[] =
+".. method:: ComputeBBox()\n"
+"\n"
+" Compute the bbox of the SShape.\n";
+
+static PyObject * SShape_ComputeBBox( BPy_SShape *self ) {
+ self->ss->ComputeBBox();
+
+ Py_RETURN_NONE;
+}
+
+static char SShape_bbox___doc__[] =
+".. method:: bbox()\n"
+"\n"
+" Returns the bounding box of the SShape.\n"
+"\n"
+" :return: the bounding box of the SShape.\n"
+" :rtype: :class:`BBox`\n";
+
+static PyObject * SShape_bbox( BPy_SShape *self ) {
+ BBox<Vec3r> bb( self->ss->bbox() );
+ return BPy_BBox_from_BBox( bb );
+}
+
+static char SShape_getVertexList___doc__[] =
+".. method:: getVertexList()\n"
+"\n"
+" Returns the list of vertices of the SShape.\n"
+"\n"
+" :return: The list of vertices objects.\n"
+" :rtype: List of :class:`SVertex` objects\n";
+
+static PyObject * SShape_getVertexList( BPy_SShape *self ) {
+ PyObject *py_vertices = PyList_New(0);
+
+ vector< SVertex * > vertices = self->ss->getVertexList();
+ vector< SVertex * >::iterator it;
+
+ for( it = vertices.begin(); it != vertices.end(); it++ ) {
+ PyList_Append( py_vertices, BPy_SVertex_from_SVertex(*( *it )) );
+ }
+
+ return py_vertices;
+}
+
+static char SShape_getEdgeList___doc__[] =
+".. method:: getEdgeList()\n"
+"\n"
+" Returns the list of edges of the SShape.\n"
+"\n"
+" :return: The list of edges of the SShape.\n"
+" :rtype: List of :class:`FEdge` objects\n";
+
+static PyObject * SShape_getEdgeList( BPy_SShape *self ) {
+ PyObject *py_edges = PyList_New(0);
+
+ vector< FEdge * > edges = self->ss->getEdgeList();
+ vector< FEdge * >::iterator it;
+
+ for( it = edges.begin(); it != edges.end(); it++ ) {
+ PyList_Append( py_edges, Any_BPy_FEdge_from_FEdge(*( *it )) );
+ }
+
+ return py_edges;
+}
+
+static char SShape_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the Id of the SShape.\n"
+"\n"
+" :return: The Id of the SShape.\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject * SShape_getId( BPy_SShape *self ) {
+ Id id( self->ss->getId() );
+ return BPy_Id_from_Id( id );
+}
+
+static char SShape_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the Id of the SShape.\n"
+"\n"
+" :arg id: The Id of the SShape.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject * SShape_setId( BPy_SShape *self , PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ self->ss->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+// const Material & material (unsigned i) const
+// const vector< Material > & materials () const
+// void SetMaterials (const vector< Material > &iMaterials)
+
+/*----------------------SShape instance definitions ----------------------------*/
+static PyMethodDef BPy_SShape_methods[] = {
+ {"AddEdge", ( PyCFunction ) SShape_AddEdge, METH_VARARGS, SShape_AddEdge___doc__},
+ {"AddNewVertex", ( PyCFunction ) SShape_AddNewVertex, METH_VARARGS, SShape_AddNewVertex___doc__},
+ {"setBBox", ( PyCFunction ) SShape_setBBox, METH_VARARGS, SShape_setBBox___doc__},
+ {"ComputeBBox", ( PyCFunction ) SShape_ComputeBBox, METH_NOARGS, SShape_ComputeBBox___doc__},
+ {"bbox", ( PyCFunction ) SShape_bbox, METH_NOARGS, SShape_bbox___doc__},
+ {"getVertexList", ( PyCFunction ) SShape_getVertexList, METH_NOARGS, SShape_getVertexList___doc__},
+ {"getEdgeList", ( PyCFunction ) SShape_getEdgeList, METH_NOARGS, SShape_getEdgeList___doc__},
+ {"getId", ( PyCFunction ) SShape_getId, METH_NOARGS, SShape_getId___doc__},
+ {"setId", ( PyCFunction ) SShape_setId, METH_VARARGS, SShape_setId___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_SShape type definition ------------------------------*/
+
+PyTypeObject SShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SShape", /* tp_name */
+ sizeof(BPy_SShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)SShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)SShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_SShape.h b/source/blender/freestyle/intern/python/BPy_SShape.h
new file mode 100644
index 00000000000..e8d631f0538
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_SShape.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_SSHAPE_H
+#define FREESTYLE_PYTHON_SSHAPE_H
+
+#include <Python.h>
+
+#include "../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject SShape_Type;
+
+#define BPy_SShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SShape_Type) )
+
+/*---------------------------Python BPy_SShape structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ SShape *ss;
+ int borrowed; /* non-zero if *ss is a borrowed object */
+} BPy_SShape;
+
+/*---------------------------Python BPy_SShape visible prototypes-----------*/
+
+int SShape_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
new file mode 100644
index 00000000000..4db7110ac29
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp
@@ -0,0 +1,658 @@
+#include "BPy_StrokeAttribute.h"
+
+#include "BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int StrokeAttribute_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &StrokeAttribute_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeAttribute_Type );
+ PyModule_AddObject(module, "StrokeAttribute", (PyObject *)&StrokeAttribute_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeAttribute___doc__[] =
+"Class to define a set of attributes associated with a :class:`StrokeVertex`.\n"
+"The attribute set stores the color, alpha and thickness values for a Stroke\n"
+"Vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A StrokeAttribute object.\n"
+" :type iBrother: :class:`StrokeAttribute`\n"
+"\n"
+".. method:: __init__(iRColor, iGColor, iBColor, iAlpha, iRThickness, iLThickness)\n"
+"\n"
+" Builds a stroke vertex attribute from a set of parameters.\n"
+"\n"
+" :arg iRColor: Red component of a stroke color.\n"
+" :type iRColor: float\n"
+" :arg iGColor: Green component of a stroke color.\n"
+" :type iGColor: float\n"
+" :arg iBColor: Blue component of a stroke color.\n"
+" :type iBColor: float\n"
+" :arg iAlpha: Alpha component of a stroke color.\n"
+" :type iAlpha: float\n"
+" :arg iRThickness: Stroke thickness on the right.\n"
+" :type iRThickness: float\n"
+" :arg iLThickness: Stroke thickness on the left.\n"
+" :type iLThickness: float\n"
+"\n"
+".. method:: __init__(a1, a2, t)\n"
+"\n"
+" Interpolation constructor. Builds a StrokeAttribute from two\n"
+" StrokeAttribute objects and an interpolation parameter.\n"
+"\n"
+" :arg a1: The first StrokeAttribute object.\n"
+" :type a1: :class:`StrokeAttribute`\n"
+" :arg a2: The second StrokeAttribute object.\n"
+" :type a2: :class:`StrokeAttribute`\n"
+" :arg t: The interpolation parameter.\n"
+" :type t: float\n";
+
+static int StrokeAttribute___init__(BPy_StrokeAttribute *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0, *obj4 = 0, *obj5 = 0 , *obj6 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOOOOO", &obj1, &obj2, &obj3, &obj4, &obj5, &obj6) )
+ return -1;
+
+ if( !obj1 || !obj2 || !obj3 ){
+
+ self->sa = new StrokeAttribute();
+
+ } else if( BPy_StrokeAttribute_Check(obj1) &&
+ BPy_StrokeAttribute_Check(obj2) &&
+ PyFloat_Check(obj3) ) {
+
+ self->sa = new StrokeAttribute( *( ((BPy_StrokeAttribute *) obj1)->sa ),
+ *( ((BPy_StrokeAttribute *) obj2)->sa ),
+ PyFloat_AsDouble( obj3 ) );
+
+ } else if( obj4 && obj5 && obj6 ) {
+
+ self->sa = new StrokeAttribute( PyFloat_AsDouble( obj1 ),
+ PyFloat_AsDouble( obj2 ),
+ PyFloat_AsDouble( obj3 ),
+ PyFloat_AsDouble( obj4 ),
+ PyFloat_AsDouble( obj5 ),
+ PyFloat_AsDouble( obj6 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return -1;
+ }
+
+ self->borrowed = 0;
+
+ return 0;
+
+}
+
+static void StrokeAttribute___dealloc__(BPy_StrokeAttribute* self)
+{
+ if( self->sa && !self->borrowed )
+ delete self->sa;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * StrokeAttribute___repr__(BPy_StrokeAttribute* self)
+{
+ stringstream repr("StrokeAttribute:");
+ repr << " r: " << self->sa->getColorR()
+ << " g: " << self->sa->getColorG()
+ << " b: " << self->sa->getColorB()
+ << " a: " << self->sa->getAlpha()
+ << " - R: " << self->sa->getThicknessR()
+ << " L: " << self->sa->getThicknessL();
+
+ return PyUnicode_FromFormat( repr.str().c_str() );
+}
+
+
+static char StrokeAttribute_getColorR___doc__[] =
+".. method:: getColorR()\n"
+"\n"
+" Returns the red component of the stroke color.\n"
+"\n"
+" :return: Red component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getColorR( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getColorR() );
+}
+
+static char StrokeAttribute_getColorG___doc__[] =
+".. method:: getColorG()\n"
+"\n"
+" Returns the green component of the stroke color.\n"
+"\n"
+" :return: Green component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getColorG( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getColorG() );
+}
+
+static char StrokeAttribute_getColorB___doc__[] =
+".. method:: getColorB()\n"
+"\n"
+" Returns the blue component of the stroke color.\n"
+"\n"
+" :return: Blue component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getColorB( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getColorB() );
+}
+
+static char StrokeAttribute_getColorRGB___doc__[] =
+".. method:: getColorRGB()\n"
+"\n"
+" Returns the RGB components of the stroke color.\n"
+"\n"
+" :return: RGB components of the stroke color.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getColorRGB( BPy_StrokeAttribute *self ) {
+ Vec3f v( self->sa->getColorRGB() );
+ return Vector_from_Vec3f( v );
+}
+
+static char StrokeAttribute_getAlpha___doc__[] =
+".. method:: getAlpha()\n"
+"\n"
+" Returns the alpha component of the stroke color.\n"
+"\n"
+" :return: Alpha component of the stroke color.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getAlpha( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getAlpha() );
+}
+
+static char StrokeAttribute_getThicknessR___doc__[] =
+".. method:: getThicknessR()\n"
+"\n"
+" Returns the thickness on the right of the vertex when following\n"
+" the stroke.\n"
+"\n"
+" :return: The thickness on the right of the vertex.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getThicknessR( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getThicknessR() );
+}
+
+static char StrokeAttribute_getThicknessL___doc__[] =
+".. method:: getThicknessL()\n"
+"\n"
+" Returns the thickness on the left of the vertex when following\n"
+" the stroke.\n"
+"\n"
+" :return: The thickness on the left of the vertex.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getThicknessL( BPy_StrokeAttribute *self ) {
+ return PyFloat_FromDouble( self->sa->getThicknessL() );
+}
+
+static char StrokeAttribute_getThicknessRL___doc__[] =
+".. method:: getThicknessRL()\n"
+"\n"
+" Returns the thickness on the right and on the left of the vertex\n"
+" when following the stroke.\n"
+"\n"
+" :return: A two-dimensional vector. The first value is the\n"
+" thickness on the right of the vertex when following the stroke,\n"
+" and the second one is the thickness on the left.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getThicknessRL( BPy_StrokeAttribute *self ) {
+ Vec2f v( self->sa->getThicknessRL() );
+ return Vector_from_Vec2f( v );
+}
+
+static char StrokeAttribute_isVisible___doc__[] =
+".. method:: isVisible()\n"
+"\n"
+" Returns true if the StrokeVertex is visible, false otherwise.\n"
+"\n"
+" :return: True if the StrokeVertex is visible, false otherwise.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isVisible( BPy_StrokeAttribute *self ) {
+ return PyBool_from_bool( self->sa->isVisible() );
+}
+
+static char StrokeAttribute_getAttributeReal___doc__[] =
+".. method:: getAttributeReal(iName)\n"
+"\n"
+" Returns an attribute of float type.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :return: The attribute value.\n"
+" :rtype: float\n";
+
+static PyObject *StrokeAttribute_getAttributeReal( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ double a = self->sa->getAttributeReal( attr );
+ return PyFloat_FromDouble( a );
+}
+
+static char StrokeAttribute_getAttributeVec2f___doc__[] =
+".. method:: getAttributeVec2f(iName)\n"
+"\n"
+" Returns an attribute of two-dimensional vector type.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :return: The attribute value.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getAttributeVec2f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ Vec2f a = self->sa->getAttributeVec2f( attr );
+ return Vector_from_Vec2f( a );
+}
+
+static char StrokeAttribute_getAttributeVec3f___doc__[] =
+".. method:: getAttributeVec3f(iName)\n"
+"\n"
+" Returns an attribute of three-dimensional vector type.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :return: The attribute value.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject *StrokeAttribute_getAttributeVec3f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ Vec3f a = self->sa->getAttributeVec3f( attr );
+ return Vector_from_Vec3f( a );
+}
+
+static char StrokeAttribute_isAttributeAvailableReal___doc__[] =
+".. method:: isAttributeAvailableReal(iName)\n"
+"\n"
+" Checks whether the attribute iName of float type is available.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isAttributeAvailableReal( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ return PyBool_from_bool( self->sa->isAttributeAvailableReal( attr ) );
+}
+
+static char StrokeAttribute_isAttributeAvailableVec2f___doc__[] =
+".. method:: isAttributeAvailableVec2f(iName)\n"
+"\n"
+" Checks whether the attribute iName of two-dimensional vector type\n"
+" is available.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isAttributeAvailableVec2f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ return PyBool_from_bool( self->sa->isAttributeAvailableVec2f( attr ) );
+}
+
+static char StrokeAttribute_isAttributeAvailableVec3f___doc__[] =
+".. method:: isAttributeAvailableVec3f(iName)\n"
+"\n"
+" Checks whether the attribute iName of three-dimensional vector\n"
+" type is available.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :return: True if the attribute is availbale.\n"
+" :rtype: bool\n";
+
+static PyObject *StrokeAttribute_isAttributeAvailableVec3f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *attr;
+
+ if(!( PyArg_ParseTuple(args, "s", &attr) ))
+ return NULL;
+
+ return PyBool_from_bool( self->sa->isAttributeAvailableVec3f( attr ) );
+}
+
+
+static char StrokeAttribute_setColor___doc__[] =
+".. method:: setColor(r, g, b)\n"
+"\n"
+" Sets the stroke color.\n"
+"\n"
+" :arg r: Red component of the stroke color.\n"
+" :type r: float\n"
+" :arg g: Green component of the stroke color.\n"
+" :type g: float\n"
+" :arg b: Blue component of the stroke color.\n"
+" :type b: float\n"
+"\n"
+".. method:: setColor(iRGB)\n"
+"\n"
+" Sets the stroke color.\n"
+"\n"
+" :arg iRGB: The new RGB values.\n"
+" :type iRGB: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * StrokeAttribute_setColor( BPy_StrokeAttribute *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0 ;
+
+ if(!( PyArg_ParseTuple(args, "O|OO", &obj1, &obj2, &obj3) ))
+ return NULL;
+
+ if( obj1 && !obj2 && !obj3 ){
+
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setColor( *v );
+ delete v;
+
+ } else if( obj1 && obj2 && obj3 ){
+
+ self->sa->setColor( PyFloat_AsDouble(obj1),
+ PyFloat_AsDouble(obj2),
+ PyFloat_AsDouble(obj3) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAlpha___doc__[] =
+".. method:: setAlpha(alpha)\n"
+"\n"
+" Sets the alpha component of the stroke color.\n"
+"\n"
+" :arg alpha: The new alpha value.\n"
+" :type alpha: float\n";
+
+static PyObject * StrokeAttribute_setAlpha( BPy_StrokeAttribute *self, PyObject *args ){
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ self->sa->setAlpha( f );
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setThickness___doc__[] =
+".. method:: setThickness(tr, tl)\n"
+"\n"
+" Sets the stroke thickness.\n"
+"\n"
+" :arg tr: The thickness on the right of the vertex when following\n"
+" the stroke.\n"
+" :type tr: float\n"
+" :arg tl: The thickness on the left of the vertex when following\n"
+" the stroke.\n"
+" :type tl: float\n"
+"\n"
+".. method:: setThickness(tRL)\n"
+"\n"
+" Sets the stroke thickness.\n"
+"\n"
+" :arg tRL: The thickness on the right and on the left of the vertex\n"
+" when following the stroke.\n"
+" :type tRL: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n";
+
+static PyObject * StrokeAttribute_setThickness( BPy_StrokeAttribute *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) ))
+ return NULL;
+
+ if( obj1 && !obj2 ){
+
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setThickness( *v );
+ delete v;
+
+ } else if( obj1 && obj2 ){
+
+ self->sa->setThickness( PyFloat_AsDouble(obj1),
+ PyFloat_AsDouble(obj2) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setVisible___doc__[] =
+".. method:: setVisible(iVisible)\n"
+"\n"
+" Sets the visibility flag. True means the StrokeVertex is visible.\n"
+"\n"
+" :arg iVisible: True if the StrokeVertex is visible.\n"
+" :type iVisible: bool\n";
+
+static PyObject * StrokeAttribute_setVisible( BPy_StrokeAttribute *self, PyObject *args ) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->sa->setVisible( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAttributeReal___doc__[] =
+".. method:: setAttributeReal(iName, att)\n"
+"\n"
+" Adds a user-defined attribute of float type. If there is no\n"
+" attribute of the given name, it is added. Otherwise, the new value\n"
+" replaces the old one.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :arg att: The attribute value.\n"
+" :type att: float\n";
+
+static PyObject * StrokeAttribute_setAttributeReal( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *s = 0;
+ double d = 0;
+
+ if(!( PyArg_ParseTuple(args, "sd", &s, &d) ))
+ return NULL;
+
+ self->sa->setAttributeReal( s, d );
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAttributeVec2f___doc__[] =
+".. method:: setAttributeVec2f(iName, att)\n"
+"\n"
+" Adds a user-defined attribute of two-dimensional vector type. If\n"
+" there is no attribute of the given name, it is added. Otherwise,\n"
+" the new value replaces the old one.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :arg att: The attribute value.\n"
+" :type att: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n";
+
+static PyObject * StrokeAttribute_setAttributeVec2f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *s;
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "sO", &s, &obj) ))
+ return NULL;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setAttributeVec2f( s, *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeAttribute_setAttributeVec3f___doc__[] =
+".. method:: setAttributeVec3f(iName, att)\n"
+"\n"
+" Adds a user-defined attribute of three-dimensional vector type.\n"
+" If there is no attribute of the given name, it is added.\n"
+" Otherwise, the new value replaces the old one.\n"
+"\n"
+" :arg iName: The name of the attribute.\n"
+" :type iName: string\n"
+" :arg att: The attribute value.\n"
+" :type att: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * StrokeAttribute_setAttributeVec3f( BPy_StrokeAttribute *self, PyObject *args ) {
+ char *s;
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "sO", &s, &obj) ))
+ return NULL;
+ Vec3f *v = Vec3f_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sa->setAttributeVec3f( s, *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------StrokeAttribute instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeAttribute_methods[] = {
+ {"getColorR", ( PyCFunction ) StrokeAttribute_getColorR, METH_NOARGS, StrokeAttribute_getColorR___doc__},
+ {"getColorG", ( PyCFunction ) StrokeAttribute_getColorG, METH_NOARGS, StrokeAttribute_getColorG___doc__},
+ {"getColorB", ( PyCFunction ) StrokeAttribute_getColorB, METH_NOARGS, StrokeAttribute_getColorB___doc__},
+ {"getColorRGB", ( PyCFunction ) StrokeAttribute_getColorRGB, METH_NOARGS, StrokeAttribute_getColorRGB___doc__},
+ {"getAlpha", ( PyCFunction ) StrokeAttribute_getAlpha, METH_NOARGS, StrokeAttribute_getAlpha___doc__},
+ {"getThicknessR", ( PyCFunction ) StrokeAttribute_getThicknessR, METH_NOARGS, StrokeAttribute_getThicknessR___doc__},
+ {"getThicknessL", ( PyCFunction ) StrokeAttribute_getThicknessL, METH_NOARGS, StrokeAttribute_getThicknessL___doc__},
+ {"getThicknessRL", ( PyCFunction ) StrokeAttribute_getThicknessRL, METH_NOARGS, StrokeAttribute_getThicknessRL___doc__},
+ {"isVisible", ( PyCFunction ) StrokeAttribute_isVisible, METH_NOARGS, StrokeAttribute_isVisible___doc__},
+ {"getAttributeReal", ( PyCFunction ) StrokeAttribute_getAttributeReal, METH_VARARGS, StrokeAttribute_getAttributeReal___doc__},
+ {"getAttributeVec2f", ( PyCFunction ) StrokeAttribute_getAttributeVec2f, METH_VARARGS, StrokeAttribute_getAttributeVec2f___doc__},
+ {"getAttributeVec3f", ( PyCFunction ) StrokeAttribute_getAttributeVec3f, METH_VARARGS, StrokeAttribute_getAttributeVec3f___doc__},
+ {"isAttributeAvailableReal", ( PyCFunction ) StrokeAttribute_isAttributeAvailableReal, METH_VARARGS, StrokeAttribute_isAttributeAvailableReal___doc__},
+ {"isAttributeAvailableVec2f", ( PyCFunction ) StrokeAttribute_isAttributeAvailableVec2f, METH_VARARGS, StrokeAttribute_isAttributeAvailableVec2f___doc__},
+ {"isAttributeAvailableVec3f", ( PyCFunction ) StrokeAttribute_isAttributeAvailableVec3f, METH_VARARGS, StrokeAttribute_isAttributeAvailableVec3f___doc__},
+ {"setColor", ( PyCFunction ) StrokeAttribute_setColor, METH_VARARGS, StrokeAttribute_setColor___doc__},
+ {"setAlpha", ( PyCFunction ) StrokeAttribute_setAlpha, METH_VARARGS, StrokeAttribute_setAlpha___doc__},
+ {"setThickness", ( PyCFunction ) StrokeAttribute_setThickness, METH_VARARGS, StrokeAttribute_setThickness___doc__},
+ {"setVisible", ( PyCFunction ) StrokeAttribute_setVisible, METH_VARARGS, StrokeAttribute_setVisible___doc__},
+ {"setAttributeReal", ( PyCFunction ) StrokeAttribute_setAttributeReal, METH_VARARGS, StrokeAttribute_setAttributeReal___doc__},
+ {"setAttributeVec2f", ( PyCFunction ) StrokeAttribute_setAttributeVec2f, METH_VARARGS, StrokeAttribute_setAttributeVec2f___doc__},
+ {"setAttributeVec3f", ( PyCFunction ) StrokeAttribute_setAttributeVec3f, METH_VARARGS, StrokeAttribute_setAttributeVec3f___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeAttribute type definition ------------------------------*/
+
+PyTypeObject StrokeAttribute_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeAttribute", /* tp_name */
+ sizeof(BPy_StrokeAttribute), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)StrokeAttribute___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)StrokeAttribute___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeAttribute___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeAttribute_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeAttribute___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h
new file mode 100644
index 00000000000..51e18c0a96f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_STROKEATTRIBUTE_H
+#define FREESTYLE_PYTHON_STROKEATTRIBUTE_H
+
+#include <Python.h>
+
+#include "../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject StrokeAttribute_Type;
+
+#define BPy_StrokeAttribute_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeAttribute_Type) )
+
+/*---------------------------Python BPy_StrokeAttribute structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ StrokeAttribute *sa;
+ int borrowed; /* non-zero if *sa is a borrowed reference */
+} BPy_StrokeAttribute;
+
+/*---------------------------Python BPy_StrokeAttribute visible prototypes-----------*/
+
+int StrokeAttribute_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEATTRIBUTE_H */
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
new file mode 100644
index 00000000000..820f029223f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp
@@ -0,0 +1,297 @@
+#include "BPy_StrokeShader.h"
+
+#include "BPy_Convert.h"
+#include "Interface1D/BPy_Stroke.h"
+
+#include "StrokeShader/BPy_BackboneStretcherShader.h"
+#include "StrokeShader/BPy_BezierCurveShader.h"
+#include "StrokeShader/BPy_CalligraphicShader.h"
+#include "StrokeShader/BPy_ColorNoiseShader.h"
+#include "StrokeShader/BPy_ColorVariationPatternShader.h"
+#include "StrokeShader/BPy_ConstantColorShader.h"
+#include "StrokeShader/BPy_ConstantThicknessShader.h"
+#include "StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h"
+#include "StrokeShader/BPy_fstreamShader.h"
+#include "StrokeShader/BPy_GuidingLinesShader.h"
+#include "StrokeShader/BPy_IncreasingColorShader.h"
+#include "StrokeShader/BPy_IncreasingThicknessShader.h"
+#include "StrokeShader/BPy_PolygonalizationShader.h"
+#include "StrokeShader/BPy_SamplingShader.h"
+#include "StrokeShader/BPy_SmoothingShader.h"
+#include "StrokeShader/BPy_SpatialNoiseShader.h"
+#include "StrokeShader/BPy_streamShader.h"
+#include "StrokeShader/BPy_StrokeTextureShader.h"
+#include "StrokeShader/BPy_TextureAssignerShader.h"
+#include "StrokeShader/BPy_ThicknessNoiseShader.h"
+#include "StrokeShader/BPy_ThicknessVariationPatternShader.h"
+#include "StrokeShader/BPy_TipRemoverShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int StrokeShader_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &StrokeShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeShader_Type );
+ PyModule_AddObject(module, "StrokeShader", (PyObject *)&StrokeShader_Type);
+
+ if( PyType_Ready( &BackboneStretcherShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &BackboneStretcherShader_Type );
+ PyModule_AddObject(module, "BackboneStretcherShader", (PyObject *)&BackboneStretcherShader_Type);
+
+ if( PyType_Ready( &BezierCurveShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &BezierCurveShader_Type );
+ PyModule_AddObject(module, "BezierCurveShader", (PyObject *)&BezierCurveShader_Type);
+
+ if( PyType_Ready( &CalligraphicShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CalligraphicShader_Type );
+ PyModule_AddObject(module, "CalligraphicShader", (PyObject *)&CalligraphicShader_Type);
+
+ if( PyType_Ready( &ColorNoiseShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ColorNoiseShader_Type );
+ PyModule_AddObject(module, "ColorNoiseShader", (PyObject *)&ColorNoiseShader_Type);
+
+ if( PyType_Ready( &ColorVariationPatternShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ColorVariationPatternShader_Type );
+ PyModule_AddObject(module, "ColorVariationPatternShader", (PyObject *)&ColorVariationPatternShader_Type);
+
+ if( PyType_Ready( &ConstantColorShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ConstantColorShader_Type );
+ PyModule_AddObject(module, "ConstantColorShader", (PyObject *)&ConstantColorShader_Type);
+
+ if( PyType_Ready( &ConstantThicknessShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ConstantThicknessShader_Type );
+ PyModule_AddObject(module, "ConstantThicknessShader", (PyObject *)&ConstantThicknessShader_Type);
+
+ if( PyType_Ready( &ConstrainedIncreasingThicknessShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ConstrainedIncreasingThicknessShader_Type );
+ PyModule_AddObject(module, "ConstrainedIncreasingThicknessShader", (PyObject *)&ConstrainedIncreasingThicknessShader_Type);
+
+ if( PyType_Ready( &fstreamShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &fstreamShader_Type );
+ PyModule_AddObject(module, "fstreamShader", (PyObject *)&fstreamShader_Type);
+
+ if( PyType_Ready( &GuidingLinesShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GuidingLinesShader_Type );
+ PyModule_AddObject(module, "GuidingLinesShader", (PyObject *)&GuidingLinesShader_Type);
+
+ if( PyType_Ready( &IncreasingColorShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IncreasingColorShader_Type );
+ PyModule_AddObject(module, "IncreasingColorShader", (PyObject *)&IncreasingColorShader_Type);
+
+ if( PyType_Ready( &IncreasingThicknessShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IncreasingThicknessShader_Type );
+ PyModule_AddObject(module, "IncreasingThicknessShader", (PyObject *)&IncreasingThicknessShader_Type);
+
+ if( PyType_Ready( &PolygonalizationShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &PolygonalizationShader_Type );
+ PyModule_AddObject(module, "PolygonalizationShader", (PyObject *)&PolygonalizationShader_Type);
+
+ if( PyType_Ready( &SamplingShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SamplingShader_Type );
+ PyModule_AddObject(module, "SamplingShader", (PyObject *)&SamplingShader_Type);
+
+ if( PyType_Ready( &SmoothingShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SmoothingShader_Type );
+ PyModule_AddObject(module, "SmoothingShader", (PyObject *)&SmoothingShader_Type);
+
+ if( PyType_Ready( &SpatialNoiseShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &SpatialNoiseShader_Type );
+ PyModule_AddObject(module, "SpatialNoiseShader", (PyObject *)&SpatialNoiseShader_Type);
+
+ if( PyType_Ready( &streamShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &streamShader_Type );
+ PyModule_AddObject(module, "streamShader", (PyObject *)&streamShader_Type);
+
+ if( PyType_Ready( &StrokeTextureShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &StrokeTextureShader_Type );
+ PyModule_AddObject(module, "StrokeTextureShader", (PyObject *)&StrokeTextureShader_Type);
+
+ if( PyType_Ready( &TextureAssignerShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TextureAssignerShader_Type );
+ PyModule_AddObject(module, "TextureAssignerShader", (PyObject *)&TextureAssignerShader_Type);
+
+ if( PyType_Ready( &ThicknessNoiseShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ThicknessNoiseShader_Type );
+ PyModule_AddObject(module, "ThicknessNoiseShader", (PyObject *)&ThicknessNoiseShader_Type);
+
+ if( PyType_Ready( &ThicknessVariationPatternShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ThicknessVariationPatternShader_Type );
+ PyModule_AddObject(module, "ThicknessVariationPatternShader", (PyObject *)&ThicknessVariationPatternShader_Type);
+
+ if( PyType_Ready( &TipRemoverShader_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TipRemoverShader_Type );
+ PyModule_AddObject(module, "TipRemoverShader", (PyObject *)&TipRemoverShader_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeShader___doc__[] =
+"Base class for stroke shaders. Any stroke shader must inherit from\n"
+"this class and overload the shade() method. A StrokeShader is\n"
+"designed to modify stroke attributes such as thickness, color,\n"
+"geometry, texture, blending mode, and so on. The basic way for this\n"
+"operation is to iterate over the stroke vertices of the :class:`Stroke`\n"
+"and to modify the :class:`StrokeAttribute` of each vertex. Here is a\n"
+"code example of such an iteration::\n"
+"\n"
+" it = ioStroke.strokeVerticesBegin()\n"
+" while it.isEnd() == 0:\n"
+" att = it.getObject().attribute()\n"
+" ## perform here any attribute modification\n"
+" it.increment()\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int StrokeShader___init__(BPy_StrokeShader *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->ss = new StrokeShader();
+ self->ss->py_ss = (PyObject *) self;
+ return 0;
+}
+
+static void StrokeShader___dealloc__(BPy_StrokeShader* self)
+{
+ if (self->ss)
+ delete self->ss;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * StrokeShader___repr__(BPy_StrokeShader* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->ss->getName().c_str(), self->ss );
+}
+
+static char StrokeShader_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of this stroke shader.\n"
+"\n"
+" :return: The name of this stroke shader.\n"
+" :rtype: string\n";
+
+static PyObject * StrokeShader_getName( BPy_StrokeShader *self, PyObject *args)
+{
+ return PyUnicode_FromFormat( self->ss->getName().c_str() );
+}
+
+static char StrokeShader_shade___doc__[] =
+".. method:: shade(s)\n"
+"\n"
+" The shading method. Must be overloaded by inherited classes.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static PyObject *StrokeShader_shade( BPy_StrokeShader *self , PyObject *args) {
+ PyObject *py_s = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Stroke_Type, &py_s) ))
+ return NULL;
+
+ if( typeid(*(self->ss)) == typeid(StrokeShader) ) {
+ PyErr_SetString(PyExc_TypeError, "shade method not properly overridden");
+ return NULL;
+ }
+ if (self->ss->shade(*( ((BPy_Stroke *) py_s)->s )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->ss->getName() + " shade method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+/*----------------------StrokeShader instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeShader_methods[] = {
+ {"getName", ( PyCFunction ) StrokeShader_getName, METH_NOARGS, StrokeShader_getName___doc__},
+ {"shade", ( PyCFunction ) StrokeShader_shade, METH_VARARGS, StrokeShader_shade___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeShader type definition ------------------------------*/
+
+PyTypeObject StrokeShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeShader", /* tp_name */
+ sizeof(BPy_StrokeShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)StrokeShader___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)StrokeShader___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeShader_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.h b/source/blender/freestyle/intern/python/BPy_StrokeShader.h
new file mode 100644
index 00000000000..baa31a3100e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.h
@@ -0,0 +1,40 @@
+#ifndef FREESTYLE_PYTHON_STROKESHADER_H
+#define FREESTYLE_PYTHON_STROKESHADER_H
+
+#include <Python.h>
+
+#include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+#include "../stroke/StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject StrokeShader_Type;
+
+#define BPy_StrokeShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeShader_Type) )
+
+/*---------------------------Python BPy_StrokeShader structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ StrokeShader *ss;
+} BPy_StrokeShader;
+
+/*---------------------------Python BPy_StrokeShader visible prototypes-----------*/
+
+int StrokeShader_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_STROKESHADER_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
new file mode 100644
index 00000000000..b254786897c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp
@@ -0,0 +1,126 @@
+#include "BPy_UnaryFunction0D.h"
+
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryFunction0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0D_Type );
+ PyModule_AddObject(module, "UnaryFunction0D", (PyObject *)&UnaryFunction0D_Type);
+
+ UnaryFunction0DDouble_Init( module );
+ UnaryFunction0DEdgeNature_Init( module );
+ UnaryFunction0DFloat_Init( module );
+ UnaryFunction0DId_Init( module );
+ UnaryFunction0DMaterial_Init( module );
+ UnaryFunction0DUnsigned_Init( module );
+ UnaryFunction0DVec2f_Init( module );
+ UnaryFunction0DVec3f_Init( module );
+ UnaryFunction0DVectorViewShape_Init( module );
+ UnaryFunction0DViewShape_Init( module );
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0D___doc__[] =
+"Base class for Unary Functions (functors) working on\n"
+":class:`Interface0DIterator`. A unary function will be used by\n"
+"invoking __call__() on an Interface0DIterator. In Python, several\n"
+"different subclasses of UnaryFunction0D are used depending on the\n"
+"types of functors' return values. For example, you would inherit from\n"
+"a :class:`UnaryFunction0DDouble` if you wish to define a function that\n"
+"returns a double value. Available UnaryFunction0D subclasses are:\n"
+"\n"
+"* :class:`UnaryFunction0DDouble`\n"
+"* :class:`UnaryFunction0DEdgeNature`\n"
+"* :class:`UnaryFunction0DFloat`\n"
+"* :class:`UnaryFunction0DId`\n"
+"* :class:`UnaryFunction0DMaterial`\n"
+"* :class:`UnaryFunction0DUnsigned`\n"
+"* :class:`UnaryFunction0DVec2f`\n"
+"* :class:`UnaryFunction0DVec3f`\n"
+"* :class:`UnaryFunction0DVectorViewShape`\n"
+"* :class:`UnaryFunction0DViewShape`\n";
+
+static void UnaryFunction0D___dealloc__(BPy_UnaryFunction0D* self)
+{
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+
+static PyObject * UnaryFunction0D___repr__(BPy_UnaryFunction0D* self)
+{
+ return PyUnicode_FromFormat("UnaryFunction0D");
+}
+
+/*-----------------------BPy_UnaryFunction0D type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0D", /* tp_name */
+ sizeof(BPy_UnaryFunction0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
new file mode 100644
index 00000000000..6d61c336662
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0D_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0D_H
+
+#include <Python.h>
+
+#include "../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryFunction0D_Type;
+
+#define BPy_UnaryFunction0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0D_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ PyObject *py_uf0D;
+} BPy_UnaryFunction0D;
+
+/*---------------------------Python BPy_UnaryFunction0D visible prototypes-----------*/
+
+int UnaryFunction0D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
new file mode 100644
index 00000000000..a9ca73003f5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp
@@ -0,0 +1,117 @@
+#include "BPy_UnaryFunction1D.h"
+
+#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryFunction1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1D_Type );
+ PyModule_AddObject(module, "UnaryFunction1D", (PyObject *)&UnaryFunction1D_Type);
+
+ UnaryFunction1DDouble_Init( module );
+ UnaryFunction1DEdgeNature_Init( module );
+ UnaryFunction1DFloat_Init( module );
+ UnaryFunction1DUnsigned_Init( module );
+ UnaryFunction1DVec2f_Init( module );
+ UnaryFunction1DVec3f_Init( module );
+ UnaryFunction1DVectorViewShape_Init( module );
+ UnaryFunction1DVoid_Init( module );
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1D___doc__[] =
+"Base class for Unary Functions (functors) working on\n"
+":class:`Interface1D`. A unary function will be used by invoking\n"
+"__call__() on an Interface1D. In Python, several different subclasses\n"
+"of UnaryFunction1D are used depending on the types of functors' return\n"
+"values. For example, you would inherit from a\n"
+":class:`UnaryFunction1DDouble` if you wish to define a function that\n"
+"returns a double value. Available UnaryFunction1D subclasses are:\n"
+"\n"
+"* :class:`UnaryFunction1DDouble`\n"
+"* :class:`UnaryFunction1DEdgeNature`\n"
+"* :class:`UnaryFunction1DFloat`\n"
+"* :class:`UnaryFunction1DUnsigned`\n"
+"* :class:`UnaryFunction1DVec2f`\n"
+"* :class:`UnaryFunction1DVec3f`\n"
+"* :class:`UnaryFunction1DVectorViewShape`\n"
+"* :class:`UnaryFunction1DVoid`\n";
+
+static void UnaryFunction1D___dealloc__(BPy_UnaryFunction1D* self)
+{
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1D___repr__(BPy_UnaryFunction1D* self)
+{
+ return PyUnicode_FromFormat("UnaryFunction1D");
+}
+
+/*-----------------------BPy_UnaryFunction1D type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1D", /* tp_name */
+ sizeof(BPy_UnaryFunction1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
new file mode 100644
index 00000000000..cb9df18ab75
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1D_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1D_H
+
+#include <Python.h>
+
+#include "../view_map/Functions1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryFunction1D_Type;
+
+#define BPy_UnaryFunction1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1D_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ PyObject *py_uf1D;
+} BPy_UnaryFunction1D;
+
+/*---------------------------Python BPy_UnaryFunction1D visible prototypes-----------*/
+
+int UnaryFunction1D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
new file mode 100644
index 00000000000..9de3c5cc389
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp
@@ -0,0 +1,184 @@
+#include "BPy_UnaryPredicate0D.h"
+
+#include "BPy_Convert.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "UnaryPredicate0D/BPy_FalseUP0D.h"
+#include "UnaryPredicate0D/BPy_TrueUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryPredicate0D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryPredicate0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryPredicate0D_Type );
+ PyModule_AddObject(module, "UnaryPredicate0D", (PyObject *)&UnaryPredicate0D_Type);
+
+ if( PyType_Ready( &FalseUP0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FalseUP0D_Type );
+ PyModule_AddObject(module, "FalseUP0D", (PyObject *)&FalseUP0D_Type);
+
+ if( PyType_Ready( &TrueUP0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TrueUP0D_Type );
+ PyModule_AddObject(module, "TrueUP0D", (PyObject *)&TrueUP0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryPredicate0D___doc__[] =
+"Base class for unary predicates that work on\n"
+":class:`Interface0DIterator`. A UnaryPredicate0D is a functor that\n"
+"evaluates a condition on an Interface0DIterator and returns true or\n"
+"false depending on whether this condition is satisfied or not. The\n"
+"UnaryPredicate0D is used by invoking its __call__() method. Any\n"
+"inherited class must overload the __call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Must be overload by inherited classes.\n"
+"\n"
+" :arg it: The Interface0DIterator pointing onto the Interface0D at\n"
+" which we wish to evaluate the predicate.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: True if the condition is satisfied, false otherwise.\n"
+" :rtype: bool\n";
+
+static int UnaryPredicate0D___init__(BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->up0D = new UnaryPredicate0D();
+ self->up0D->py_up0D = (PyObject *) self;
+ return 0;
+}
+
+static void UnaryPredicate0D___dealloc__(BPy_UnaryPredicate0D* self)
+{
+ if (self->up0D)
+ delete self->up0D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * UnaryPredicate0D___repr__(BPy_UnaryPredicate0D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->up0D->getName().c_str(), self->up0D );
+}
+
+static char UnaryPredicate0D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the UnaryPredicate0D.\n"
+"\n"
+" :return: The name of the UnaryPredicate0D.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryPredicate0D_getName( BPy_UnaryPredicate0D *self )
+{
+ return PyUnicode_FromFormat( self->up0D->getName().c_str() );
+}
+
+static PyObject * UnaryPredicate0D___call__( BPy_UnaryPredicate0D *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_if0D_it;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &py_if0D_it) )
+ return NULL;
+
+ Interface0DIterator *if0D_it = ((BPy_Interface0DIterator *) py_if0D_it)->if0D_it;
+
+ if( !if0D_it ) {
+ string msg(self->up0D->getName() + " has no Interface0DIterator");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ return NULL;
+ }
+ if( typeid(*(self->up0D)) == typeid(UnaryPredicate0D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->up0D->operator()(*if0D_it) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->up0D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->up0D->result );
+}
+
+/*----------------------UnaryPredicate0D instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryPredicate0D_methods[] = {
+ {"getName", ( PyCFunction ) UnaryPredicate0D_getName, METH_NOARGS, UnaryPredicate0D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryPredicate0D type definition ------------------------------*/
+
+PyTypeObject UnaryPredicate0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryPredicate0D", /* tp_name */
+ sizeof(BPy_UnaryPredicate0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryPredicate0D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryPredicate0D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryPredicate0D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryPredicate0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryPredicate0D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryPredicate0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
new file mode 100644
index 00000000000..9f9bb0c1003
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYPREDICATE0D_H
+#define FREESTYLE_PYTHON_UNARYPREDICATE0D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryPredicate0D_Type;
+
+#define BPy_UnaryPredicate0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryPredicate0D_Type) )
+
+/*---------------------------Python BPy_UnaryPredicate0D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ UnaryPredicate0D *up0D;
+} BPy_UnaryPredicate0D;
+
+/*---------------------------Python BPy_UnaryPredicate0D visible prototypes-----------*/
+
+int UnaryPredicate0D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYPREDICATE0D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
new file mode 100644
index 00000000000..8f68bba17b1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp
@@ -0,0 +1,230 @@
+#include "BPy_UnaryPredicate1D.h"
+
+#include "BPy_Convert.h"
+#include "BPy_Interface1D.h"
+
+#include "UnaryPredicate1D/BPy_ContourUP1D.h"
+#include "UnaryPredicate1D/BPy_DensityLowerThanUP1D.h"
+#include "UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h"
+#include "UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h"
+#include "UnaryPredicate1D/BPy_ExternalContourUP1D.h"
+#include "UnaryPredicate1D/BPy_FalseUP1D.h"
+#include "UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h"
+#include "UnaryPredicate1D/BPy_ShapeUP1D.h"
+#include "UnaryPredicate1D/BPy_TrueUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int UnaryPredicate1D_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryPredicate1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryPredicate1D_Type );
+ PyModule_AddObject(module, "UnaryPredicate1D", (PyObject *)&UnaryPredicate1D_Type);
+
+ if( PyType_Ready( &ContourUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ContourUP1D_Type );
+ PyModule_AddObject(module, "ContourUP1D", (PyObject *)&ContourUP1D_Type);
+
+ if( PyType_Ready( &DensityLowerThanUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &DensityLowerThanUP1D_Type );
+ PyModule_AddObject(module, "DensityLowerThanUP1D", (PyObject *)&DensityLowerThanUP1D_Type);
+
+ if( PyType_Ready( &EqualToChainingTimeStampUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &EqualToChainingTimeStampUP1D_Type );
+ PyModule_AddObject(module, "EqualToChainingTimeStampUP1D", (PyObject *)&EqualToChainingTimeStampUP1D_Type);
+
+ if( PyType_Ready( &EqualToTimeStampUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &EqualToTimeStampUP1D_Type );
+ PyModule_AddObject(module, "EqualToTimeStampUP1D", (PyObject *)&EqualToTimeStampUP1D_Type);
+
+ if( PyType_Ready( &ExternalContourUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ExternalContourUP1D_Type );
+ PyModule_AddObject(module, "ExternalContourUP1D", (PyObject *)&ExternalContourUP1D_Type);
+
+ if( PyType_Ready( &FalseUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &FalseUP1D_Type );
+ PyModule_AddObject(module, "FalseUP1D", (PyObject *)&FalseUP1D_Type);
+
+ if( PyType_Ready( &QuantitativeInvisibilityUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &QuantitativeInvisibilityUP1D_Type );
+ PyModule_AddObject(module, "QuantitativeInvisibilityUP1D", (PyObject *)&QuantitativeInvisibilityUP1D_Type);
+
+ if( PyType_Ready( &ShapeUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ShapeUP1D_Type );
+ PyModule_AddObject(module, "ShapeUP1D", (PyObject *)&ShapeUP1D_Type);
+
+ if( PyType_Ready( &TrueUP1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TrueUP1D_Type );
+ PyModule_AddObject(module, "TrueUP1D", (PyObject *)&TrueUP1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryPredicate1D___doc__[] =
+"Base class for unary predicates that work on :class:`Interface1D`. A\n"
+"UnaryPredicate1D is a functor that evaluates a condition on a\n"
+"Interface1D and returns true or false depending on whether this\n"
+"condition is satisfied or not. The UnaryPredicate1D is used by\n"
+"invoking its __call__() method. Any inherited class must overload the\n"
+"__call__() method.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Must be overload by inherited classes.\n"
+"\n"
+" :arg inter: The Interface1D on which we wish to evaluate the predicate.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the condition is satisfied, false otherwise.\n"
+" :rtype: bool\n";
+
+static int UnaryPredicate1D___init__(BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->up1D = new UnaryPredicate1D();
+ self->up1D->py_up1D = (PyObject *) self;
+ return 0;
+}
+
+static void UnaryPredicate1D___dealloc__(BPy_UnaryPredicate1D* self)
+{
+ if (self->up1D)
+ delete self->up1D;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * UnaryPredicate1D___repr__(BPy_UnaryPredicate1D* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->up1D->getName().c_str(), self->up1D );
+}
+
+static char UnaryPredicate1D_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the string of the name of the UnaryPredicate1D.\n"
+"\n"
+" Reimplemented in TrueUP1D, FalseUP1D, QuantitativeInvisibilityUP1D,\n"
+" ContourUP1D, ExternalContourUP1D, EqualToTimeStampUP1D,\n"
+" EqualToChainingTimeStampUP1D, ShapeUP1D, and DensityLowerThanUP1D.\n"
+"\n"
+" :return: \n"
+" :rtype: string\n";
+
+static PyObject * UnaryPredicate1D_getName( BPy_UnaryPredicate1D *self, PyObject *args)
+{
+ return PyUnicode_FromFormat( self->up1D->getName().c_str() );
+}
+
+static PyObject * UnaryPredicate1D___call__( BPy_UnaryPredicate1D *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_if1D;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &py_if1D) )
+ return NULL;
+
+ Interface1D *if1D = ((BPy_Interface1D *) py_if1D)->if1D;
+
+ if( !if1D ) {
+ string msg(self->up1D->getName() + " has no Interface0DIterator");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ return NULL;
+ }
+ if( typeid(*(self->up1D)) == typeid(UnaryPredicate1D) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if( self->up1D->operator()(*if1D) < 0 ) {
+ if (!PyErr_Occurred()) {
+ string msg(self->up1D->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyBool_from_bool( self->up1D->result );
+}
+
+/*----------------------UnaryPredicate1D instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryPredicate1D_methods[] = {
+ {"getName", ( PyCFunction ) UnaryPredicate1D_getName, METH_NOARGS, UnaryPredicate1D_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryPredicate1D type definition ------------------------------*/
+
+PyTypeObject UnaryPredicate1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryPredicate1D", /* tp_name */
+ sizeof(BPy_UnaryPredicate1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryPredicate1D___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryPredicate1D___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryPredicate1D___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryPredicate1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryPredicate1D_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryPredicate1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
new file mode 100644
index 00000000000..75953e7977b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYPREDICATE1D_H
+#define FREESTYLE_PYTHON_UNARYPREDICATE1D_H
+
+#include <Python.h>
+
+#include "../stroke/Predicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject UnaryPredicate1D_Type;
+
+#define BPy_UnaryPredicate1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryPredicate1D_Type) )
+
+/*---------------------------Python BPy_UnaryPredicate1D structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ UnaryPredicate1D *up1D;
+} BPy_UnaryPredicate1D;
+
+/*---------------------------Python BPy_UnaryPredicate1D visible prototypes-----------*/
+
+int UnaryPredicate1D_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYPREDICATE1D_H */
diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.cpp b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp
new file mode 100644
index 00000000000..c9667103e5a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp
@@ -0,0 +1,195 @@
+#include "BPy_ViewMap.h"
+
+#include "BPy_Convert.h"
+#include "BPy_BBox.h"
+#include "Interface1D/BPy_FEdge.h"
+#include "Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int ViewMap_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &ViewMap_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &ViewMap_Type );
+ PyModule_AddObject(module, "ViewMap", (PyObject *)&ViewMap_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewMap___doc__[] =
+"Class defining the ViewMap.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int ViewMap___init__(BPy_ViewMap *self, PyObject *args, PyObject *kwds)
+{
+ self->vm = new ViewMap();
+ return 0;
+}
+
+static void ViewMap___dealloc__(BPy_ViewMap *self)
+{
+ if( self->vm )
+ delete self->vm;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * ViewMap___repr__(BPy_ViewMap *self)
+{
+ return PyUnicode_FromFormat("ViewMap - address: %p", self->vm );
+}
+
+static char ViewMap_getClosestViewEdge___doc__[] =
+".. method:: getClosestViewEdge(x, y)\n"
+"\n"
+" Gets the ViewEdge nearest to the 2D point specified as arguments.\n"
+"\n"
+" :arg x: X coordinate of a 2D point.\n"
+" :type x: float\n"
+" :arg y: Y coordinate of a 2D point.\n"
+" :type y: float\n"
+" :return: The ViewEdge nearest to the specified 2D point.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * ViewMap_getClosestViewEdge( BPy_ViewMap *self , PyObject *args) {
+ double x, y;
+
+ if(!( PyArg_ParseTuple(args, "dd", &x, &y) ))
+ return NULL;
+
+ ViewEdge *ve = const_cast<ViewEdge *>( self->vm->getClosestViewEdge(x,y) );
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge(*ve);
+
+ Py_RETURN_NONE;
+}
+
+static char ViewMap_getClosestFEdge___doc__[] =
+".. method:: getClosestFEdge(x, y)\n"
+"\n"
+" Gets the FEdge nearest to the 2D point specified as arguments.\n"
+"\n"
+" :arg x: X coordinate of a 2D point.\n"
+" :type x: float\n"
+" :arg y: Y coordinate of a 2D point.\n"
+" :type y: float\n"
+" :return: The FEdge nearest to the specified 2D point.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * ViewMap_getClosestFEdge( BPy_ViewMap *self , PyObject *args) {
+ double x, y;
+
+ if(!( PyArg_ParseTuple(args, "dd", &x, &y) ))
+ return NULL;
+
+ FEdge *fe = const_cast<FEdge *>( self->vm->getClosestFEdge(x,y) );
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge(*fe);
+
+ Py_RETURN_NONE;
+}
+
+static char ViewMap_getScene3dBBox___doc__[] =
+".. method:: getScene3dBBox()\n"
+"\n"
+" Returns the scene 3D bounding box.\n"
+"\n"
+" :return: The scene 3D bounding box.\n"
+" :rtype: :class:`BBox`\n";
+
+static PyObject * ViewMap_getScene3dBBox( BPy_ViewMap *self , PyObject *args) {
+ BBox<Vec3r> bb( self->vm->getScene3dBBox() );
+ return BPy_BBox_from_BBox( bb );
+}
+
+static char ViewMap_setScene3dBBox___doc__[] =
+".. method:: setScene3dBBox(bbox)\n"
+"\n"
+" Sets the scene 3D bounding box.\n"
+"\n"
+" :arg bbox: The scene 3D bounding box.\n"
+" :type bbox: :class:`BBox`\n";
+
+static PyObject * ViewMap_setScene3dBBox( BPy_ViewMap *self , PyObject *args) {
+ PyObject *py_bb = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &BBox_Type, &py_bb) ))
+ return NULL;
+
+ self->vm->setScene3dBBox(*( ((BPy_BBox *) py_bb)->bb ));
+
+ Py_RETURN_NONE;
+}
+
+// static ViewMap *getInstance ();
+
+/*---------------------- BPy_ViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewMap_methods[] = {
+ {"getClosestViewEdge", ( PyCFunction ) ViewMap_getClosestViewEdge, METH_VARARGS, ViewMap_getClosestViewEdge___doc__},
+ {"getClosestFEdge", ( PyCFunction ) ViewMap_getClosestFEdge, METH_VARARGS, ViewMap_getClosestFEdge___doc__},
+ {"getScene3dBBox", ( PyCFunction ) ViewMap_getScene3dBBox, METH_NOARGS, ViewMap_getScene3dBBox___doc__},
+ {"setScene3dBBox", ( PyCFunction ) ViewMap_setScene3dBBox, METH_VARARGS, ViewMap_setScene3dBBox___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewMap type definition ------------------------------*/
+
+PyTypeObject ViewMap_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewMap", /* tp_name */
+ sizeof(BPy_ViewMap), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ViewMap___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ViewMap___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewMap___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewMap_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewMap___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.h b/source/blender/freestyle/intern/python/BPy_ViewMap.h
new file mode 100644
index 00000000000..943aeb718fc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewMap.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_VIEWMAP_H
+#define FREESTYLE_PYTHON_VIEWMAP_H
+
+#include <Python.h>
+
+#include "../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject ViewMap_Type;
+
+#define BPy_ViewMap_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewMap_Type) )
+
+/*---------------------------Python BPy_ViewMap structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ ViewMap *vm;
+} BPy_ViewMap;
+
+/*---------------------------Python BPy_ViewMap visible prototypes-----------*/
+
+int ViewMap_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWMAP_H */
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
new file mode 100644
index 00000000000..8849b6b3776
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp
@@ -0,0 +1,340 @@
+#include "BPy_ViewShape.h"
+
+#include "BPy_Convert.h"
+#include "Interface0D/BPy_ViewVertex.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "BPy_SShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+int ViewShape_Init( PyObject *module )
+{
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &ViewShape_Type ) < 0 )
+ return -1;
+
+ Py_INCREF( &ViewShape_Type );
+ PyModule_AddObject(module, "ViewShape", (PyObject *)&ViewShape_Type);
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewShape___doc__[] =
+"Class gathering the elements of the ViewMap (i.e., :class:`ViewVertex`\n"
+"and :class:`ViewEdge`) that are issued from the same input shape.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewShape object.\n"
+" :type iBrother: :class:`ViewShape`\n"
+"\n"
+".. method:: __init__(iSShape)\n"
+"\n"
+" Builds a ViewShape from an SShape.\n"
+"\n"
+" :arg iSShape: An SShape object.\n"
+" :type iSShape: :class:`SShape`\n";
+
+static int ViewShape___init__(BPy_ViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ) {
+ self->vs = new ViewShape();
+
+ } else if( BPy_SShape_Check(obj) ) {
+ self->vs = new ViewShape( ((BPy_SShape *) obj)->ss );
+
+ } else if( BPy_ViewShape_Check(obj) ) {
+ self->vs = new ViewShape(*( ((BPy_ViewShape *) obj)->vs ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+ self->borrowed = 0;
+
+ return 0;
+}
+
+static void ViewShape___dealloc__(BPy_ViewShape *self)
+{
+ if( self->vs && !self->borrowed )
+ delete self->vs;
+ Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject * ViewShape___repr__(BPy_ViewShape *self)
+{
+ return PyUnicode_FromFormat("ViewShape - address: %p", self->vs );
+}
+
+static char ViewShape_sshape___doc__[] =
+".. method:: sshape()\n"
+"\n"
+" Returns the SShape on top of which this ViewShape is built.\n"
+"\n"
+" :return: The SShape on top of which this ViewShape is built.\n"
+" :rtype: :class:`SShape`\n";
+
+static PyObject * ViewShape_sshape( BPy_ViewShape *self ) {
+ return BPy_SShape_from_SShape( *(self->vs->sshape()) );
+}
+
+static char ViewShape_vertices___doc__[] =
+".. method:: vertices()\n"
+"\n"
+" Returns the list of ViewVertex objects contained in this ViewShape.\n"
+"\n"
+" :return: The list of ViewVertex objects.\n"
+" :rtype: List of :class:`ViewVertex` objects\n";
+
+static PyObject * ViewShape_vertices( BPy_ViewShape *self ) {
+ PyObject *py_vertices = PyList_New(0);
+
+ vector< ViewVertex * > vertices = self->vs->vertices();
+ vector< ViewVertex * >::iterator it;
+
+ for( it = vertices.begin(); it != vertices.end(); it++ ) {
+ PyList_Append( py_vertices, Any_BPy_ViewVertex_from_ViewVertex(*( *it )) );
+ }
+
+ return py_vertices;
+}
+
+static char ViewShape_edges___doc__[] =
+".. method:: edges()\n"
+"\n"
+" Returns the list of ViewEdge objects contained in this ViewShape.\n"
+"\n"
+" :return: The list of ViewEdge objects.\n"
+" :rtype: List of :class:`ViewEdge` objects\n";
+
+static PyObject * ViewShape_edges( BPy_ViewShape *self ) {
+ PyObject *py_edges = PyList_New(0);
+
+ vector< ViewEdge * > edges = self->vs->edges();
+ vector< ViewEdge * >::iterator it;
+
+ for( it = edges.begin(); it != edges.end(); it++ ) {
+ PyList_Append( py_edges, BPy_ViewEdge_from_ViewEdge(*( *it )) );
+ }
+
+ return py_edges;
+}
+
+static char ViewShape_getId___doc__[] =
+".. method:: getId()\n"
+"\n"
+" Returns the ViewShape id.\n"
+"\n"
+" :return: An Id object.\n"
+" :rtype: :class:`Id`\n";
+
+static PyObject * ViewShape_getId( BPy_ViewShape *self ) {
+ Id id( self->vs->getId() );
+ return BPy_Id_from_Id( id );
+}
+
+static char ViewShape_setSShape___doc__[] =
+".. method:: setSShape(iSShape)\n"
+"\n"
+" Sets the SShape on top of which the ViewShape is built.\n"
+"\n"
+" :arg iSShape: An SShape object.\n"
+" :type iSShape: :class:`SShape`\n";
+
+static PyObject * ViewShape_setSShape( BPy_ViewShape *self , PyObject *args) {
+ PyObject *py_ss = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SShape_Type, &py_ss) ))
+ return NULL;
+
+ self->vs->setSShape( ((BPy_SShape *) py_ss)->ss );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_setVertices___doc__[] =
+".. method:: setVertices(iVertices)\n"
+"\n"
+" Sets the list of ViewVertex objects contained in this ViewShape.\n"
+"\n"
+" :arg iVertices: The list of ViewVertex objects.\n"
+" :type iVertices: List of :class:`ViewVertex` objects\n";
+
+static PyObject * ViewShape_setVertices( BPy_ViewShape *self , PyObject *args) {
+ PyObject *list = 0;
+ PyObject *tmp;
+
+ if(!( PyArg_ParseTuple(args, "O!", &PyList_Type, &list) ))
+ return NULL;
+
+ vector< ViewVertex *> v;
+
+ for( int i=0; i < PyList_Size(list); i++ ) {
+ tmp = PyList_GetItem(list, i);
+ if( BPy_ViewVertex_Check(tmp) )
+ v.push_back( ((BPy_ViewVertex *) tmp)->vv );
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be list of ViewVertex objects");
+ return NULL;
+ }
+ }
+
+ self->vs->setVertices( v );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_setEdges___doc__[] =
+".. method:: setEdges(iEdges)\n"
+"\n"
+" Sets the list of ViewEdge objects contained in this ViewShape.\n"
+"\n"
+" :arg iEdges: The list of ViewEdge objects.\n"
+" :type iEdges: List of :class:`ViewEdge` objects.\n";
+
+static PyObject * ViewShape_setEdges( BPy_ViewShape *self , PyObject *args) {
+ PyObject *list = 0;
+ PyObject *tmp;
+
+ if(!( PyArg_ParseTuple(args, "O!", &PyList_Type, &list) ))
+ return NULL;
+
+ vector<ViewEdge *> v;
+
+ for( int i=0; i < PyList_Size(list); i++ ) {
+ tmp = PyList_GetItem(list, i);
+ if( BPy_ViewEdge_Check(tmp) )
+ v.push_back( ((BPy_ViewEdge *) tmp)->ve );
+ else {
+ PyErr_SetString(PyExc_TypeError, "argument must be list of ViewEdge objects");
+ return NULL;
+ }
+ }
+
+ self->vs->setEdges( v );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_AddEdge___doc__[] =
+".. method:: AddEdge(iEdge)\n"
+"\n"
+" Adds a ViewEdge to the list of ViewEdge objects.\n"
+"\n"
+" :arg iEdge: A ViewEdge object.\n"
+" :type iEdge: :class:`ViewEdge`\n";
+
+static PyObject * ViewShape_AddEdge( BPy_ViewShape *self , PyObject *args) {
+ PyObject *py_ve = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ self->vs->AddEdge( ((BPy_ViewEdge *) py_ve)->ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewShape_AddVertex___doc__[] =
+".. method:: AddVertex(iVertex)\n"
+"\n"
+" Adds a ViewVertex to the list of the ViewVertex objects.\n"
+"\n"
+" :arg iVertex: A ViewVertex object.\n"
+" :type iVertex: :class:`ViewVertex`\n";
+
+static PyObject * ViewShape_AddVertex( BPy_ViewShape *self , PyObject *args) {
+ PyObject *py_vv = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) ))
+ return NULL;
+
+ self->vs->AddVertex( ((BPy_ViewVertex *) py_vv)->vv );
+
+ Py_RETURN_NONE;
+}
+
+// virtual ViewShape * duplicate ()
+
+/*---------------------- BPy_ViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewShape_methods[] = {
+ {"sshape", ( PyCFunction ) ViewShape_sshape, METH_NOARGS, ViewShape_sshape___doc__},
+ {"vertices", ( PyCFunction ) ViewShape_vertices, METH_NOARGS, ViewShape_vertices___doc__},
+ {"edges", ( PyCFunction ) ViewShape_edges, METH_NOARGS, ViewShape_edges___doc__},
+ {"getId", ( PyCFunction ) ViewShape_getId, METH_NOARGS, ViewShape_getId___doc__},
+ {"setSShape", ( PyCFunction ) ViewShape_setSShape, METH_VARARGS, ViewShape_setSShape___doc__},
+ {"setVertices", ( PyCFunction ) ViewShape_setVertices, METH_VARARGS, ViewShape_setVertices___doc__},
+ {"setEdges", ( PyCFunction ) ViewShape_setEdges, METH_VARARGS, ViewShape_setEdges___doc__},
+ {"AddEdge", ( PyCFunction ) ViewShape_AddEdge, METH_VARARGS, ViewShape_AddEdge___doc__},
+ {"AddVertex", ( PyCFunction ) ViewShape_AddVertex, METH_VARARGS, ViewShape_AddVertex___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewShape type definition ------------------------------*/
+
+PyTypeObject ViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewShape", /* tp_name */
+ sizeof(BPy_ViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)ViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.h b/source/blender/freestyle/intern/python/BPy_ViewShape.h
new file mode 100644
index 00000000000..1850ec8f13a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BPy_ViewShape.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_VIEWSHAPE_H
+#define FREESTYLE_PYTHON_VIEWSHAPE_H
+
+#include <Python.h>
+
+#include "../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+extern PyTypeObject ViewShape_Type;
+
+#define BPy_ViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewShape_Type) )
+
+/*---------------------------Python BPy_ViewShape structure definition----------*/
+typedef struct {
+ PyObject_HEAD
+ ViewShape *vs;
+ int borrowed; /* non-zero if *vs a borrowed object */
+} BPy_ViewShape;
+
+/*---------------------------Python BPy_ViewShape visible prototypes-----------*/
+
+int ViewShape_Init( PyObject *module );
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
new file mode 100644
index 00000000000..78566d915d6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp
@@ -0,0 +1,77 @@
+#include "BPy_FalseBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseBP1D___doc__[] =
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseBP1D___init__( BPy_FalseBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::FalseBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseBP1D type definition ------------------------------*/
+PyTypeObject FalseBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseBP1D", /* tp_name */
+ sizeof(BPy_FalseBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FalseBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
new file mode 100644
index 00000000000..a8d4aad88aa
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_FALSEBP1D_H
+#define FREESTYLE_PYTHON_FALSEBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseBP1D_Type;
+
+#define BPy_FalseBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseBP1D_Type) )
+
+/*---------------------------Python BPy_FalseBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_FalseBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FALSEBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
new file mode 100644
index 00000000000..5249e2ba6b0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp
@@ -0,0 +1,79 @@
+#include "BPy_Length2DBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Length2DBP1D___doc__[] =
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if the 2D length of inter1 is less than the 2D length\n"
+" of inter2.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int Length2DBP1D___init__( BPy_Length2DBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::Length2DBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_Length2DBP1D type definition ------------------------------*/
+
+PyTypeObject Length2DBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Length2DBP1D", /* tp_name */
+ sizeof(BPy_Length2DBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Length2DBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Length2DBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
new file mode 100644
index 00000000000..d5bce5b150d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_LENGTH2DBP1D_H
+#define FREESTYLE_PYTHON_LENGTH2DBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Length2DBP1D_Type;
+
+#define BPy_Length2DBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Length2DBP1D_Type) )
+
+/*---------------------------Python BPy_Length2DBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_Length2DBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_LENGTH2DBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
new file mode 100644
index 00000000000..5255752ff71
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp
@@ -0,0 +1,78 @@
+#include "BPy_SameShapeIdBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SameShapeIdBP1D___doc__[] =
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if inter1 and inter2 belong to the same shape.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int SameShapeIdBP1D___init__( BPy_SameShapeIdBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::SameShapeIdBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_SameShapeIdBP1D type definition ------------------------------*/
+
+PyTypeObject SameShapeIdBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SameShapeIdBP1D", /* tp_name */
+ sizeof(BPy_SameShapeIdBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SameShapeIdBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SameShapeIdBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
new file mode 100644
index 00000000000..71065d4ceeb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H
+#define FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SameShapeIdBP1D_Type;
+
+#define BPy_SameShapeIdBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SameShapeIdBP1D_Type) )
+
+/*---------------------------Python BPy_SameShapeIdBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_SameShapeIdBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SAMESHAPEIDBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
new file mode 100644
index 00000000000..6df906a31d5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp
@@ -0,0 +1,78 @@
+#include "BPy_TrueBP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueBP1D___doc__[] =
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueBP1D___init__( BPy_TrueBP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_bp1D.bp1D = new Predicates1D::TrueBP1D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueBP1D type definition ------------------------------*/
+
+PyTypeObject TrueBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueBP1D", /* tp_name */
+ sizeof(BPy_TrueBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TrueBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
new file mode 100644
index 00000000000..7d809e1fe65
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_TRUEBP1D_H
+#define FREESTYLE_PYTHON_TRUEBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueBP1D_Type;
+
+#define BPy_TrueBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueBP1D_Type) )
+
+/*---------------------------Python BPy_TrueBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_TrueBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TRUEBP1D_H */
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
new file mode 100644
index 00000000000..5f433ae3e22
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp
@@ -0,0 +1,90 @@
+#include "BPy_ViewMapGradientNormBP1D.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+//ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0)
+
+static char ViewMapGradientNormBP1D___doc__[] =
+".. method:: __call__(inter1, inter2)\n"
+"\n"
+" Returns true if the evaluation of the Gradient norm Function is\n"
+" higher for inter1 than for inter2.\n"
+"\n"
+" :arg inter1: The first Interface1D object.\n"
+" :type inter1: :class:`Interface1D`\n"
+" :arg inter2: The second Interface1D object.\n"
+" :type inter2: :class:`Interface1D`\n"
+" :return: True or false.\n"
+" :rtype: bool\n";
+
+static int ViewMapGradientNormBP1D___init__( BPy_ViewMapGradientNormBP1D* self, PyObject *args )
+{
+ int i;
+ PyObject *obj;
+ float f = 2.0;
+
+ if(!( PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) ))
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_bp1D.bp1D = new Predicates1D::ViewMapGradientNormBP1D(i,t,f);
+ return 0;
+}
+
+/*-----------------------BPy_ViewMapGradientNormBP1D type definition ------------------------------*/
+
+PyTypeObject ViewMapGradientNormBP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewMapGradientNormBP1D", /* tp_name */
+ sizeof(BPy_ViewMapGradientNormBP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewMapGradientNormBP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &BinaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewMapGradientNormBP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
new file mode 100644
index 00000000000..23d27e118a9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H
+#define FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H
+
+#include "../BPy_BinaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewMapGradientNormBP1D_Type;
+
+#define BPy_ViewMapGradientNormBP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewMapGradientNormBP1D_Type) )
+
+/*---------------------------Python BPy_ViewMapGradientNormBP1D structure definition----------*/
+typedef struct {
+ BPy_BinaryPredicate1D py_bp1D;
+} BPy_ViewMapGradientNormBP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWMAPGRADIENTNORMBP1D_H */
diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp
new file mode 100644
index 00000000000..1948da2b6b0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Director.cpp
@@ -0,0 +1,304 @@
+#include "Director.h"
+
+#include "BPy_Convert.h"
+
+#include "BPy_BinaryPredicate0D.h"
+#include "BPy_BinaryPredicate1D.h"
+#include "BPy_FrsMaterial.h"
+#include "BPy_Id.h"
+#include "BPy_UnaryFunction0D.h"
+#include "BPy_UnaryFunction1D.h"
+#include "BPy_UnaryPredicate0D.h"
+#include "BPy_UnaryPredicate1D.h"
+#include "BPy_StrokeShader.h"
+#include "Iterator/BPy_ChainingIterator.h"
+#include "Iterator/BPy_Interface0DIterator.h"
+#include "Interface1D/BPy_Stroke.h"
+#include "Interface1D/BPy_ViewEdge.h"
+#include "BPy_ViewShape.h"
+
+#include "UnaryFunction0D/BPy_UnaryFunction0DDouble.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DFloat.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DId.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DMaterial.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec2f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVec3f.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h"
+#include "UnaryFunction0D/BPy_UnaryFunction0DViewShape.h"
+
+#include "UnaryFunction1D/BPy_UnaryFunction1DDouble.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DFloat.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec2f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h"
+#include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h"
+
+
+// BinaryPredicate0D: __call__
+int Director_BPy_BinaryPredicate0D___call__( BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2 ) {
+ if (!bp0D->py_bp0D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp0D) not initialized");
+ return -1;
+ }
+ PyObject *arg1 = Any_BPy_Interface0D_from_Interface0D(i1);
+ PyObject *arg2 = Any_BPy_Interface0D_from_Interface0D(i2);
+ if (!arg1 || !arg2) {
+ Py_XDECREF(arg1);
+ Py_XDECREF(arg2);
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod( bp0D->py_bp0D, "__call__", "OO", arg1, arg2 );
+ Py_DECREF(arg1);
+ Py_DECREF(arg2);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ bp0D->result = ret;
+ return 0;
+}
+
+
+// BinaryPredicate1D: __call__
+int Director_BPy_BinaryPredicate1D___call__( BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2 ) {
+ if (!bp1D->py_bp1D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_bp1D) not initialized");
+ return -1;
+ }
+ PyObject *arg1 = Any_BPy_Interface1D_from_Interface1D(i1);
+ PyObject *arg2 = Any_BPy_Interface1D_from_Interface1D(i2);
+ if (!arg1 || !arg2) {
+ Py_XDECREF(arg1);
+ Py_XDECREF(arg2);
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod( bp1D->py_bp1D, "__call__", "OO", arg1, arg2 );
+ Py_DECREF(arg1);
+ Py_DECREF(arg2);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ bp1D->result = ret;
+ return 0;
+}
+
+
+// UnaryPredicate0D: __call__
+int Director_BPy_UnaryPredicate0D___call__( UnaryPredicate0D *up0D, Interface0DIterator& if0D_it ) {
+ if (!up0D->py_up0D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up0D) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( up0D->py_up0D, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ up0D->result = ret;
+ return 0;
+}
+
+
+// UnaryPredicate1D: __call__
+int Director_BPy_UnaryPredicate1D___call__( UnaryPredicate1D *up1D, Interface1D& if1D ) {
+ if (!up1D->py_up1D) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_up1D) not initialized");
+ return -1;
+ }
+ PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( up1D->py_up1D, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ int ret = PyObject_IsTrue(result);
+ Py_DECREF(result);
+ if (ret < 0)
+ return -1;
+ up1D->result = ret;
+ return 0;
+}
+
+
+// StrokeShader: shade
+int Director_BPy_StrokeShader_shade( StrokeShader *ss, Stroke& s ) {
+ if (!ss->py_ss) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_ss) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Stroke_from_Stroke(s);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( ss->py_ss, "shade", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ Py_DECREF(result);
+ return 0;
+}
+
+// ChainingIterator: init, traverse
+int Director_BPy_ChainingIterator_init( ChainingIterator *c_it ) {
+ if (!c_it->py_c_it) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
+ return -1;
+ }
+ PyObject *result = PyObject_CallMethod( c_it->py_c_it, "init", "");
+ if (!result)
+ return -1;
+ Py_DECREF(result);
+ return 0;
+}
+
+int Director_BPy_ChainingIterator_traverse( ChainingIterator *c_it, AdjacencyIterator& a_it ) {
+ if (!c_it->py_c_it) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_c_it) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_AdjacencyIterator_from_AdjacencyIterator(a_it);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( c_it->py_c_it, "traverse", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+ if (BPy_ViewEdge_Check(result)) {
+ c_it->result = ((BPy_ViewEdge *) result)->ve;
+ } else if (result == Py_None) {
+ c_it->result = NULL;
+ } else {
+ PyErr_SetString(PyExc_RuntimeError, "traverse method returned a wrong value");
+ Py_DECREF(result);
+ return -1;
+ }
+ Py_DECREF(result);
+ return 0;
+}
+
+
+// BPy_UnaryFunction{0D,1D}: __call__
+int Director_BPy_UnaryFunction0D___call__( void *uf0D, PyObject *obj, Interface0DIterator& if0D_it) {
+
+ if (!obj) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf0D) not initialized");
+ return -1;
+ }
+ PyObject *arg = BPy_Interface0DIterator_from_Interface0DIterator(if0D_it, 0);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( obj, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+
+ if( BPy_UnaryFunction0DDouble_Check(obj) ) {
+ ((UnaryFunction0D<double> *) uf0D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction0DEdgeNature_Check(obj) ) {
+ ((UnaryFunction0D<Nature::EdgeNature> *) uf0D)->result = EdgeNature_from_BPy_Nature(result);
+
+ } else if ( BPy_UnaryFunction0DFloat_Check(obj) ) {
+ ((UnaryFunction0D<float> *) uf0D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction0DId_Check(obj) ) {
+ ((UnaryFunction0D<Id> *) uf0D)->result = *( ((BPy_Id *) result)->id );
+
+ } else if ( BPy_UnaryFunction0DMaterial_Check(obj) ) {
+ ((UnaryFunction0D<FrsMaterial> *) uf0D)->result = *( ((BPy_FrsMaterial *) result)->m );
+
+ } else if ( BPy_UnaryFunction0DUnsigned_Check(obj) ) {
+ ((UnaryFunction0D<unsigned> *) uf0D)->result = PyLong_AsLong(result);
+
+ } else if ( BPy_UnaryFunction0DVec2f_Check(obj) ) {
+ Vec2f *v = Vec2f_ptr_from_Vector( result );
+ ((UnaryFunction0D<Vec2f> *) uf0D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction0DVec3f_Check(obj) ) {
+ Vec3f *v = Vec3f_ptr_from_Vector( result );
+ ((UnaryFunction0D<Vec3f> *) uf0D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction0DVectorViewShape_Check(obj) ) {
+ vector<ViewShape*> vec;
+ for( int i = 0; i < PyList_Size(result); i++) {
+ ViewShape *b = ( (BPy_ViewShape *) PyList_GetItem(result, i) )->vs;
+ vec.push_back( b );
+ }
+
+ ((UnaryFunction0D< vector<ViewShape*> > *) uf0D)->result = vec;
+
+ } else if ( BPy_UnaryFunction0DViewShape_Check(obj) ) {
+ ((UnaryFunction0D<ViewShape*> *) uf0D)->result = ((BPy_ViewShape *) result)->vs;
+
+ }
+
+ Py_DECREF(result);
+ return 0;
+}
+
+int Director_BPy_UnaryFunction1D___call__( void *uf1D, PyObject *obj, Interface1D& if1D) {
+
+ if (!obj) { // internal error
+ PyErr_SetString(PyExc_RuntimeError, "Reference to Python object (py_uf1D) not initialized");
+ return -1;
+ }
+ PyObject *arg = Any_BPy_Interface1D_from_Interface1D(if1D);
+ if (!arg)
+ return -1;
+ PyObject *result = PyObject_CallMethod( obj, "__call__", "O", arg );
+ Py_DECREF(arg);
+ if (!result)
+ return -1;
+
+ if( BPy_UnaryFunction1DDouble_Check(obj) ) {
+ ((UnaryFunction1D<double> *) uf1D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction1DEdgeNature_Check(obj) ) {
+ ((UnaryFunction1D<Nature::EdgeNature> *) uf1D)->result = EdgeNature_from_BPy_Nature(result);
+
+ } else if ( BPy_UnaryFunction1DFloat_Check(obj) ) {
+ ((UnaryFunction1D<float> *) uf1D)->result = PyFloat_AsDouble(result);
+
+ } else if ( BPy_UnaryFunction1DUnsigned_Check(obj) ) {
+ ((UnaryFunction1D<unsigned> *) uf1D)->result = PyLong_AsLong(result);
+
+ } else if ( BPy_UnaryFunction1DVec2f_Check(obj) ) {
+ Vec2f *v = Vec2f_ptr_from_Vector( result );
+ ((UnaryFunction1D<Vec2f> *) uf1D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction1DVec3f_Check(obj) ) {
+ Vec3f *v = Vec3f_ptr_from_Vector( result );
+ ((UnaryFunction1D<Vec3f> *) uf1D)->result = *v;
+ delete v;
+
+ } else if ( BPy_UnaryFunction1DVectorViewShape_Check(obj) ) {
+ vector<ViewShape*> vec;
+ for( int i = 1; i < PyList_Size(result); i++) {
+ ViewShape *b = ( (BPy_ViewShape *) PyList_GetItem(result, i) )->vs;
+ vec.push_back( b );
+ }
+
+ ((UnaryFunction1D< vector<ViewShape*> > *) uf1D)->result = vec;
+
+ }
+
+ Py_DECREF(result);
+ return 0;
+}
diff --git a/source/blender/freestyle/intern/python/Director.h b/source/blender/freestyle/intern/python/Director.h
new file mode 100644
index 00000000000..667d4a65942
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Director.h
@@ -0,0 +1,49 @@
+#ifndef FREESTYLE_PYTHON_DIRECTOR
+# define FREESTYLE_PYTHON_DIRECTOR
+
+class UnaryPredicate0D;
+class UnaryPredicate1D;
+class BinaryPredicate0D;
+class BinaryPredicate1D;
+class ChainingIterator;
+class AdjacencyIterator;
+class Interface0D;
+class Interface1D;
+class Interface0DIterator;
+class Stroke;
+class StrokeShader;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+// BinaryPredicate0D: __call__
+int Director_BPy_BinaryPredicate0D___call__( BinaryPredicate0D *bp0D, Interface0D& i1, Interface0D& i2 );
+
+// BinaryPredicate1D: __call__
+int Director_BPy_BinaryPredicate1D___call__( BinaryPredicate1D *bp1D, Interface1D& i1, Interface1D& i2 );
+
+// UnaryFunction{0D,1D}: __call__
+int Director_BPy_UnaryFunction0D___call__( void *uf0D, PyObject *obj, Interface0DIterator& if0D_it);
+int Director_BPy_UnaryFunction1D___call__( void *uf1D, PyObject *obj, Interface1D& if1D);
+
+// UnaryPredicate0D: __call__
+int Director_BPy_UnaryPredicate0D___call__( UnaryPredicate0D *up0D, Interface0DIterator& if0D_it );
+
+// UnaryPredicate1D: __call__
+int Director_BPy_UnaryPredicate1D___call__( UnaryPredicate1D *up1D, Interface1D& if1D );
+
+// StrokeShader: shade
+int Director_BPy_StrokeShader_shade( StrokeShader *ss, Stroke& s );
+
+// ChainingIterator: init, traverse
+int Director_BPy_ChainingIterator_init( ChainingIterator *c_it );
+int Director_BPy_ChainingIterator_traverse( ChainingIterator *c_it, AdjacencyIterator& a_it );
+
+#endif // FREESTYLE_PYTHON_DIRECTOR
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
new file mode 100644
index 00000000000..35f8c82f794
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp
@@ -0,0 +1,289 @@
+#include "BPy_CurvePoint.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurvePoint___doc__[] =
+"Class to represent a point of a curve. A CurvePoint can be any point\n"
+"of a 1D curve (it doesn't have to be a vertex of the curve). Any\n"
+":class:`Interface1D` is built upon ViewEdges, themselves built upon\n"
+"FEdges. Therefore, a curve is basically a polyline made of a list of\n"
+":class:`SVertex` objects. Thus, a CurvePoint is built by linearly\n"
+"interpolating two :class:`SVertex` instances. CurvePoint can be used\n"
+"as virtual points while querying 0D information along a curve at a\n"
+"given resolution.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Defult constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A CurvePoint object.\n"
+" :type iBrother: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(iA, iB, t2d)\n"
+"\n"
+" Builds a CurvePoint from two SVertex and an interpolation parameter.\n"
+"\n"
+" :arg iA: The first SVertex.\n"
+" :type iA: :class:`SVertex`\n"
+" :arg iB: The second SVertex.\n"
+" :type iB: :class:`SVertex`\n"
+" :arg t2d: A 2D interpolation parameter used to linearly interpolate\n"
+" iA and iB.\n"
+" :type t2d: float\n"
+"\n"
+".. method:: __init__(iA, iB, t2d)\n"
+"\n"
+" Builds a CurvePoint from two CurvePoint and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg iA: The first CurvePoint.\n"
+" :type iA: :class:`CurvePoint`\n"
+" :arg iB: The second CurvePoint.\n"
+" :type iB: :class:`CurvePoint`\n"
+" :arg t2d: The 2D interpolation parameter used to linearly\n"
+" interpolate iA and iB.\n"
+" :type t2d: float\n";
+
+static int CurvePoint___init__(BPy_CurvePoint *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) )
+ return -1;
+
+ if( !obj1 ){
+ self->cp = new CurvePoint();
+
+ } else if( !obj2 && BPy_CurvePoint_Check(obj1) ) {
+ self->cp = new CurvePoint( *(((BPy_CurvePoint *) obj1)->cp) );
+
+ } else if( obj3 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->cp = new CurvePoint( ((BPy_SVertex *) obj1)->sv,
+ ((BPy_SVertex *) obj2)->sv,
+ PyFloat_AsDouble( obj3 ) );
+
+ } else if( obj3 && BPy_CurvePoint_Check(obj1) && BPy_CurvePoint_Check(obj2) ) {
+ CurvePoint *cp1 = ((BPy_CurvePoint *) obj1)->cp;
+ CurvePoint *cp2 = ((BPy_CurvePoint *) obj2)->cp;
+ if( !cp1 || cp1->A() == 0 || cp1->B() == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid CurvePoint object");
+ return -1;
+ }
+ if( !cp2 || cp2->A() == 0 || cp2->B() == 0 ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid CurvePoint object");
+ return -1;
+ }
+ self->cp = new CurvePoint( cp1, cp2, PyFloat_AsDouble( obj3 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if0D.if0D = self->cp;
+ self->py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static PyObject * CurvePoint___copy__( BPy_CurvePoint *self ) {
+ BPy_CurvePoint *py_cp;
+
+ py_cp = (BPy_CurvePoint *) CurvePoint_Type.tp_new( &CurvePoint_Type, 0, 0 );
+
+ py_cp->cp = new CurvePoint( *(self->cp) );
+ py_cp->py_if0D.if0D = py_cp->cp;
+ py_cp->py_if0D.borrowed = 0;
+
+ return (PyObject *) py_cp;
+}
+
+static char CurvePoint_A___doc__[] =
+".. method:: A()\n"
+"\n"
+" Returns the first SVertex upon which the CurvePoint is built.\n"
+"\n"
+" :return: The first SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * CurvePoint_A( BPy_CurvePoint *self ) {
+ SVertex *A = self->cp->A();
+ if( A )
+ return BPy_SVertex_from_SVertex( *A );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_B___doc__[] =
+".. method:: B()\n"
+"\n"
+" Returns the second SVertex upon which the CurvePoint is built.\n"
+"\n"
+" :return: The second SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * CurvePoint_B( BPy_CurvePoint *self ) {
+ SVertex *B = self->cp->B();
+ if( B )
+ return BPy_SVertex_from_SVertex( *B );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_t2d___doc__[] =
+".. method:: t2d()\n"
+"\n"
+" Returns the 2D interpolation parameter.\n"
+"\n"
+" :return: The 2D interpolation parameter.\n"
+" :rtype: float\n";
+
+static PyObject * CurvePoint_t2d( BPy_CurvePoint *self ) {
+ return PyFloat_FromDouble( self->cp->t2d() );
+}
+
+static char CurvePoint_setA___doc__[] =
+".. method:: setA(iA)\n"
+"\n"
+" Sets the first SVertex upon which to build the CurvePoint.\n"
+"\n"
+" :arg iA: The first SVertex.\n"
+" :type iA: :class:`SVertex`\n";
+
+static PyObject *CurvePoint_setA( BPy_CurvePoint *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->cp->setA( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_setB___doc__[] =
+".. method:: setB(iB)\n"
+"\n"
+" Sets the first SVertex upon which to build the CurvePoint.\n"
+"\n"
+" :arg iB: The second SVertex.\n"
+" :type iB: :class:`SVertex`\n";
+
+static PyObject *CurvePoint_setB( BPy_CurvePoint *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->cp->setB( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_setT2d___doc__[] =
+".. method:: setT2d(t)\n"
+"\n"
+" Sets the 2D interpolation parameter to use.\n"
+"\n"
+" :arg t: The 2D interpolation parameter.\n"
+" :type t: float\n";
+
+static PyObject *CurvePoint_setT2d( BPy_CurvePoint *self , PyObject *args) {
+ float t;
+
+ if(!( PyArg_ParseTuple(args, "f", &t) ))
+ return NULL;
+
+ self->cp->setT2d( t );
+
+ Py_RETURN_NONE;
+}
+
+static char CurvePoint_curvatureFredo___doc__[] =
+".. method:: curvatureFredo()\n"
+"\n"
+" Returns the angle in radians.\n"
+"\n"
+" :return: The angle in radians.\n"
+" :rtype: float\n";
+
+static PyObject *CurvePoint_curvatureFredo( BPy_CurvePoint *self , PyObject *args) {
+ return PyFloat_FromDouble( self->cp->curvatureFredo() );
+}
+
+///bool operator== (const CurvePoint &b)
+
+/*----------------------CurvePoint instance definitions ----------------------------*/
+static PyMethodDef BPy_CurvePoint_methods[] = {
+ {"__copy__", ( PyCFunction ) CurvePoint___copy__, METH_NOARGS, "() Cloning method."},
+ {"A", ( PyCFunction ) CurvePoint_A, METH_NOARGS, CurvePoint_A___doc__},
+ {"B", ( PyCFunction ) CurvePoint_B, METH_NOARGS, CurvePoint_B___doc__},
+ {"t2d", ( PyCFunction ) CurvePoint_t2d, METH_NOARGS, CurvePoint_t2d___doc__},
+ {"setA", ( PyCFunction ) CurvePoint_setA, METH_VARARGS, CurvePoint_setA___doc__},
+ {"setB", ( PyCFunction ) CurvePoint_setB, METH_VARARGS, CurvePoint_setB___doc__},
+ {"setT2d", ( PyCFunction ) CurvePoint_setT2d, METH_VARARGS, CurvePoint_setT2d___doc__},
+ {"curvatureFredo", ( PyCFunction ) CurvePoint_curvatureFredo, METH_NOARGS, CurvePoint_curvatureFredo___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_CurvePoint type definition ------------------------------*/
+PyTypeObject CurvePoint_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePoint", /* tp_name */
+ sizeof(BPy_CurvePoint), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurvePoint___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_CurvePoint_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePoint___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
new file mode 100644
index 00000000000..b4c22645503
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CURVEPOINT_H
+#define FREESTYLE_PYTHON_CURVEPOINT_H
+
+#include "../BPy_Interface0D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePoint_Type;
+
+#define BPy_CurvePoint_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePoint_Type) )
+
+/*---------------------------Python BPy_CurvePoint structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ CurvePoint *cp;
+} BPy_CurvePoint;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVEPOINT_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
new file mode 100644
index 00000000000..327f392e811
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp
@@ -0,0 +1,314 @@
+#include "BPy_SVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+static char SVertex___doc__[] =
+"Class to define a vertex of the embedding.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A SVertex object.\n"
+" :type iBrother: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(iPoint3D, id)\n"
+"\n"
+" Builds a SVertex from 3D coordinates and an Id.\n"
+"\n"
+" :arg iPoint3D: A three-dimensional vector.\n"
+" :type iPoint3D: :class:`mathutils.Vector`\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static int SVertex___init__(BPy_SVertex *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *py_point = 0;
+ BPy_Id *py_id = 0;
+
+
+ if (! PyArg_ParseTuple(args, "|OO!", &py_point, &Id_Type, &py_id) )
+ return -1;
+
+ if( !py_point ) {
+ self->sv = new SVertex();
+
+ } else if( !py_id && BPy_SVertex_Check(py_point) ) {
+ self->sv = new SVertex( *(((BPy_SVertex *)py_point)->sv) );
+
+ } else if( py_point && py_id ) {
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return -1;
+ }
+ self->sv = new SVertex( *v, *(py_id->id) );
+ delete v;
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if0D.if0D = self->sv;
+ self->py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static PyObject * SVertex___copy__( BPy_SVertex *self ) {
+ BPy_SVertex *py_svertex;
+
+ py_svertex = (BPy_SVertex *) SVertex_Type.tp_new( &SVertex_Type, 0, 0 );
+
+ py_svertex->sv = self->sv->duplicate();
+ py_svertex->py_if0D.if0D = py_svertex->sv;
+ py_svertex->py_if0D.borrowed = 0;
+
+ return (PyObject *) py_svertex;
+}
+
+static char SVertex_normals___doc__[] =
+".. method:: normals()\n"
+"\n"
+" Returns the normals for this Vertex as a list. In a smooth surface,\n"
+" a vertex has exactly one normal. In a sharp surface, a vertex can\n"
+" have any number of normals.\n"
+"\n"
+" :return: A list of normals.\n"
+" :rtype: List of :class:`mathutils.Vector` objects\n";
+
+static PyObject * SVertex_normals( BPy_SVertex *self ) {
+ PyObject *py_normals;
+ set< Vec3r > normals;
+
+ py_normals = PyList_New(0);
+ normals = self->sv->normals();
+
+ for( set< Vec3r >::iterator set_iterator = normals.begin(); set_iterator != normals.end(); set_iterator++ ) {
+ Vec3r v( *set_iterator );
+ PyList_Append( py_normals, Vector_from_Vec3r(v) );
+ }
+
+ return py_normals;
+}
+
+static char SVertex_normalsSize___doc__[] =
+".. method:: normalsSize()\n"
+"\n"
+" Returns the number of different normals for this vertex.\n"
+"\n"
+" :return: The number of normals.\n"
+" :rtype: int\n";
+
+static PyObject * SVertex_normalsSize( BPy_SVertex *self ) {
+ return PyLong_FromLong( self->sv->normalsSize() );
+}
+
+static char SVertex_viewvertex___doc__[] =
+".. method:: viewvertex()\n"
+"\n"
+" If this SVertex is also a ViewVertex, this method returns the\n"
+" ViewVertex. None is returned otherwise.\n"
+"\n"
+" :return: The ViewVertex object.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject * SVertex_viewvertex( BPy_SVertex *self ) {
+ ViewVertex *vv = self->sv->viewvertex();
+ if( vv )
+ return Any_BPy_ViewVertex_from_ViewVertex( *vv );
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_setPoint3D___doc__[] =
+".. method:: setPoint3D(p)\n"
+"\n"
+" Sets the 3D coordinates of the SVertex.\n"
+"\n"
+" :arg p: A three-dimensional vector.\n"
+" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject *SVertex_setPoint3D( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_point;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_point) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->setPoint3D( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_setPoint2D___doc__[] =
+".. method:: setPoint2D(p)\n"
+"\n"
+" Sets the 2D projected coordinates of the SVertex.\n"
+"\n"
+" :arg p: A three-dimensional vector.\n"
+" :type p: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject *SVertex_setPoint2D( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_point;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_point) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(py_point);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->setPoint2D( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_AddNormal___doc__[] =
+".. method:: AddNormal(n)\n"
+"\n"
+" Adds a normal to the SVertex's set of normals. If the same normal\n"
+" is already in the set, nothing changes.\n"
+"\n"
+" :arg n: A three-dimensional vector.\n"
+" :type n: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject *SVertex_AddNormal( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_normal;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_normal) ))
+ return NULL;
+ Vec3r *n = Vec3r_ptr_from_PyObject(py_normal);
+ if( !n ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->sv->AddNormal( *n );
+ delete n;
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the identifier of the SVertex.\n"
+"\n"
+" :arg id: The identifier.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject *SVertex_setId( BPy_SVertex *self , PyObject *args) {
+ BPy_Id *py_id;
+
+ if( !PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) )
+ return NULL;
+
+ self->sv->setId( *(py_id->id) );
+
+ Py_RETURN_NONE;
+}
+
+static char SVertex_AddFEdge___doc__[] =
+".. method:: AddFEdge(fe)\n"
+"\n"
+" Add an FEdge to the list of edges emanating from this SVertex.\n"
+"\n"
+" :arg fe: An FEdge.\n"
+" :type fe: :class:`FEdge`\n";
+
+static PyObject *SVertex_AddFEdge( BPy_SVertex *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->sv->AddFEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+// virtual bool operator== (const SVertex &iBrother)
+// ViewVertex * viewvertex ()
+
+/*----------------------SVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_SVertex_methods[] = {
+ {"__copy__", ( PyCFunction ) SVertex___copy__, METH_NOARGS, "() Cloning method."},
+ {"normals", ( PyCFunction ) SVertex_normals, METH_NOARGS, SVertex_normals___doc__},
+ {"normalsSize", ( PyCFunction ) SVertex_normalsSize, METH_NOARGS, SVertex_normalsSize___doc__},
+ {"viewvertex", ( PyCFunction ) SVertex_viewvertex, METH_NOARGS, SVertex_viewvertex___doc__},
+ {"setPoint3D", ( PyCFunction ) SVertex_setPoint3D, METH_VARARGS, SVertex_setPoint3D___doc__},
+ {"setPoint2D", ( PyCFunction ) SVertex_setPoint2D, METH_VARARGS, SVertex_setPoint2D___doc__},
+ {"AddNormal", ( PyCFunction ) SVertex_AddNormal, METH_VARARGS, SVertex_AddNormal___doc__},
+ {"setId", ( PyCFunction ) SVertex_setId, METH_VARARGS, SVertex_setId___doc__},
+ {"AddFEdge", ( PyCFunction ) SVertex_AddFEdge, METH_VARARGS, SVertex_AddFEdge___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_SVertex type definition ------------------------------*/
+PyTypeObject SVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertex", /* tp_name */
+ sizeof(BPy_SVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
new file mode 100644
index 00000000000..7d310f2b7dc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_SVERTEX_H
+#define FREESTYLE_PYTHON_SVERTEX_H
+
+#include "../../view_map/Silhouette.h"
+#include "../BPy_Interface0D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertex_Type;
+
+#define BPy_SVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertex_Type) )
+
+/*---------------------------Python BPy_SVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ SVertex *sv;
+} BPy_SVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
new file mode 100644
index 00000000000..9b81ce56400
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp
@@ -0,0 +1,193 @@
+#include "BPy_ViewVertex.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewVertex___doc__[] =
+"Class to define a view vertex. A view vertex is a feature vertex\n"
+"corresponding to a point of the image graph, where the characteristics\n"
+"of an edge (e.g., nature and visibility) might change. A\n"
+":class:`ViewVertex` can be of two kinds: A :class:`TVertex` when it\n"
+"corresponds to the intersection between two ViewEdges or a\n"
+":class:`NonTVertex` when it corresponds to a vertex of the initial\n"
+"input mesh (it is the case for vertices such as corners for example).\n"
+"Thus, this class can be specialized into two classes, the\n"
+":class:`TVertex` class and the :class:`NonTVertex` class.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewVertex object.\n"
+" :type iBrother: :class:`ViewVertex`\n";
+
+static int ViewVertex___init__( BPy_ViewVertex *self, PyObject *args, PyObject *kwds )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->vv = 0; // ViewVertex is abstract
+ self->py_if0D.if0D = self->vv;
+ self->py_if0D.borrowed = 0;
+ return 0;
+}
+
+static char ViewVertex_setNature___doc__[] =
+".. method:: setNature(iNature)\n"
+"\n"
+" Sets the nature of the vertex.\n"
+"\n"
+" :arg iNature: A Nature object.\n"
+" :type iNature: :class:`Nature`\n";
+
+static PyObject * ViewVertex_setNature( BPy_ViewVertex *self, PyObject *args ) {
+ PyObject *py_n;
+
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) ))
+ return NULL;
+
+ PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i );
+ ((ViewVertex *) self->py_if0D.if0D)->setNature( PyLong_AsLong(i) );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewVertex_edgesBegin___doc__[] =
+".. method:: edgesBegin()\n"
+"\n"
+" Returns an iterator over the ViewEdges that goes to or comes from\n"
+" this ViewVertex pointing to the first ViewEdge of the list. The\n"
+" orientedViewEdgeIterator allows to iterate in CCW order over these\n"
+" ViewEdges and to get the orientation for each ViewEdge\n"
+" (incoming/outgoing).\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing to the first ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`\n";
+
+static PyObject * ViewVertex_edgesBegin( BPy_ViewVertex *self ) {
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesBegin() );
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 0 );
+}
+
+static char ViewVertex_edgesEnd___doc__[] =
+".. method:: edgesEnd()\n"
+"\n"
+" Returns an orientedViewEdgeIterator over the ViewEdges around this\n"
+" ViewVertex, pointing after the last ViewEdge.\n"
+"\n"
+" :return: An orientedViewEdgeIterator pointing after the last ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`\n";
+
+static PyObject * ViewVertex_edgesEnd( BPy_ViewVertex *self ) {
+#if 0
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesEnd() );
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 1 );
+#else
+ PyErr_SetString(PyExc_NotImplementedError, "edgesEnd method currently disabled");
+ return NULL;
+#endif
+}
+
+static char ViewVertex_edgesIterator___doc__[] =
+".. method:: edgesIterator(iEdge)\n"
+"\n"
+" Returns an orientedViewEdgeIterator pointing to the ViewEdge given\n"
+" as argument.\n"
+"\n"
+" :arg iEdge: A ViewEdge object.\n"
+" :type iEdge: :class:`ViewEdge`\n"
+" :return: An orientedViewEdgeIterator pointing to the given ViewEdge.\n"
+" :rtype: :class:`orientedViewEdgeIterator`\n";
+
+static PyObject * ViewVertex_edgesIterator( BPy_ViewVertex *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if( !self->vv )
+ Py_RETURN_NONE;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) py_ve)->ve;
+ ViewVertexInternal::orientedViewEdgeIterator ove_it( self->vv->edgesIterator( ve ) );
+ return BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( ove_it, 0 );
+}
+
+/*----------------------ViewVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewVertex_methods[] = {
+ {"setNature", ( PyCFunction ) ViewVertex_setNature, METH_VARARGS, ViewVertex_setNature___doc__},
+ {"edgesBegin", ( PyCFunction ) ViewVertex_edgesBegin, METH_NOARGS, ViewVertex_edgesBegin___doc__},
+ {"edgesEnd", ( PyCFunction ) ViewVertex_edgesEnd, METH_NOARGS, ViewVertex_edgesEnd___doc__},
+ {"edgesIterator", ( PyCFunction ) ViewVertex_edgesIterator, METH_VARARGS, ViewVertex_edgesIterator___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewVertex type definition ------------------------------*/
+PyTypeObject ViewVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewVertex", /* tp_name */
+ sizeof(BPy_ViewVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
new file mode 100644
index 00000000000..26c06b50d71
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_VIEWVERTEX_H
+#define FREESTYLE_PYTHON_VIEWVERTEX_H
+
+#include "../../view_map/ViewMap.h"
+#include "../BPy_Interface0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewVertex_Type;
+
+#define BPy_ViewVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewVertex_Type) )
+
+/*---------------------------Python BPy_ViewVertex structure definition----------*/
+typedef struct {
+ BPy_Interface0D py_if0D;
+ ViewVertex *vv;
+} BPy_ViewVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
new file mode 100644
index 00000000000..d19069eae4b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp
@@ -0,0 +1,399 @@
+#include "BPy_StrokeVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../../BPy_StrokeAttribute.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeVertex___doc__[] =
+"Class to define a stroke vertex.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A StrokeVertex object.\n"
+" :type iBrother: :class:`StrokeVertex`\n"
+"\n"
+".. method:: __init__(iA, iB, t3)\n"
+"\n"
+" Builds a stroke vertex from 2 stroke vertices and an interpolation\n"
+" parameter.\n"
+"\n"
+" :arg iA: The first StrokeVertex.\n"
+" :type iA: :class:`StrokeVertex`\n"
+" :arg iB: The second StrokeVertex.\n"
+" :type iB: :class:`StrokeVertex`\n"
+" :arg t3: An interpolation parameter.\n"
+" :type t3: float\n"
+"\n"
+".. method:: __init__(iPoint)\n"
+"\n"
+" Builds a stroke vertex from a CurvePoint\n"
+"\n"
+" :arg iPoint: A CurvePoint object.\n"
+" :type iPoint: :class:`CurvePoint`\n"
+"\n"
+".. method:: __init__(iSVertex)\n"
+"\n"
+" Builds a stroke vertex from a SVertex\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n"
+"\n"
+".. method:: __init__(iSVertex, iAttribute)\n"
+"\n"
+" Builds a stroke vertex from an SVertex and a StrokeAttribute object.\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n"
+" :arg iAttribute: A StrokeAttribute object.\n"
+" :type iAttribute: :class:`StrokeAttribute`\n";
+
+static int StrokeVertex___init__(BPy_StrokeVertex *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO!", &obj1, &obj2, &PyFloat_Type, &obj3) )
+ return -1;
+
+ if( !obj1 ){
+ self->sv = new StrokeVertex();
+
+ } else if( !obj2 && BPy_StrokeVertex_Check(obj1) && ((BPy_StrokeVertex *) obj1)->sv ) {
+ self->sv = new StrokeVertex( *(((BPy_StrokeVertex *) obj1)->sv) );
+
+ } else if( !obj2 && BPy_CurvePoint_Check(obj1) && ((BPy_CurvePoint *) obj1)->cp ) {
+ self->sv = new StrokeVertex( ((BPy_CurvePoint *) obj1)->cp );
+
+ } else if( !obj2 && BPy_SVertex_Check(obj1) && ((BPy_SVertex *) obj1)->sv ) {
+ self->sv = new StrokeVertex( ((BPy_SVertex *) obj1)->sv );
+
+ } else if( obj3 && BPy_StrokeVertex_Check(obj1) && BPy_StrokeVertex_Check(obj2) ) {
+ StrokeVertex *sv1 = ((BPy_StrokeVertex *) obj1)->sv;
+ StrokeVertex *sv2 = ((BPy_StrokeVertex *) obj2)->sv;
+ if( !sv1 || ( sv1->A() == 0 && sv1->B() == 0 ) ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 is an invalid StrokeVertex object");
+ return -1;
+ }
+ if( !sv2 || ( sv2->A() == 0 && sv2->B() == 0 ) ) {
+ PyErr_SetString(PyExc_TypeError, "argument 2 is an invalid StrokeVertex object");
+ return -1;
+ }
+ self->sv = new StrokeVertex( sv1, sv2, PyFloat_AsDouble( obj3 ) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_cp.cp = self->sv;
+ self->py_cp.py_if0D.if0D = self->sv;
+ self->py_cp.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char StrokeVertex_x___doc__[] =
+".. method:: x()\n"
+"\n"
+" Returns the 2D point X coordinate.\n"
+"\n"
+" :return: The X coordinate.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_x( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->x() );
+}
+
+static char StrokeVertex_y___doc__[] =
+".. method:: y()\n"
+"\n"
+" Returns the 2D point Y coordinate.\n"
+"\n"
+" :return: The Y coordinate.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_y( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->y() );
+}
+
+static char StrokeVertex_getPoint___doc__[] =
+".. method:: getPoint()\n"
+"\n"
+" Returns the 2D point coordinates as a two-dimensional vector.\n"
+"\n"
+" :return: The 2D coordinates.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * StrokeVertex_getPoint( BPy_StrokeVertex *self ) {
+ Vec2f v( self->sv->getPoint() );
+ return Vector_from_Vec2f( v );
+}
+
+static char StrokeVertex_attribute___doc__[] =
+".. method:: attribute()\n"
+"\n"
+" Returns the StrokeAttribute for this StrokeVertex.\n"
+"\n"
+" :return: The StrokeAttribute object.\n"
+" :rtype: :class:`StrokeAttribute`\n";
+
+static PyObject * StrokeVertex_attribute( BPy_StrokeVertex *self ) {
+ return BPy_StrokeAttribute_from_StrokeAttribute( self->sv->attribute() );
+}
+
+static char StrokeVertex_curvilinearAbscissa___doc__[] =
+".. method:: curvilinearAbscissa()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_curvilinearAbscissa( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->curvilinearAbscissa() );
+}
+
+static char StrokeVertex_strokeLength___doc__[] =
+".. method:: strokeLength()\n"
+"\n"
+" Returns the length of the Stroke to which this StrokeVertex belongs\n"
+"\n"
+" :return: The stroke length.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_strokeLength( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->strokeLength() );
+}
+
+static char StrokeVertex_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the curvilinear abscissa of this StrokeVertex in the Stroke\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertex_u( BPy_StrokeVertex *self ) {
+ return PyFloat_FromDouble( self->sv->u() );
+}
+
+static char StrokeVertex_setX___doc__[] =
+".. method:: setX(x)\n"
+"\n"
+" Sets the 2D point X coordinate.\n"
+"\n"
+" :arg x: The X coordinate.\n"
+" :type x: float\n";
+
+static PyObject *StrokeVertex_setX( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setX( r );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setY___doc__[] =
+".. method:: setY(y)\n"
+"\n"
+" Sets the 2D point Y coordinate.\n"
+"\n"
+" :arg y: The Y coordinate.\n"
+" :type y: float\n";
+
+static PyObject *StrokeVertex_setY( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setY( r );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setPoint___doc__[] =
+".. method:: setPoint(x, y)\n"
+"\n"
+" Sets the 2D point X and Y coordinates.\n"
+"\n"
+" :arg x: The X coordinate.\n"
+" :type x: float\n"
+" :arg y: The Y coordinate.\n"
+" :type y: float\n"
+"\n"
+".. method:: SetPoint(p)\n"
+"\n"
+" Sets the 2D point X and Y coordinates.\n"
+"\n"
+" :arg p: A two-dimensional vector.\n"
+" :type p: :class:`mathutils.Vector`, list or tuple of 2 real numbers\n";
+
+static PyObject *StrokeVertex_setPoint( BPy_StrokeVertex *self , PyObject *args) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) ))
+ return NULL;
+
+ if( obj1 && !obj2 ){
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj1);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 2D vector (either a list of 2 elements or Vector)");
+ return NULL;
+ }
+ self->sv->setPoint( *v );
+ delete v;
+ } else if( PyFloat_Check(obj1) && obj2 && PyFloat_Check(obj2) ){
+ self->sv->setPoint( PyFloat_AsDouble(obj1), PyFloat_AsDouble(obj2) );
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid arguments");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setAttribute___doc__[] =
+".. method:: setAttribute(iAttribute)\n"
+"\n"
+" Sets the attribute.\n"
+"\n"
+" :arg iAttribute: A StrokeAttribute object.\n"
+" :type iAttribute: :class:`StrokeAttribute`\n";
+
+static PyObject *StrokeVertex_setAttribute( BPy_StrokeVertex *self , PyObject *args) {
+ PyObject *py_sa;
+
+ if(!( PyArg_ParseTuple(args, "O!", &StrokeAttribute_Type, &py_sa) ))
+ return NULL;
+
+ self->sv->setAttribute(*( ((BPy_StrokeAttribute *) py_sa)->sa ));
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setCurvilinearAbscissa___doc__[] =
+".. method:: setCurvilinearAbscissa(iAbscissa)\n"
+"\n"
+" Sets the curvilinear abscissa of this StrokeVertex in the Stroke\n"
+"\n"
+" :arg iAbscissa: The curvilinear abscissa.\n"
+" :type iAbscissa: float\n";
+
+static PyObject *StrokeVertex_setCurvilinearAbscissa( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setCurvilinearAbscissa( r );
+
+ Py_RETURN_NONE;
+}
+
+static char StrokeVertex_setStrokeLength___doc__[] =
+".. method:: setStrokeLength(iLength)\n"
+"\n"
+" Sets the stroke length (it is only a value retained by the\n"
+" StrokeVertex, and it won't change the real stroke length).\n"
+"\n"
+" :arg iLength: The stroke length.\n"
+" :type iLength: float\n";
+
+static PyObject *StrokeVertex_setStrokeLength( BPy_StrokeVertex *self , PyObject *args) {
+ double r;
+
+ if(!( PyArg_ParseTuple(args, "d", &r) ))
+ return NULL;
+
+ self->sv->setStrokeLength( r );
+
+ Py_RETURN_NONE;
+}
+
+// real operator[] (const int i) const
+// real & operator[] (const int i)
+
+/*----------------------StrokeVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeVertex_methods[] = {
+// {"__copy__", ( PyCFunction ) StrokeVertex___copy__, METH_NOARGS, "() Cloning method."},
+ {"x", ( PyCFunction ) StrokeVertex_x, METH_NOARGS, StrokeVertex_x___doc__},
+ {"y", ( PyCFunction ) StrokeVertex_y, METH_NOARGS, StrokeVertex_y___doc__},
+ {"getPoint", ( PyCFunction ) StrokeVertex_getPoint, METH_NOARGS, StrokeVertex_getPoint___doc__},
+ {"attribute", ( PyCFunction ) StrokeVertex_attribute, METH_NOARGS, StrokeVertex_attribute___doc__},
+ {"curvilinearAbscissa", ( PyCFunction ) StrokeVertex_curvilinearAbscissa, METH_NOARGS, StrokeVertex_curvilinearAbscissa___doc__},
+ {"strokeLength", ( PyCFunction ) StrokeVertex_strokeLength, METH_NOARGS, StrokeVertex_strokeLength___doc__},
+ {"u", ( PyCFunction ) StrokeVertex_u, METH_NOARGS, StrokeVertex_u___doc__},
+ {"setX", ( PyCFunction ) StrokeVertex_setX, METH_VARARGS, StrokeVertex_setX___doc__},
+ {"setY", ( PyCFunction ) StrokeVertex_setY, METH_VARARGS, StrokeVertex_setY___doc__},
+ {"setPoint", ( PyCFunction ) StrokeVertex_setPoint, METH_VARARGS, StrokeVertex_setPoint___doc__},
+ {"setAttribute", ( PyCFunction ) StrokeVertex_setAttribute, METH_VARARGS, StrokeVertex_setAttribute___doc__},
+ {"setCurvilinearAbscissa", ( PyCFunction ) StrokeVertex_setCurvilinearAbscissa, METH_VARARGS, StrokeVertex_setCurvilinearAbscissa___doc__},
+ {"setStrokeLength", ( PyCFunction ) StrokeVertex_setStrokeLength, METH_VARARGS, StrokeVertex_setStrokeLength___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeVertex type definition ------------------------------*/
+PyTypeObject StrokeVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertex", /* tp_name */
+ sizeof(BPy_StrokeVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_StrokeVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &CurvePoint_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
new file mode 100644
index 00000000000..2a84e2480f0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STROKEVERTEX_H
+#define FREESTYLE_PYTHON_STROKEVERTEX_H
+
+#include "../BPy_CurvePoint.h"
+#include "../../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertex_Type;
+
+#define BPy_StrokeVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertex_Type) )
+
+/*---------------------------Python BPy_StrokeVertex structure definition----------*/
+typedef struct {
+ BPy_CurvePoint py_cp;
+ StrokeVertex *sv;
+} BPy_StrokeVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
new file mode 100644
index 00000000000..c842be49136
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp
@@ -0,0 +1,152 @@
+#include "BPy_NonTVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char NonTVertex___doc__[] =
+"View vertex for corners, cusps, etc. associated to a single SVertex.\n"
+"Can be associated to 2 or more view edges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A NonTVertex object.\n"
+" :type iBrother: :class:`NonTVertex`\n"
+"\n"
+".. method:: __init__(iSVertex)\n"
+"\n"
+" Builds a NonTVertex from a SVertex.\n"
+"\n"
+" :arg iSVertex: An SVertex object.\n"
+" :type iSVertex: :class:`SVertex`\n";
+
+static int NonTVertex___init__(BPy_NonTVertex *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O!", &SVertex_Type, &obj) )
+ return -1;
+
+ if( !obj ){
+ self->ntv = new NonTVertex();
+
+ } else if( ((BPy_SVertex *) obj)->sv ) {
+ self->ntv = new NonTVertex( ((BPy_SVertex *) obj)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_vv.vv = self->ntv;
+ self->py_vv.py_if0D.if0D = self->ntv;
+ self->py_vv.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char NonTVertex_svertex___doc__[] =
+".. method:: svertex()\n"
+"\n"
+" Returns the SVertex on top of which this NonTVertex is built.\n"
+"\n"
+" :return: The SVertex on top of which this NonTVertex is built.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * NonTVertex_svertex( BPy_NonTVertex *self ) {
+ SVertex *v = self->ntv->svertex();
+ if( v ){
+ return BPy_SVertex_from_SVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char NonTVertex_setSVertex___doc__[] =
+".. method:: setSVertex(iSVertex)\n"
+"\n"
+" Sets the SVertex on top of which this NonTVertex is built.\n"
+"\n"
+" :arg iSVertex: The SVertex on top of which this NonTVertex is built.\n"
+" :type iSVertex: :class:`SVertex`\n";
+
+static PyObject * NonTVertex_setSVertex( BPy_NonTVertex *self, PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->ntv->setSVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------NonTVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_NonTVertex_methods[] = {
+// {"__copy__", ( PyCFunction ) NonTVertex___copy__, METH_NOARGS, "() Cloning method."},
+ {"svertex", ( PyCFunction ) NonTVertex_svertex, METH_NOARGS, NonTVertex_svertex___doc__},
+ {"setSVertex", ( PyCFunction ) NonTVertex_setSVertex, METH_VARARGS, NonTVertex_setSVertex___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_NonTVertex type definition ------------------------------*/
+PyTypeObject NonTVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "NonTVertex", /* tp_name */
+ sizeof(BPy_NonTVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ NonTVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_NonTVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)NonTVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
new file mode 100644
index 00000000000..071194d2d42
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_NONTVERTEX_H
+#define FREESTYLE_PYTHON_NONTVERTEX_H
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject NonTVertex_Type;
+
+#define BPy_NonTVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &NonTVertex_Type) )
+
+/*---------------------------Python BPy_NonTVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ NonTVertex *ntv;
+} BPy_NonTVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NONTVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
new file mode 100644
index 00000000000..f7e36e753b5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp
@@ -0,0 +1,248 @@
+#include "BPy_TVertex.h"
+
+#include "../../BPy_Convert.h"
+#include "../BPy_SVertex.h"
+#include "../../BPy_Id.h"
+#include "../../Interface1D/BPy_FEdge.h"
+#include "../../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TVertex___doc__[] =
+"Class to define a T vertex, i.e. an intersection between two edges.\n"
+"It points towards two SVertex and four ViewEdges. Among the\n"
+"ViewEdges, two are front and the other two are back. Basically a\n"
+"front edge hides part of a back edge. So, among the back edges, one\n"
+"is of invisibility N and the other of invisibility N+1.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A TVertex object.\n"
+" :type iBrother: :class:`TVertex`\n";
+
+static int TVertex___init__(BPy_TVertex *self, PyObject *args, PyObject *kwds)
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->tv = new TVertex();
+ self->py_vv.vv = self->tv;
+ self->py_vv.py_if0D.if0D = self->tv;
+ self->py_vv.py_if0D.borrowed = 0;
+
+ return 0;
+}
+
+static char TVertex_frontSVertex___doc__[] =
+".. method:: frontSVertex()\n"
+"\n"
+" Returns the SVertex that is closer to the viewpoint.\n"
+"\n"
+" :return: The SVertex that is closer to the viewpoint.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * TVertex_frontSVertex( BPy_TVertex *self ) {
+ SVertex *v = self->tv->frontSVertex();
+ if( v ){
+ return BPy_SVertex_from_SVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_backSVertex___doc__[] =
+".. method:: backSVertex()\n"
+"\n"
+" Returns the SVertex that is further away from the viewpoint.\n"
+"\n"
+" :return: The SVertex that is further away from the viewpoint.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * TVertex_backSVertex( BPy_TVertex *self ) {
+ SVertex *v = self->tv->backSVertex();
+ if( v ){
+ return BPy_SVertex_from_SVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_setFrontSVertex___doc__[] =
+".. method:: setFrontSVertex(iFrontSVertex)\n"
+"\n"
+" Sets the SVertex that is closer to the viewpoint.\n"
+"\n"
+" :arg iFrontSVertex: An SVertex object.\n"
+" :type iFrontSVertex: :class:`SVertex`\n";
+
+static PyObject * TVertex_setFrontSVertex( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->tv->setFrontSVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_setBackSVertex___doc__[] =
+".. method:: setBackSVertex(iBackSVertex)\n"
+"\n"
+" Sets the SVertex that is further away from the viewpoint.\n"
+"\n"
+" :arg iBackSVertex: An SVertex object.\n"
+" :type iBackSVertex: :class:`SVertex`\n";
+
+static PyObject * TVertex_setBackSVertex( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->tv->setBackSVertex( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_setId___doc__[] =
+".. method:: setId(iId)\n"
+"\n"
+" Sets the Id.\n"
+"\n"
+" :arg iId: An Id object.\n"
+" :type iId: :class:`Id`\n";
+
+static PyObject * TVertex_setId( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ if( ((BPy_Id *) py_id)->id )
+ self->tv->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_getSVertex___doc__[] =
+".. method:: getSVertex(iFEdge)\n"
+"\n"
+" Returns the SVertex (among the 2) belonging to the given FEdge.\n"
+"\n"
+" :arg iFEdge: An FEdge object.\n"
+" :type iFEdge: :class:`FEdge`\n"
+" :return: The SVertex belonging to the given FEdge.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * TVertex_getSVertex( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ SVertex *sv = self->tv->getSVertex( ((BPy_FEdge *) py_fe)->fe );
+ if( sv ){
+ return BPy_SVertex_from_SVertex( *sv );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char TVertex_mate___doc__[] =
+".. method:: mate(iEdgeA)\n"
+"\n"
+" Returns the mate edge of the ViewEdge given as argument. If the\n"
+" ViewEdge is frontEdgeA, frontEdgeB is returned. If the ViewEdge is\n"
+" frontEdgeB, frontEdgeA is returned. Same for back edges.\n"
+"\n"
+" :arg iEdgeA: A ViewEdge object.\n"
+" :type iEdgeA: :class:`ViewEdge`\n"
+" :return: The mate edge of the given ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * TVertex_mate( BPy_TVertex *self, PyObject *args) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ ViewEdge *ve = self->tv->mate( ((BPy_ViewEdge *) py_ve)->ve );
+ if( ve ){
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+ }
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------TVertex instance definitions ----------------------------*/
+static PyMethodDef BPy_TVertex_methods[] = {
+// {"__copy__", ( PyCFunction ) TVertex___copy__, METH_NOARGS, "() Cloning method."},
+ {"frontSVertex", ( PyCFunction ) TVertex_frontSVertex, METH_NOARGS, TVertex_frontSVertex___doc__},
+ {"backSVertex", ( PyCFunction ) TVertex_backSVertex, METH_NOARGS, TVertex_backSVertex___doc__},
+ {"setFrontSVertex", ( PyCFunction ) TVertex_setFrontSVertex, METH_VARARGS, TVertex_setFrontSVertex___doc__},
+ {"setBackSVertex", ( PyCFunction ) TVertex_setBackSVertex, METH_VARARGS, TVertex_setBackSVertex___doc__},
+ {"setId", ( PyCFunction ) TVertex_setId, METH_VARARGS, TVertex_setId___doc__},
+ {"getSVertex", ( PyCFunction ) TVertex_getSVertex, METH_VARARGS, TVertex_getSVertex___doc__},
+ {"mate", ( PyCFunction ) TVertex_mate, METH_VARARGS, TVertex_mate___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_TVertex type definition ------------------------------*/
+PyTypeObject TVertex_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TVertex", /* tp_name */
+ sizeof(BPy_TVertex), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TVertex___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_TVertex_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ViewVertex_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TVertex___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
new file mode 100644
index 00000000000..12fe5c0cb43
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TVERTEX_H
+#define FREESTYLE_PYTHON_TVERTEX_H
+
+#include "../BPy_ViewVertex.h"
+#include "../../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TVertex_Type;
+
+#define BPy_TVertex_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TVertex_Type) )
+
+/*---------------------------Python BPy_TVertex structure definition----------*/
+typedef struct {
+ BPy_ViewVertex py_vv;
+ TVertex *tv;
+} BPy_TVertex;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TVERTEX_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
new file mode 100644
index 00000000000..5e4f9257afb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp
@@ -0,0 +1,428 @@
+#include "BPy_FEdge.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FEdge___doc__[] =
+"Base Class for feature edges. This FEdge can represent a silhouette,\n"
+"a crease, a ridge/valley, a border or a suggestive contour. For\n"
+"silhouettes, the FEdge is oriented so that the visible face lies on\n"
+"the left of the edge. For borders, the FEdge is oriented so that the\n"
+"face lies on the left of the edge. An FEdge can represent an initial\n"
+"edge of the mesh or runs accross a face of the initial mesh depending\n"
+"on the smoothness or sharpness of the mesh. This class is specialized\n"
+"into a smooth and a sharp version since their properties slightly vary\n"
+"from one to the other.\n"
+"\n"
+".. method:: FEdge()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: FEdge(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An FEdge object.\n"
+" :type iBrother: :class:`FEdge`\n"
+"\n"
+".. method:: FEdge(vA, vB)\n"
+"\n"
+" Builds an FEdge going from vA to vB.\n"
+"\n"
+" :arg vA: The first SVertex.\n"
+" :type vA: :class:`SVertex`\n"
+" :arg vB: The second SVertex.\n"
+" :type vB: :class:`SVertex`\n";
+
+static int FEdge___init__(BPy_FEdge *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->fe = new FEdge();
+
+ } else if( !obj2 && BPy_FEdge_Check(obj1) ) {
+ self->fe = new FEdge(*( ((BPy_FEdge *) obj1)->fe ));
+
+ } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->fe = new FEdge( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if1D.if1D = self->fe;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+
+static PyObject * FEdge___copy__( BPy_FEdge *self ) {
+ BPy_FEdge *py_fe;
+
+ py_fe = (BPy_FEdge *) FEdge_Type.tp_new( &FEdge_Type, 0, 0 );
+
+ py_fe->fe = new FEdge( *(self->fe) );
+ py_fe->py_if1D.if1D = py_fe->fe;
+ py_fe->py_if1D.borrowed = 0;
+
+ return (PyObject *) py_fe;
+}
+
+static char FEdge_vertexA___doc__[] =
+".. method:: vertexA()\n"
+"\n"
+" Returns the first SVertex.\n"
+"\n"
+" :return: The first SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * FEdge_vertexA( BPy_FEdge *self ) {
+ SVertex *A = self->fe->vertexA();
+ if( A ){
+ return BPy_SVertex_from_SVertex( *A );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_vertexB___doc__[] =
+".. method:: vertexB()\n"
+"\n"
+" Returns the second SVertex.\n"
+"\n"
+" :return: The second SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * FEdge_vertexB( BPy_FEdge *self ) {
+ SVertex *B = self->fe->vertexB();
+ if( B ){
+ return BPy_SVertex_from_SVertex( *B );
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+static PyObject * FEdge___getitem__( BPy_FEdge *self, PyObject *args ) {
+ int i;
+
+ if(!( PyArg_ParseTuple(args, "i", &i) ))
+ return NULL;
+ if(!(i == 0 || i == 1)) {
+ PyErr_SetString(PyExc_IndexError, "index must be either 0 or 1");
+ return NULL;
+ }
+
+ SVertex *v = self->fe->operator[](i);
+ if( v )
+ return BPy_SVertex_from_SVertex( *v );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_nextEdge___doc__[] =
+".. method:: nextEdge()\n"
+"\n"
+" Returns the FEdge following this one in the ViewEdge. If this FEdge\n"
+" is the last of the ViewEdge, None is returned.\n"
+"\n"
+" :return: The edge following this one in the ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * FEdge_nextEdge( BPy_FEdge *self ) {
+ FEdge *fe = self->fe->nextEdge();
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_previousEdge___doc__[] =
+".. method:: previousEdge()\n"
+"\n"
+" Returns the FEdge preceding this one in the ViewEdge. If this FEdge\n"
+" is the first one of the ViewEdge, None is returned.\n"
+"\n"
+" :return: The edge preceding this one in the ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * FEdge_previousEdge( BPy_FEdge *self ) {
+ FEdge *fe = self->fe->previousEdge();
+ if( fe )
+ return Any_BPy_FEdge_from_FEdge( *fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_viewedge___doc__[] =
+".. method:: viewedge()\n"
+"\n"
+" Returns the ViewEdge to which this FEdge belongs to.\n"
+"\n"
+" :return: The ViewEdge to which this FEdge belongs to.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * FEdge_viewedge( BPy_FEdge *self ) {
+ ViewEdge *ve = self->fe->viewedge();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_isSmooth___doc__[] =
+".. method:: isSmooth()\n"
+"\n"
+" Returns true if this FEdge is a smooth FEdge.\n"
+"\n"
+" :return: True if this FEdge is a smooth FEdge.\n"
+" :rtype: bool\n";
+
+static PyObject * FEdge_isSmooth( BPy_FEdge *self ) {
+ return PyBool_from_bool( self->fe->isSmooth() );
+}
+
+static char FEdge_setVertexA___doc__[] =
+".. method:: setVertexA(vA)\n"
+"\n"
+" Sets the first SVertex.\n"
+"\n"
+" :arg vA: An SVertex object.\n"
+" :type vA: :class:`SVertex`\n";
+
+static PyObject *FEdge_setVertexA( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &SVertex_Type, &py_sv) ))
+ return NULL;
+
+ self->fe->setVertexA( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setVertexB___doc__[] =
+".. method:: setVertexB(vB)\n"
+"\n"
+" Sets the second SVertex.\n"
+"\n"
+" :arg vB: An SVertex object.\n"
+" :type vB: :class:`SVertex`\n";
+
+static PyObject *FEdge_setVertexB( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_sv) && BPy_SVertex_Check(py_sv) )) {
+ cout << "ERROR: FEdge_setVertexB" << endl;
+ Py_RETURN_NONE;
+ }
+
+ self->fe->setVertexB( ((BPy_SVertex *) py_sv)->sv );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the Id of this FEdge.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject *FEdge_setId( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ self->fe->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setNextEdge___doc__[] =
+".. method:: setNextEdge(iEdge)\n"
+"\n"
+" Sets the pointer to the next FEdge.\n"
+"\n"
+" :arg iEdge: An FEdge object.\n"
+" :type iEdge: :class:`FEdge`\n";
+
+static PyObject *FEdge_setNextEdge( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->fe->setNextEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setPreviousEdge___doc__[] =
+".. method:: setPreviousEdge(iEdge)\n"
+"\n"
+" Sets the pointer to the previous FEdge.\n"
+"\n"
+" :arg iEdge: An FEdge object.\n"
+" :type iEdge: :class:`FEdge`\n";
+
+static PyObject *FEdge_setPreviousEdge( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->fe->setPreviousEdge( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setNature___doc__[] =
+".. method:: setNature(iNature)\n"
+"\n"
+" Sets the nature of this FEdge.\n"
+"\n"
+" :arg iNature: A Nature object.\n"
+" :type iNature: :class:`Nature`\n";
+
+static PyObject * FEdge_setNature( BPy_FEdge *self, PyObject *args ) {
+ PyObject *py_n;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) ))
+ return NULL;
+
+ PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i );
+ self->fe->setNature( PyLong_AsLong(i) );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setViewEdge___doc__[] =
+".. method:: setViewEdge(iViewEdge)\n"
+"\n"
+" Sets the ViewEdge to which this FEdge belongs to.\n"
+"\n"
+" :arg iViewEdge: A ViewEdge object.\n"
+" :type iViewEdge: :class:`ViewEdge`\n";
+
+static PyObject * FEdge_setViewEdge( BPy_FEdge *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) py_ve)->ve;
+ self->fe->setViewEdge( ve );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdge_setSmooth___doc__[] =
+".. method:: setSmooth(iFlag)\n"
+"\n"
+" Sets the flag telling whether this FEdge is smooth or sharp. True\n"
+" for Smooth, false for Sharp.\n"
+"\n"
+" :arg iFlag: True for Smooth, false for Sharp.\n"
+" :type iFlag: bool\n";
+
+static PyObject *FEdge_setSmooth( BPy_FEdge *self , PyObject *args) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->fe->setSmooth( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FEdge instance definitions ----------------------------*/
+
+static PyMethodDef BPy_FEdge_methods[] = {
+ {"__copy__", ( PyCFunction ) FEdge___copy__, METH_NOARGS, "() Cloning method."},
+ {"vertexA", ( PyCFunction ) FEdge_vertexA, METH_NOARGS, FEdge_vertexA___doc__},
+ {"vertexB", ( PyCFunction ) FEdge_vertexB, METH_NOARGS, FEdge_vertexB___doc__},
+ {"__getitem__", ( PyCFunction ) FEdge___getitem__, METH_VARARGS, "(int i) Returns the first SVertex if i=0, the seccond SVertex if i=1."},
+ {"nextEdge", ( PyCFunction ) FEdge_nextEdge, METH_NOARGS, FEdge_nextEdge___doc__},
+ {"previousEdge", ( PyCFunction ) FEdge_previousEdge, METH_NOARGS, FEdge_previousEdge___doc__},
+ {"viewedge", ( PyCFunction ) FEdge_viewedge, METH_NOARGS, FEdge_viewedge___doc__},
+ {"isSmooth", ( PyCFunction ) FEdge_isSmooth, METH_NOARGS, FEdge_isSmooth___doc__},
+ {"setVertexA", ( PyCFunction ) FEdge_setVertexA, METH_VARARGS, FEdge_setVertexA___doc__},
+ {"setVertexB", ( PyCFunction ) FEdge_setVertexB, METH_VARARGS, FEdge_setVertexB___doc__},
+ {"setId", ( PyCFunction ) FEdge_setId, METH_VARARGS, FEdge_setId___doc__},
+ {"setNextEdge", ( PyCFunction ) FEdge_setNextEdge, METH_VARARGS, FEdge_setNextEdge___doc__},
+ {"setPreviousEdge", ( PyCFunction ) FEdge_setPreviousEdge, METH_VARARGS, FEdge_setPreviousEdge___doc__},
+ {"setSmooth", ( PyCFunction ) FEdge_setSmooth, METH_VARARGS, FEdge_setSmooth___doc__},
+ {"setViewEdge", ( PyCFunction ) FEdge_setViewEdge, METH_VARARGS, FEdge_setViewEdge___doc__},
+ {"setNature", ( PyCFunction ) FEdge_setNature, METH_VARARGS, FEdge_setNature___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FEdge type definition ------------------------------*/
+
+PyTypeObject FEdge_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdge", /* tp_name */
+ sizeof(BPy_FEdge), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FEdge___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FEdge_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdge___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
new file mode 100644
index 00000000000..9d13145aaf2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FEDGE_H
+#define FREESTYLE_PYTHON_FEDGE_H
+
+#include "../BPy_Interface1D.h"
+#include "../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdge_Type;
+
+#define BPy_FEdge_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdge_Type) )
+
+/*---------------------------Python BPy_FEdge structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ FEdge *fe;
+} BPy_FEdge;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FEDGE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
new file mode 100644
index 00000000000..1ec9e3efc53
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp
@@ -0,0 +1,200 @@
+#include "BPy_FrsCurve.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_CurvePoint.h"
+#include "../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FrsCurve___doc__[] =
+"Base class for curves made of CurvePoints. :class:`SVertex` is the\n"
+"type of the initial curve vertices. A :class:`Chain` is a\n"
+"specialization of a Curve.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default Constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy Constructor.\n"
+"\n"
+" :arg iBrother: A FrsCurve object.\n"
+" :type iBrother: :class:`FrsCurve`\n"
+"\n"
+".. method:: __init__(iId)\n"
+"\n"
+" Builds a FrsCurve from its Id.\n"
+"\n"
+" :arg iId: An Id object.\n"
+" :type iId: :class:`Id`\n";
+
+static int FrsCurve___init__(BPy_FrsCurve *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->c = new Curve();
+
+ } else if( BPy_FrsCurve_Check(obj) ) {
+ self->c = new Curve(*( ((BPy_FrsCurve *) obj)->c ));
+
+ } else if( BPy_Id_Check(obj) ) {
+ self->c = new Curve(*( ((BPy_Id *) obj)->id ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_if1D.if1D = self->c;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FrsCurve_push_vertex_back___doc__[] =
+".. method:: push_vertex_back(iVertex)\n"
+"\n"
+" Adds a single vertex at the end of the FrsCurve.\n"
+"\n"
+" :arg iVertex: A vertex object.\n"
+" :type iVertex: :class:`SVertex` or :class:`CurvePoint`\n";
+
+static PyObject * FrsCurve_push_vertex_back( BPy_FrsCurve *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ if( BPy_CurvePoint_Check(obj) ) {
+ self->c->push_vertex_back( ((BPy_CurvePoint *) obj)->cp );
+ } else if( BPy_SVertex_Check(obj) ) {
+ self->c->push_vertex_back( ((BPy_SVertex *) obj)->sv );
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char FrsCurve_push_vertex_front___doc__[] =
+".. method:: push_vertex_front(iVertex)\n"
+"\n"
+" Adds a single vertex at the front of the FrsCurve.\n"
+"\n"
+" :arg iVertex: A vertex object.\n"
+" :type iVertex: :class:`SVertex` or :class:`CurvePoint`\n";
+
+static PyObject * FrsCurve_push_vertex_front( BPy_FrsCurve *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ if( BPy_CurvePoint_Check(obj) ) {
+ self->c->push_vertex_front( ((BPy_CurvePoint *) obj)->cp );
+ } else if( BPy_SVertex_Check(obj) ) {
+ self->c->push_vertex_front( ((BPy_SVertex *) obj)->sv );
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char FrsCurve_empty___doc__[] =
+".. method:: empty()\n"
+"\n"
+" Returns true if the FrsCurve doesn't have any Vertex yet.\n"
+"\n"
+" :return: True if the FrsCurve has no vertices.\n"
+" :rtype: bool\n";
+
+static PyObject * FrsCurve_empty( BPy_FrsCurve *self ) {
+ return PyBool_from_bool( self->c->empty() );
+}
+
+static char FrsCurve_nSegments___doc__[] =
+".. method:: nSegments()\n"
+"\n"
+" Returns the number of segments in the polyline constituing the\n"
+" FrsCurve.\n"
+"\n"
+" :return: The number of segments.\n"
+" :rtype: int\n";
+
+static PyObject * FrsCurve_nSegments( BPy_FrsCurve *self ) {
+ return PyLong_FromLong( self->c->nSegments() );
+}
+
+/*----------------------FrsCurve instance definitions ----------------------------*/
+static PyMethodDef BPy_FrsCurve_methods[] = {
+ {"push_vertex_back", ( PyCFunction ) FrsCurve_push_vertex_back, METH_VARARGS, FrsCurve_push_vertex_back___doc__},
+ {"push_vertex_front", ( PyCFunction ) FrsCurve_push_vertex_front, METH_VARARGS, FrsCurve_push_vertex_front___doc__},
+ {"empty", ( PyCFunction ) FrsCurve_empty, METH_NOARGS, FrsCurve_empty___doc__},
+ {"nSegments", ( PyCFunction ) FrsCurve_nSegments, METH_NOARGS, FrsCurve_nSegments___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FrsCurve type definition ------------------------------*/
+
+PyTypeObject FrsCurve_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FrsCurve", /* tp_name */
+ sizeof(BPy_FrsCurve), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FrsCurve___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FrsCurve_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FrsCurve___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
new file mode 100644
index 00000000000..0829cf0ebf5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FRSCURVE_H
+#define FREESTYLE_PYTHON_FRSCURVE_H
+
+#include "../BPy_Interface1D.h"
+#include "../../stroke/Curve.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FrsCurve_Type;
+
+#define BPy_FrsCurve_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FrsCurve_Type) )
+
+/*---------------------------Python BPy_FrsCurve structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ Curve *c;
+} BPy_FrsCurve;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FRSCURVE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
new file mode 100644
index 00000000000..4edcc52fabf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp
@@ -0,0 +1,490 @@
+#include "BPy_Stroke.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface0D/CurvePoint/BPy_StrokeVertex.h"
+#include "../Iterator/BPy_StrokeVertexIterator.h"
+#include "../BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+// Stroke ()
+// template<class InputVertexIterator> Stroke (InputVertexIterator iBegin, InputVertexIterator iEnd)
+//
+// pb: - need to be able to switch representation: InputVertexIterator <=> position
+// - is it even used ? not even in SWIG version
+
+static char Stroke___doc__[] =
+"Class to define a stroke. A stroke is made of a set of 2D vertices\n"
+"(:class:`StrokeVertex`), regularly spaced out. This set of vertices\n"
+"defines the stroke's backbone geometry. Each of these stroke vertices\n"
+"defines the stroke's shape and appearance at this vertex position.\n"
+"\n"
+".. method:: Stroke()\n"
+"\n"
+" Default constructor\n"
+"\n"
+".. method:: Stroke(iBrother)\n"
+"\n"
+" Copy constructor\n"
+"\n"
+" :arg iBrother: \n"
+" :type iBrother: :class:`Stroke`\n"
+"\n"
+".. method:: Stroke(iBegin, iEnd)\n"
+"\n"
+" Builds a stroke from a set of StrokeVertex. This constructor is\n"
+" templated by an iterator type. This iterator type must allow the\n"
+" vertices parsing using the ++ operator.\n"
+"\n"
+" :arg iBegin: The iterator pointing to the first vertex.\n"
+" :type iBegin: InputVertexIterator\n"
+" :arg iEnd: The iterator pointing to the end of the vertex list.\n"
+" :type iEnd: InputVertexIterator\n";
+
+static int Stroke___init__(BPy_Stroke *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = NULL, *obj2 = NULL;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->s = new Stroke();
+
+ } else if ( !obj2 && BPy_Stroke_Check(obj1) ) {
+ self->s = new Stroke(*( ((BPy_Stroke *)obj1)->s ));
+
+ } else if ( obj2 ) {
+ PyErr_SetString(PyExc_TypeError,
+ "Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd) not implemented");
+ return -1;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_if1D.if1D = self->s;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static PyObject * Stroke___iter__( PyObject *self ) {
+ StrokeInternal::StrokeVertexIterator sv_it( ((BPy_Stroke *)self)->s->strokeVerticesBegin() );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 );
+}
+
+static Py_ssize_t Stroke_length( BPy_Stroke *self ) {
+ return self->s->strokeVerticesSize();
+}
+
+static PyObject * Stroke_item( BPy_Stroke *self, Py_ssize_t i ) {
+ if (i < 0 || i >= (Py_ssize_t)self->s->strokeVerticesSize()) {
+ PyErr_SetString(PyExc_IndexError, "subscript index out of range");
+ return NULL;
+ }
+ return BPy_StrokeVertex_from_StrokeVertex( self->s->strokeVerticeAt(i) );
+}
+
+static PyObject * Stroke___getitem__( BPy_Stroke *self, PyObject *item ) {
+ long i;
+
+ if (!PyLong_Check(item)) {
+ PyErr_SetString(PyExc_TypeError, "subscript indices must be integers");
+ return NULL;
+ }
+ i = PyLong_AsLong(item);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ if (i < 0) {
+ i += self->s->strokeVerticesSize();
+ }
+ return Stroke_item(self, i);
+}
+
+static char Stroke_ComputeSampling___doc__[] =
+".. method:: ComputeSampling(iNVertices)\n"
+"\n"
+" Compute the sampling needed to get iNVertices vertices. If the\n"
+" specified number of vertices is less than the actual number of\n"
+" vertices, the actual sampling value is returned. (To remove Vertices,\n"
+" use the RemoveVertex() method of this class.)\n"
+"\n"
+" :arg iNVertices: The number of stroke vertices we eventually want\n"
+" in our Stroke.\n"
+" :type iNVertices: int\n"
+" :return: The sampling that must be used in the Resample(float)\n"
+" method.\n"
+" :rtype: float\n";
+
+static PyObject * Stroke_ComputeSampling( BPy_Stroke *self, PyObject *args ) {
+ int i;
+
+ if(!( PyArg_ParseTuple(args, "i", &i) ))
+ return NULL;
+
+ return PyFloat_FromDouble( self->s->ComputeSampling( i ) );
+}
+
+static char Stroke_Resample___doc__[] =
+".. method:: Resample(iNPoints)\n"
+"\n"
+" Resamples the stroke so that it eventually has iNPoints. That means\n"
+" it is going to add iNPoints-vertices_size, if vertices_size is the\n"
+" number of points we already have. If vertices_size >= iNPoints, no\n"
+" resampling is done.\n"
+"\n"
+" :arg iNPoints: The number of vertices we eventually want in our stroke.\n"
+" :type iNPoints: int\n"
+"\n"
+".. method:: Resample(iSampling)\n"
+"\n"
+" Resamples the stroke with a given sampling. If the sampling is\n"
+" smaller than the actual sampling value, no resampling is done.\n"
+"\n"
+" :arg iSampling: The new sampling value.\n"
+" :type iSampling: float\n";
+
+static PyObject * Stroke_Resample( BPy_Stroke *self, PyObject *args ) {
+ PyObject *obj;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+
+ if( PyLong_Check(obj) )
+ self->s->Resample( (int) PyLong_AsLong(obj) );
+ else if( PyFloat_Check(obj) )
+ self->s->Resample( (float) PyFloat_AsDouble(obj) );
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_InsertVertex___doc__[] =
+".. method:: InsertVertex(iVertex, next)\n"
+"\n"
+" Inserts the stroke vertex iVertex in the stroke before next. The\n"
+" length, curvilinear abscissa are updated consequently.\n"
+"\n"
+" :arg iVertex: The StrokeVertex to insert in the Stroke.\n"
+" :type iVertex: :class:`StrokeVertex`\n"
+" :arg next: A StrokeVertexIterator pointing to the StrokeVertex\n"
+" before which iVertex must be inserted.\n"
+" :type next: :class:`StrokeVertexIterator`\n";
+
+static PyObject * Stroke_InsertVertex( BPy_Stroke *self, PyObject *args ) {
+ PyObject *py_sv = 0, *py_sv_it = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!O!", &StrokeVertex_Type, &py_sv, &StrokeVertexIterator_Type, &py_sv_it) ))
+ return NULL;
+
+ StrokeVertex *sv = ((BPy_StrokeVertex *) py_sv)->sv;
+ StrokeInternal::StrokeVertexIterator sv_it(*( ((BPy_StrokeVertexIterator *) py_sv_it)->sv_it ));
+ self->s->InsertVertex( sv, sv_it );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_RemoveVertex___doc__[] =
+".. method:: RemoveVertex(iVertex)\n"
+"\n"
+" Removes the stroke vertex iVertex from the stroke. The length and\n"
+" curvilinear abscissa are updated consequently.\n"
+"\n"
+" :arg iVertex: \n"
+" :type iVertex: :class:`StrokeVertex`\n";
+
+static PyObject * Stroke_RemoveVertex( BPy_Stroke *self, PyObject *args ) {
+ PyObject *py_sv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &StrokeVertex_Type, &py_sv) ))
+ return NULL;
+
+ if( ((BPy_StrokeVertex *) py_sv)->sv )
+ self->s->RemoveVertex( ((BPy_StrokeVertex *) py_sv)->sv );
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_getMediumType___doc__[] =
+".. method:: getMediumType()\n"
+"\n"
+" Returns the MediumType used for this Stroke.\n"
+"\n"
+" :return: the MediumType used for this Stroke.\n"
+" :rtype: :class:`MediumType`\n";
+
+static PyObject * Stroke_getMediumType( BPy_Stroke *self ) {
+ return BPy_MediumType_from_MediumType( self->s->getMediumType() );
+}
+
+static char Stroke_getTextureId___doc__[] =
+".. method:: getTextureId()\n"
+"\n"
+" Returns the ID of the texture used to simulate th marks system for\n"
+" this Stroke\n"
+"\n"
+" :return: The texture ID.\n"
+" :rtype: int\n";
+
+static PyObject * Stroke_getTextureId( BPy_Stroke *self ) {
+ return PyLong_FromLong( self->s->getTextureId() );
+}
+
+static char Stroke_hasTips___doc__[] =
+".. method:: hasTips()\n"
+"\n"
+" Returns true if this Stroke uses a texture with tips, false\n"
+" otherwise.\n"
+"\n"
+" :return: True if this Stroke uses a texture with tips.\n"
+" :rtype: bool\n";
+
+static PyObject * Stroke_hasTips( BPy_Stroke *self ) {
+ return PyBool_from_bool( self->s->hasTips() );
+}
+
+static char Stroke_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the Id of the Stroke.\n"
+"\n"
+" :arg id: the Id of the Stroke.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject *Stroke_setId( BPy_Stroke *self , PyObject *args) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ self->s->setId(*( ((BPy_Id *) py_id)->id ));
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setLength___doc__[] =
+".. method:: setLength(iLength)\n"
+"\n"
+" Sets the 2D length of the Stroke.\n"
+"\n"
+" :arg iLength: The 2D length of the Stroke.\n"
+" :type iLength: float\n";
+
+static PyObject *Stroke_setLength( BPy_Stroke *self , PyObject *args) {
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return NULL;
+
+ self->s->setLength( f );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setMediumType___doc__[] =
+".. method:: setMediumType(iType)\n"
+"\n"
+" Sets the medium type that must be used for this Stroke.\n"
+"\n"
+" :arg iType: A MediumType object.\n"
+" :type iType: :class:`MediumType`\n";
+
+static PyObject *Stroke_setMediumType( BPy_Stroke *self , PyObject *args) {
+ PyObject *py_mt;
+
+ if(!( PyArg_ParseTuple(args, "O!", &MediumType_Type, &py_mt) ))
+ return NULL;
+
+ self->s->setMediumType( MediumType_from_BPy_MediumType(py_mt) );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setTextureId___doc__[] =
+".. method:: setTextureId(iId)\n"
+"\n"
+" Sets the texture ID to be used to simulate the marks system for this\n"
+" Stroke.\n"
+"\n"
+" :arg iId: A texture ID.\n"
+" :type iId: int\n";
+
+static PyObject *Stroke_setTextureId( BPy_Stroke *self , PyObject *args) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->s->setTextureId( i );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_setTips___doc__[] =
+".. method:: setTips(iTips)\n"
+"\n"
+" Sets the flag telling whether this stroke is using a texture with\n"
+" tips or not.\n"
+"\n"
+" :arg iTips: True if this stroke uses a texture with tips.\n"
+" :type iTips: bool\n";
+
+static PyObject *Stroke_setTips( BPy_Stroke *self , PyObject *args) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->s->setTips( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+static char Stroke_strokeVerticesBegin___doc__[] =
+".. method:: strokeVerticesBegin(t=0.0)\n"
+"\n"
+" Returns a StrokeVertexIterator pointing on the first StrokeVertex of\n"
+" the Stroke. O ne can specify a sampling value to resample the Stroke\n"
+" on the fly if needed.\n"
+"\n"
+" :arg t: The resampling value with which we want our Stroke to be\n"
+" resampled. If 0 is specified, no resampling is done.\n"
+" :type t: float\n"
+" :return: A StrokeVertexIterator pointing on the first StrokeVertex.\n"
+" :rtype: :class:`StrokeVertexIterator`\n";
+
+static PyObject * Stroke_strokeVerticesBegin( BPy_Stroke *self , PyObject *args) {
+ float f = 0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return NULL;
+
+ StrokeInternal::StrokeVertexIterator sv_it( self->s->strokeVerticesBegin(f) );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 0 );
+}
+
+static char Stroke_strokeVerticesEnd___doc__[] =
+".. method:: strokeVerticesEnd()\n"
+"\n"
+" Returns a StrokeVertexIterator pointing after the last StrokeVertex\n"
+" of the Stroke.\n"
+"\n"
+" :return: A StrokeVertexIterator pointing after the last StrokeVertex.\n"
+" :rtype: :class:`StrokeVertexIterator`\n";
+
+static PyObject * Stroke_strokeVerticesEnd( BPy_Stroke *self ) {
+ StrokeInternal::StrokeVertexIterator sv_it( self->s->strokeVerticesEnd() );
+ return BPy_StrokeVertexIterator_from_StrokeVertexIterator( sv_it, 1 );
+}
+
+static char Stroke_strokeVerticesSize___doc__[] =
+".. method:: strokeVerticesSize()\n"
+"\n"
+" Returns the number of StrokeVertex constituing the Stroke.\n"
+"\n"
+" :return: The number of stroke vertices.\n"
+" :rtype: int\n";
+
+static PyObject * Stroke_strokeVerticesSize( BPy_Stroke *self ) {
+ return PyLong_FromLong( self->s->strokeVerticesSize() );
+}
+
+/*----------------------Stroke instance definitions ----------------------------*/
+
+static PyMethodDef BPy_Stroke_methods[] = {
+ {"__getitem__", ( PyCFunction ) Stroke___getitem__, METH_O, "(int i) Returns the i-th StrokeVertex constituting the Stroke."},
+ {"ComputeSampling", ( PyCFunction ) Stroke_ComputeSampling, METH_VARARGS, Stroke_ComputeSampling___doc__},
+ {"Resample", ( PyCFunction ) Stroke_Resample, METH_VARARGS, Stroke_Resample___doc__},
+ {"RemoveVertex", ( PyCFunction ) Stroke_RemoveVertex, METH_VARARGS, Stroke_RemoveVertex___doc__},
+ {"InsertVertex", ( PyCFunction ) Stroke_InsertVertex, METH_VARARGS, Stroke_InsertVertex___doc__},
+ {"getMediumType", ( PyCFunction ) Stroke_getMediumType, METH_NOARGS, Stroke_getMediumType___doc__},
+ {"getTextureId", ( PyCFunction ) Stroke_getTextureId, METH_NOARGS, Stroke_getTextureId___doc__},
+ {"hasTips", ( PyCFunction ) Stroke_hasTips, METH_NOARGS, Stroke_hasTips___doc__},
+ {"setId", ( PyCFunction ) Stroke_setId, METH_VARARGS, Stroke_setId___doc__},
+ {"setLength", ( PyCFunction ) Stroke_setLength, METH_VARARGS, Stroke_setLength___doc__},
+ {"setMediumType", ( PyCFunction ) Stroke_setMediumType, METH_VARARGS, Stroke_setMediumType___doc__},
+ {"setTextureId", ( PyCFunction ) Stroke_setTextureId, METH_VARARGS, Stroke_setTextureId___doc__},
+ {"setTips", ( PyCFunction ) Stroke_setTips, METH_VARARGS, Stroke_setTips___doc__},
+ {"strokeVerticesBegin", ( PyCFunction ) Stroke_strokeVerticesBegin, METH_VARARGS, Stroke_strokeVerticesBegin___doc__},
+ {"strokeVerticesEnd", ( PyCFunction ) Stroke_strokeVerticesEnd, METH_NOARGS, Stroke_strokeVerticesEnd___doc__},
+ {"strokeVerticesSize", ( PyCFunction ) Stroke_strokeVerticesSize, METH_NOARGS, Stroke_strokeVerticesSize___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Stroke type definition ------------------------------*/
+
+static PySequenceMethods Stroke_as_sequence = {
+ (lenfunc)Stroke_length, /* sq_length */
+ NULL, /* sq_concat */
+ NULL, /* sq_repeat */
+ (ssizeargfunc)Stroke_item, /* sq_item */
+ NULL, /* sq_slice */
+ NULL, /* sq_ass_item */
+ NULL, /* sq_ass_slice */
+ NULL, /* sq_contains */
+ NULL, /* sq_inplace_concat */
+ NULL, /* sq_inplace_repeat */
+};
+
+PyTypeObject Stroke_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Stroke", /* tp_name */
+ sizeof(BPy_Stroke), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ &Stroke_as_sequence, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Stroke___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ (getiterfunc)Stroke___iter__, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Stroke_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Stroke___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
new file mode 100644
index 00000000000..52c6d214b85
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STROKE_H
+#define FREESTYLE_PYTHON_STROKE_H
+
+#include "../BPy_Interface1D.h"
+#include "../../stroke/Stroke.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Stroke_Type;
+
+#define BPy_Stroke_Check(v) (( (PyObject *) v)->ob_type == &Stroke_Type)
+
+/*---------------------------Python BPy_Stroke structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ Stroke *s;
+} BPy_Stroke;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
new file mode 100644
index 00000000000..49ef52f87aa
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp
@@ -0,0 +1,461 @@
+#include "BPy_ViewEdge.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Id.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+#include "../Interface1D/BPy_FEdge.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_Nature.h"
+#include "../BPy_ViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewEdge___doc__[] =
+"Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n"
+"it connnects two :class:`ViewVertex` objects. It is made by connecting\n"
+"a set of FEdges.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A ViewEdge object.\n"
+" :type iBrother: :class:`ViewEdge`\n";
+
+static int ViewEdge___init__(BPy_ViewEdge *self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->ve = new ViewEdge();
+ self->py_if1D.if1D = self->ve;
+ self->py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char ViewEdge_A___doc__[] =
+".. method:: A()\n"
+"\n"
+" Returns the first ViewVertex.\n"
+"\n"
+" :return: The first ViewVertex.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject * ViewEdge_A( BPy_ViewEdge *self ) {
+ ViewVertex *v = self->ve->A();
+ if( v ){
+ return Any_BPy_ViewVertex_from_ViewVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_B___doc__[] =
+".. method:: B()\n"
+"\n"
+" Returns the second ViewVertex.\n"
+"\n"
+" :return: The second ViewVertex.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject * ViewEdge_B( BPy_ViewEdge *self ) {
+ ViewVertex *v = self->ve->B();
+ if( v ){
+ return Any_BPy_ViewVertex_from_ViewVertex( *v );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_fedgeA___doc__[] =
+".. method:: fedgeA()\n"
+"\n"
+" Returns the first FEdge that constitutes this ViewEdge.\n"
+"\n"
+" :return: The first FEdge constituting this ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_fedgeA( BPy_ViewEdge *self ) {
+ FEdge *A = self->ve->fedgeA();
+ if( A ){
+ return Any_BPy_FEdge_from_FEdge( *A );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_fedgeB___doc__[] =
+".. method:: fedgeB()\n"
+"\n"
+" Returns the last FEdge that constitutes this ViewEdge.\n"
+"\n"
+" :return: The last FEdge constituting this ViewEdge.\n"
+" :rtype: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_fedgeB( BPy_ViewEdge *self ) {
+ FEdge *B = self->ve->fedgeB();
+ if( B ){
+ return Any_BPy_FEdge_from_FEdge( *B );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_viewShape___doc__[] =
+".. method:: viewShape()\n"
+"\n"
+" Returns the ViewShape to which this ViewEdge belongs to.\n"
+"\n"
+" :return: The ViewShape to which this ViewEdge belongs to.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_viewShape( BPy_ViewEdge *self ) {
+ ViewShape *vs = self->ve->viewShape();
+ if( vs ){
+ return BPy_ViewShape_from_ViewShape( *vs );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_aShape___doc__[] =
+".. method:: aShape()\n"
+"\n"
+" Returns the shape that is occluded by the ViewShape to which this\n"
+" ViewEdge belongs to. If no object is occluded, None is returned.\n"
+"\n"
+" :return: The occluded ViewShape.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_aShape( BPy_ViewEdge *self ) {
+ ViewShape *vs = self->ve->aShape();
+ if( vs ){
+ return BPy_ViewShape_from_ViewShape( *vs );
+ }
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_isClosed___doc__[] =
+".. method:: isClosed()\n"
+"\n"
+" Tells whether this ViewEdge forms a closed loop or not.\n"
+"\n"
+" :return: True if this ViewEdge forms a closed loop.\n"
+" :rtype: bool\n";
+
+static PyObject * ViewEdge_isClosed( BPy_ViewEdge *self ) {
+ return PyBool_from_bool( self->ve->isClosed() );
+}
+
+static char ViewEdge_getChainingTimeStamp___doc__[] =
+".. method:: getChainingTimeStamp()\n"
+"\n"
+" Returns the time stamp of this ViewEdge.\n"
+"\n"
+" :return: The time stamp.\n"
+" :rtype: int\n";
+
+static PyObject * ViewEdge_getChainingTimeStamp( BPy_ViewEdge *self ) {
+ return PyLong_FromLong( self->ve->getChainingTimeStamp() );
+}
+
+static char ViewEdge_setChainingTimeStamp___doc__[] =
+".. method:: setChainingTimeStamp(ts)\n"
+"\n"
+" Sets the time stamp value.\n"
+"\n"
+" :arg ts: The time stamp.\n"
+" :type ts: int\n";
+
+static PyObject * ViewEdge_setChainingTimeStamp( BPy_ViewEdge *self, PyObject *args) {
+ int timestamp = 0 ;
+
+ if( !PyArg_ParseTuple(args, "i", &timestamp) )
+ return NULL;
+
+ self->ve->setChainingTimeStamp( timestamp );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setA___doc__[] =
+".. method:: setA(iA)\n"
+"\n"
+" Sets the first ViewVertex of the ViewEdge.\n"
+"\n"
+" :arg iA: The first ViewVertex of the ViewEdge.\n"
+" :type iA: :class:`ViewVertex`\n";
+
+static PyObject *ViewEdge_setA( BPy_ViewEdge *self , PyObject *args) {
+ PyObject *py_vv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) ))
+ return NULL;
+
+ self->ve->setA( ((BPy_ViewVertex *) py_vv)->vv );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setB___doc__[] =
+".. method:: setB(iB)\n"
+"\n"
+" Sets the last ViewVertex of the ViewEdge.\n"
+"\n"
+" :arg iB: The last ViewVertex of the ViewEdge.\n"
+" :type iB: :class:`ViewVertex`\n";
+
+static PyObject *ViewEdge_setB( BPy_ViewEdge *self , PyObject *args) {
+ PyObject *py_vv;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewVertex_Type, &py_vv) ))
+ return NULL;
+
+ self->ve->setB( ((BPy_ViewVertex *) py_vv)->vv );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setNature___doc__[] =
+".. method:: setNature(iNature)\n"
+"\n"
+" Sets the nature of the ViewEdge.\n"
+"\n"
+" :arg iNature: The nature of the ViewEdge.\n"
+" :type iNature: :class:`Nature`\n";
+
+static PyObject * ViewEdge_setNature( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_n;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Nature_Type, &py_n) ))
+ return NULL;
+
+ PyObject *i = (PyObject *) &( ((BPy_Nature *) py_n)->i );
+ self->ve->setNature( PyLong_AsLong(i) );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setFEdgeA___doc__[] =
+".. method:: setFEdgeA(iFEdge)\n"
+"\n"
+" Sets the first FEdge of the ViewEdge.\n"
+"\n"
+" :arg iFEdge: The first FEdge of the ViewEdge.\n"
+" :type iFEdge: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_setFEdgeA( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->ve->setFEdgeA( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setFEdgeB___doc__[] =
+".. method:: setFEdgeB(iFEdge)\n"
+"\n"
+" Sets the last FEdge of the ViewEdge.\n"
+"\n"
+" :arg iFEdge: The last FEdge of the ViewEdge.\n"
+" :type iFEdge: :class:`FEdge`\n";
+
+static PyObject * ViewEdge_setFEdgeB( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_fe;
+
+ if(!( PyArg_ParseTuple(args, "O!", &FEdge_Type, &py_fe) ))
+ return NULL;
+
+ self->ve->setFEdgeB( ((BPy_FEdge *) py_fe)->fe );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setShape___doc__[] =
+".. method:: setShape(iVShape)\n"
+"\n"
+" Sets the ViewShape to which this ViewEdge belongs to.\n"
+"\n"
+" :arg iVShape: The ViewShape to which this ViewEdge belongs to.\n"
+" :type iVShape: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_setShape( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_vs;
+
+ if(!( PyArg_ParseTuple(args, "O", &ViewShape_Type, &py_vs) ))
+ return NULL;
+
+ self->ve->setShape( ((BPy_ViewShape *) py_vs)->vs );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setId___doc__[] =
+".. method:: setId(id)\n"
+"\n"
+" Sets the ViewEdge id.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+static PyObject * ViewEdge_setId( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_id;
+
+ if(!( PyArg_ParseTuple(args, "O!", &Id_Type, &py_id) ))
+ return NULL;
+
+ Id id(*( ((BPy_Id *) py_id)->id ));
+ self->ve->setId( id );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_UpdateFEdges___doc__[] =
+".. method:: UpdateFEdges()\n"
+"\n"
+" Sets Viewedge to this for all embedded fedges.\n";
+
+static PyObject * ViewEdge_UpdateFEdges( BPy_ViewEdge *self ) {
+ self->ve->UpdateFEdges();
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setaShape___doc__[] =
+".. method:: setaShape(iShape)\n"
+"\n"
+" Sets the occluded ViewShape.\n"
+"\n"
+" :arg iShape: A ViewShape object.\n"
+" :type iShape: :class:`ViewShape`\n";
+
+static PyObject * ViewEdge_setaShape( BPy_ViewEdge *self, PyObject *args ) {
+ PyObject *py_vs;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewShape_Type, &py_vs) ))
+ return NULL;
+
+ ViewShape *vs = ((BPy_ViewShape *) py_vs)->vs;
+ self->ve->setaShape( vs );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_setQI___doc__[] =
+".. method:: setQI(qi)\n"
+"\n"
+" Sets the quantitative invisibility value of the ViewEdge.\n"
+"\n"
+" :arg qi: The quantitative invisibility.\n"
+" :type qi: int\n";
+
+static PyObject * ViewEdge_setQI( BPy_ViewEdge *self, PyObject *args ) {
+ int qi;
+
+ if(!( PyArg_ParseTuple(args, "i", &qi) ))
+ return NULL;
+
+ self->ve->setQI( qi );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdge_qi___doc__[] =
+".. method:: getChainingTimeStamp()\n"
+"\n"
+" Returns the quantitative invisibility value of the ViewEdge.\n"
+"\n"
+" :return: The quantitative invisibility.\n"
+" :rtype: int\n";
+
+static PyObject * ViewEdge_qi( BPy_ViewEdge *self ) {
+ return PyLong_FromLong( self->ve->qi() );
+}
+
+/*----------------------ViewEdge instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewEdge_methods[] = {
+ {"A", ( PyCFunction ) ViewEdge_A, METH_NOARGS, ViewEdge_A___doc__},
+ {"B", ( PyCFunction ) ViewEdge_B, METH_NOARGS, ViewEdge_B___doc__},
+ {"fedgeA", ( PyCFunction ) ViewEdge_fedgeA, METH_NOARGS, ViewEdge_fedgeA___doc__},
+ {"fedgeB", ( PyCFunction ) ViewEdge_fedgeB, METH_NOARGS, ViewEdge_fedgeB___doc__},
+ {"viewShape", ( PyCFunction ) ViewEdge_viewShape, METH_NOARGS, ViewEdge_viewShape___doc__},
+ {"aShape", ( PyCFunction ) ViewEdge_aShape, METH_NOARGS, ViewEdge_aShape___doc__},
+ {"isClosed", ( PyCFunction ) ViewEdge_isClosed, METH_NOARGS, ViewEdge_isClosed___doc__},
+ {"getChainingTimeStamp", ( PyCFunction ) ViewEdge_getChainingTimeStamp, METH_NOARGS, ViewEdge_getChainingTimeStamp___doc__},
+ {"setChainingTimeStamp", ( PyCFunction ) ViewEdge_setChainingTimeStamp, METH_VARARGS, ViewEdge_setChainingTimeStamp___doc__},
+ {"setA", ( PyCFunction ) ViewEdge_setA, METH_VARARGS, ViewEdge_setA___doc__},
+ {"setB", ( PyCFunction ) ViewEdge_setB, METH_VARARGS, ViewEdge_setB___doc__},
+ {"setNature", ( PyCFunction ) ViewEdge_setNature, METH_VARARGS, ViewEdge_setNature___doc__},
+ {"setFEdgeA", ( PyCFunction ) ViewEdge_setFEdgeA, METH_VARARGS, ViewEdge_setFEdgeA___doc__},
+ {"setFEdgeB", ( PyCFunction ) ViewEdge_setFEdgeB, METH_VARARGS, ViewEdge_setFEdgeB___doc__},
+ {"setShape", ( PyCFunction ) ViewEdge_setShape, METH_VARARGS, ViewEdge_setShape___doc__},
+ {"setId", ( PyCFunction ) ViewEdge_setId, METH_VARARGS, ViewEdge_setId___doc__},
+ {"UpdateFEdges", ( PyCFunction ) ViewEdge_UpdateFEdges, METH_NOARGS, ViewEdge_UpdateFEdges___doc__},
+ {"setaShape", ( PyCFunction ) ViewEdge_setaShape, METH_VARARGS, ViewEdge_setaShape___doc__},
+ {"setQI", ( PyCFunction ) ViewEdge_setQI, METH_VARARGS, ViewEdge_setQI___doc__},
+ {"qi", ( PyCFunction ) ViewEdge_qi, METH_NOARGS, ViewEdge_qi___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewEdge type definition ------------------------------*/
+
+PyTypeObject ViewEdge_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewEdge", /* tp_name */
+ sizeof(BPy_ViewEdge), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewEdge___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewEdge_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Interface1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewEdge___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
new file mode 100644
index 00000000000..ead377377e8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_VIEWEDGE_H
+#define FREESTYLE_PYTHON_VIEWEDGE_H
+
+#include "../../view_map/ViewMap.h"
+
+#include "../BPy_Interface1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewEdge_Type;
+
+#define BPy_ViewEdge_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewEdge_Type) )
+
+/*---------------------------Python BPy_ViewEdge structure definition----------*/
+typedef struct {
+ BPy_Interface1D py_if1D;
+ ViewEdge *ve;
+} BPy_ViewEdge;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWEDGE_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
new file mode 100644
index 00000000000..7958a35b851
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp
@@ -0,0 +1,169 @@
+#include "BPy_Chain.h"
+
+#include "../../BPy_Convert.h"
+#include "../../BPy_Id.h"
+#include "../BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Chain___doc__[] =
+"Class to represent a 1D elements issued from the chaining process. A\n"
+"Chain is the last step before the :class:`Stroke` and is used in the\n"
+"Splitting and Creation processes.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Defult constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: A Chain object.\n"
+" :type iBrother: :class:`Chain`\n"
+"\n"
+".. method:: __init__(id)\n"
+"\n"
+" Builds a chain from its Id.\n"
+"\n"
+" :arg id: An Id object.\n"
+" :type id: :class:`Id`\n";
+
+int Chain___init__(BPy_Chain *self, PyObject *args, PyObject *kwds)
+{
+
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->c = new Chain();
+
+ } else if( BPy_Chain_Check(obj) ) {
+ self->c = new Chain(*( ((BPy_Chain *) obj)->c ));
+
+ } else if( BPy_Id_Check(obj) ) {
+ self->c = new Chain(*( ((BPy_Id *) obj)->id ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_c.c = self->c;
+ self->py_c.py_if1D.if1D = self->c;
+ self->py_c.py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char Chain_push_viewedge_back___doc__[] =
+".. method:: push_viewedge_back(iViewEdge, orientation)\n"
+"\n"
+" Adds a ViewEdge at the end of the Chain.\n"
+"\n"
+" :arg iViewEdge: The ViewEdge that must be added.\n"
+" :type iViewEdge: :class:`ViewEdge`\n"
+" :arg orientation: The orientation with which the ViewEdge must be\n"
+" processed.\n"
+" :type orientation: bool\n";
+
+PyObject * Chain_push_viewedge_back( BPy_Chain *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!O", &ViewEdge_Type, &obj1, &obj2) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) obj1)->ve;
+ bool orientation = bool_from_PyBool( obj2 );
+ self->c->push_viewedge_back( ve, orientation);
+
+ Py_RETURN_NONE;
+}
+
+static char Chain_push_viewedge_front___doc__[] =
+".. method:: push_viewedge_front(iViewEdge, orientation)\n"
+"\n"
+" Adds a ViewEdge at the beginning of the Chain.\n"
+"\n"
+" :arg iViewEdge: The ViewEdge that must be added.\n"
+" :type iViewEdge: :class:`ViewEdge`\n"
+" :arg orientation: The orientation with which the ViewEdge must be\n"
+" processed.\n"
+" :type orientation: bool\n";
+
+PyObject * Chain_push_viewedge_front( BPy_Chain *self, PyObject *args ) {
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if(!( PyArg_ParseTuple(args, "O!O", &ViewEdge_Type, &obj1, &obj2) ))
+ return NULL;
+
+ ViewEdge *ve = ((BPy_ViewEdge *) obj1)->ve;
+ bool orientation = bool_from_PyBool( obj2 );
+ self->c->push_viewedge_front(ve, orientation);
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------Chain instance definitions ----------------------------*/
+static PyMethodDef BPy_Chain_methods[] = {
+ {"push_viewedge_back", ( PyCFunction ) Chain_push_viewedge_back, METH_VARARGS, Chain_push_viewedge_back___doc__},
+ {"push_viewedge_front", ( PyCFunction ) Chain_push_viewedge_front, METH_VARARGS, Chain_push_viewedge_front___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Chain type definition ------------------------------*/
+
+PyTypeObject Chain_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Chain", /* tp_name */
+ sizeof(BPy_Chain), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Chain___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_Chain_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FrsCurve_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Chain___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
new file mode 100644
index 00000000000..19f325ef513
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CHAIN_H
+#define FREESTYLE_PYTHON_CHAIN_H
+
+#include "../BPy_FrsCurve.h"
+#include "../../../stroke/Chain.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Chain_Type;
+
+#define BPy_Chain_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Chain_Type) )
+
+/*---------------------------Python BPy_Chain structure definition----------*/
+typedef struct {
+ BPy_FrsCurve py_c;
+ Chain *c;
+} BPy_Chain;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAIN_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
new file mode 100644
index 00000000000..f98b6f49940
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp
@@ -0,0 +1,303 @@
+#include "BPy_FEdgeSharp.h"
+
+#include "../../BPy_Convert.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FEdgeSharp___doc__[] =
+"Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial\n"
+"edge of the input mesh. It can be a silhouette, a crease or a border.\n"
+"If it is a crease edge, then it is borded by two faces of the mesh.\n"
+"Face a lies on its right whereas Face b lies on its left. If it is a\n"
+"border edge, then it doesn't have any face on its right, and thus Face\n"
+"a is None.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An FEdgeSharp object.\n"
+" :type iBrother: :class:`FEdgeSharp`\n"
+"\n"
+".. method:: __init__(vA, vB)\n"
+"\n"
+" Builds an FEdgeSharp going from vA to vB.\n"
+"\n"
+" :arg vA: The first SVertex object.\n"
+" :type vA: :class:`SVertex`\n"
+" :arg vB: The second SVertex object.\n"
+" :type vB: :class:`SVertex`\n";
+
+static int FEdgeSharp___init__(BPy_FEdgeSharp *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->fes = new FEdgeSharp();
+
+ } else if( !obj2 && BPy_FEdgeSharp_Check(obj1) ) {
+ self->fes = new FEdgeSharp(*( ((BPy_FEdgeSharp *) obj1)->fes ));
+
+ } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->fes = new FEdgeSharp( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_fe.fe = self->fes;
+ self->py_fe.py_if1D.if1D = self->fes;
+ self->py_fe.py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FEdgeSharp_normalA___doc__[] =
+".. method:: normalA()\n"
+"\n"
+" Returns the normal to the face lying on the right of the FEdge. If\n"
+" this FEdge is a border, it has no Face on its right and therefore, no\n"
+" normal.\n"
+"\n"
+" :return: The normal to the face lying on the right of the FEdge.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * FEdgeSharp_normalA( BPy_FEdgeSharp *self ) {
+ Vec3r v( self->fes->normalA() );
+ return Vector_from_Vec3r( v );
+}
+
+static char FEdgeSharp_normalB___doc__[] =
+".. method:: normalB()\n"
+"\n"
+" Returns the normal to the face lying on the left of the FEdge.\n"
+"\n"
+" :return: The normal to the face lying on the left of the FEdge.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * FEdgeSharp_normalB( BPy_FEdgeSharp *self ) {
+ Vec3r v( self->fes->normalB() );
+ return Vector_from_Vec3r( v );
+}
+
+static char FEdgeSharp_aMaterialIndex___doc__[] =
+".. method:: aMaterialIndex()\n"
+"\n"
+" Returns the index of the material of the face lying on the right of\n"
+" the FEdge. If this FEdge is a border, it has no Face on its right and\n"
+" therefore, no material.\n"
+"\n"
+" :return: The index of the material of the face lying on the right of\n"
+" the FEdge.\n"
+" :rtype: int\n";
+
+static PyObject * FEdgeSharp_aMaterialIndex( BPy_FEdgeSharp *self ) {
+ return PyLong_FromLong( self->fes->aFrsMaterialIndex() );
+}
+
+static char FEdgeSharp_bMaterialIndex___doc__[] =
+".. method:: bMaterialIndex()\n"
+"\n"
+" Returns the index of the material of the face lying on the left of\n"
+" the FEdge.\n"
+"\n"
+" :return: The index of the material of the face lying on the left of\n"
+" the FEdge.\n"
+" :rtype: int\n";
+
+static PyObject * FEdgeSharp_bMaterialIndex( BPy_FEdgeSharp *self ) {
+ return PyLong_FromLong( self->fes->bFrsMaterialIndex() );
+}
+
+static char FEdgeSharp_aMaterial___doc__[] =
+".. method:: aMaterial()\n"
+"\n"
+" Returns the material of the face lying on the right of the FEdge. If\n"
+" this FEdge is a border, it has no Face on its right and therefore, no\n"
+" material.\n"
+"\n"
+" :return: The material of the face lying on the right of the FEdge.\n"
+" :rtype: :class:`Material`\n";
+
+static PyObject * FEdgeSharp_aMaterial( BPy_FEdgeSharp *self ) {
+ FrsMaterial m( self->fes->aFrsMaterial() );
+ return BPy_FrsMaterial_from_FrsMaterial(m);
+}
+
+static char FEdgeSharp_bMaterial___doc__[] =
+".. method:: bMaterial()\n"
+"\n"
+" Returns the material of the face lying on the left of the FEdge.\n"
+"\n"
+" :return: The material of the face lying on the left of the FEdge.\n"
+" :rtype: :class:`Material`\n";
+
+static PyObject * FEdgeSharp_bMaterial( BPy_FEdgeSharp *self ) {
+ FrsMaterial m( self->fes->aFrsMaterial() );
+ return BPy_FrsMaterial_from_FrsMaterial(m);
+}
+
+static char FEdgeSharp_setNormalA___doc__[] =
+".. method:: setNormalA(iNormal)\n"
+"\n"
+" Sets the normal to the face lying on the right of the FEdge.\n"
+"\n"
+" :arg iNormal: A three-dimensional vector.\n"
+" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * FEdgeSharp_setNormalA( BPy_FEdgeSharp *self, PyObject *args ) {
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->fes->setNormalA( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setNormalB___doc__[] =
+".. method:: setNormalB(iNormal)\n"
+"\n"
+" Sets the normal to the face lying on the left of the FEdge.\n"
+"\n"
+" :arg iNormal: A three-dimensional vector.\n"
+" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * FEdgeSharp_setNormalB( BPy_FEdgeSharp *self, PyObject *args ) {
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->fes->setNormalB( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setaMaterialIndex___doc__[] =
+".. method:: setaMaterialIndex(i)\n"
+"\n"
+" Sets the index of the material lying on the right of the FEdge.\n"
+"\n"
+" :arg i: A material index.\n"
+" :type i: int\n";
+
+static PyObject * FEdgeSharp_setaMaterialIndex( BPy_FEdgeSharp *self, PyObject *args ) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->fes->setaFrsMaterialIndex( i );
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSharp_setbMaterialIndex___doc__[] =
+".. method:: setbMaterialIndex(i)\n"
+"\n"
+" Sets the index of the material lying on the left of the FEdge.\n"
+"\n"
+" :arg i: A material index.\n"
+" :type i: int\n";
+
+static PyObject * FEdgeSharp_setbMaterialIndex( BPy_FEdgeSharp *self, PyObject *args ) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->fes->setbFrsMaterialIndex( i );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FEdgeSharp instance definitions ----------------------------*/
+static PyMethodDef BPy_FEdgeSharp_methods[] = {
+ {"normalA", ( PyCFunction ) FEdgeSharp_normalA, METH_NOARGS, FEdgeSharp_normalA___doc__},
+ {"normalB", ( PyCFunction ) FEdgeSharp_normalB, METH_NOARGS, FEdgeSharp_normalB___doc__},
+ {"aMaterialIndex", ( PyCFunction ) FEdgeSharp_aMaterialIndex, METH_NOARGS, FEdgeSharp_aMaterialIndex___doc__},
+ {"bMaterialIndex", ( PyCFunction ) FEdgeSharp_bMaterialIndex, METH_NOARGS, FEdgeSharp_bMaterialIndex___doc__},
+ {"aMaterial", ( PyCFunction ) FEdgeSharp_aMaterial, METH_NOARGS, FEdgeSharp_aMaterial___doc__},
+ {"bMaterial", ( PyCFunction ) FEdgeSharp_bMaterial, METH_NOARGS, FEdgeSharp_bMaterial___doc__},
+ {"setNormalA", ( PyCFunction ) FEdgeSharp_setNormalA, METH_VARARGS, FEdgeSharp_setNormalA___doc__},
+ {"setNormalB", ( PyCFunction ) FEdgeSharp_setNormalB, METH_VARARGS, FEdgeSharp_setNormalB___doc__},
+ {"setaMaterialIndex", ( PyCFunction ) FEdgeSharp_setaMaterialIndex, METH_VARARGS, FEdgeSharp_setaMaterialIndex___doc__},
+ {"setbMaterialIndex", ( PyCFunction ) FEdgeSharp_setbMaterialIndex, METH_VARARGS, FEdgeSharp_setbMaterialIndex___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FEdgeSharp type definition ------------------------------*/
+
+PyTypeObject FEdgeSharp_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdgeSharp", /* tp_name */
+ sizeof(BPy_FEdgeSharp), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FEdgeSharp___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FEdgeSharp_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FEdge_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdgeSharp___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h
new file mode 100644
index 00000000000..84b01e27c21
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FEDGESHARP_H
+#define FREESTYLE_PYTHON_FEDGESHARP_H
+
+#include "../BPy_FEdge.h"
+#include "../../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdgeSharp_Type;
+
+#define BPy_FEdgeSharp_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdgeSharp_Type) )
+
+/*---------------------------Python BPy_FEdgeSharp structure definition----------*/
+typedef struct {
+ BPy_FEdge py_fe;
+ FEdgeSharp *fes;
+} BPy_FEdgeSharp;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FEDGESHARP_H */
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
new file mode 100644
index 00000000000..3e043108d98
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp
@@ -0,0 +1,205 @@
+#include "BPy_FEdgeSmooth.h"
+
+#include "../../BPy_Convert.h"
+#include "../../Interface0D/BPy_SVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FEdgeSmooth___doc__[] =
+"Class defining a smooth edge. This kind of edge typically runs across\n"
+"a face of the input mesh. It can be a silhouette, a ridge or valley,\n"
+"a suggestive contour.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An FEdgeSmooth object.\n"
+" :type iBrother: :class:`FEdgeSmooth`\n"
+"\n"
+".. method:: __init__(vA, vB)\n"
+"\n"
+" Builds an FEdgeSmooth going from vA to vB.\n"
+"\n"
+" :arg vA: The first SVertex object.\n"
+" :type vA: :class:`SVertex`\n"
+" :arg vB: The second SVertex object.\n"
+" :type vB: :class:`SVertex`\n";
+
+static int FEdgeSmooth___init__(BPy_FEdgeSmooth *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OO", &obj1, &obj2) )
+ return -1;
+
+ if( !obj1 ){
+ self->fes = new FEdgeSmooth();
+
+ } else if( !obj2 && BPy_FEdgeSmooth_Check(obj1) ) {
+ self->fes = new FEdgeSmooth(*( ((BPy_FEdgeSmooth *) obj1)->fes ));
+
+ } else if( obj2 && BPy_SVertex_Check(obj1) && BPy_SVertex_Check(obj2) ) {
+ self->fes = new FEdgeSmooth( ((BPy_SVertex *) obj1)->sv, ((BPy_SVertex *) obj2)->sv );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_fe.fe = self->fes;
+ self->py_fe.py_if1D.if1D = self->fes;
+ self->py_fe.py_if1D.borrowed = 0;
+
+ return 0;
+}
+
+static char FEdgeSmooth_normal___doc__[] =
+".. method:: normal()\n"
+"\n"
+" Returns the normal to the Face it is running accross.\n"
+"\n"
+" :return: The normal to the Face it is running accross.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static PyObject * FEdgeSmooth_normal( BPy_FEdgeSmooth *self ) {
+ Vec3r v( self->fes->normal() );
+ return Vector_from_Vec3r( v );
+}
+
+static char FEdgeSmooth_materialIndex___doc__[] =
+".. method:: materialIndex()\n"
+"\n"
+" Returns the index of the material of the face it is running accross.\n"
+"\n"
+" :return: The index of the material of the face it is running accross.\n"
+" :rtype: int\n";
+
+static PyObject * FEdgeSmooth_materialIndex( BPy_FEdgeSmooth *self ) {
+ return PyLong_FromLong( self->fes->frs_materialIndex() );
+}
+
+static char FEdgeSmooth_material___doc__[] =
+".. method:: material()\n"
+"\n"
+" Returns the material of the face it is running accross.\n"
+"\n"
+" :return: The material of the face it is running accross.\n"
+" :rtype: :class:`Material`\n";
+
+static PyObject * FEdgeSmooth_material( BPy_FEdgeSmooth *self ) {
+ FrsMaterial m( self->fes->frs_material() );
+ return BPy_FrsMaterial_from_FrsMaterial(m);
+}
+
+static char FEdgeSmooth_setNormal___doc__[] =
+".. method:: setNormal(iNormal)\n"
+"\n"
+" Sets the normal to the Face it is running accross.\n"
+"\n"
+" :arg iNormal: A three-dimensional vector.\n"
+" :type iNormal: :class:`mathutils.Vector`, list or tuple of 3 real numbers\n";
+
+static PyObject * FEdgeSmooth_setNormal( BPy_FEdgeSmooth *self, PyObject *args ) {
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "O", &obj) ))
+ return NULL;
+ Vec3r *v = Vec3r_ptr_from_PyObject(obj);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be a 3D vector (either a list of 3 elements or Vector)");
+ return NULL;
+ }
+ self->fes->setNormal( *v );
+ delete v;
+
+ Py_RETURN_NONE;
+}
+
+static char FEdgeSmooth_setMaterialIndex___doc__[] =
+".. method:: setMaterialIndex(i)\n"
+"\n"
+" Sets the index of the material of the face it is running accross.\n"
+"\n"
+" :arg i: The index of the material of the face it is running accross.\n"
+" :type i: int\n";
+
+static PyObject * FEdgeSmooth_setMaterialIndex( BPy_FEdgeSmooth *self, PyObject *args ) {
+ unsigned int i;
+
+ if(!( PyArg_ParseTuple(args, "I", &i) ))
+ return NULL;
+
+ self->fes->setFrsMaterialIndex( i );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------FEdgeSmooth instance definitions ----------------------------*/
+static PyMethodDef BPy_FEdgeSmooth_methods[] = {
+ {"normal", ( PyCFunction ) FEdgeSmooth_normal, METH_NOARGS, FEdgeSmooth_normal___doc__},
+ {"materialIndex", ( PyCFunction ) FEdgeSmooth_materialIndex, METH_NOARGS, FEdgeSmooth_materialIndex___doc__},
+ {"material", ( PyCFunction ) FEdgeSmooth_material, METH_NOARGS, FEdgeSmooth_material___doc__},
+ {"setNormal", ( PyCFunction ) FEdgeSmooth_setNormal, METH_VARARGS, FEdgeSmooth_setNormal___doc__},
+ {"setMaterialIndex", ( PyCFunction ) FEdgeSmooth_setMaterialIndex, METH_VARARGS, FEdgeSmooth_setMaterialIndex___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_FEdgeSmooth type definition ------------------------------*/
+
+PyTypeObject FEdgeSmooth_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FEdgeSmooth", /* tp_name */
+ sizeof(BPy_FEdgeSmooth), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FEdgeSmooth___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_FEdgeSmooth_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &FEdge_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FEdgeSmooth___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h
new file mode 100644
index 00000000000..d7b44bb1da7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FEDGESMOOTH_H
+#define FREESTYLE_PYTHON_FEDGESMOOTH_H
+
+#include "../BPy_FEdge.h"
+#include "../../../view_map/Silhouette.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FEdgeSmooth_Type;
+
+#define BPy_FEdgeSmooth_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FEdgeSmooth_Type) )
+
+/*---------------------------Python BPy_FEdgeSmooth structure definition----------*/
+typedef struct {
+ BPy_FEdge py_fe;
+ FEdgeSmooth *fes;
+} BPy_FEdgeSmooth;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FEDGESMOOTH_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
new file mode 100644
index 00000000000..a4fe0164f78
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp
@@ -0,0 +1,165 @@
+#include "BPy_AdjacencyIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char AdjacencyIterator___doc__[] =
+"Class for representing adjacency iterators used in the chaining\n"
+"process. An AdjacencyIterator is created in the increment() and\n"
+"decrement() methods of a :class:`ChainingIterator` and passed to the\n"
+"traverse() method of the ChainingIterator.\n"
+"\n"
+".. method:: __init__(iVertex, iRestrictToSelection=True, iRestrictToUnvisited=True)\n"
+"\n"
+" Builds a AdjacencyIterator object.\n"
+"\n"
+" :arg iVertex: The vertex which is the next crossing.\n"
+" :type iVertex: :class:`ViewVertex`\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: An AdjacencyIterator object.\n"
+" :type it: :class:`AdjacencyIterator`\n";
+
+static int AdjacencyIterator___init__(BPy_AdjacencyIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0 , *obj3 = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOO", &obj1, &obj2, &obj3) )
+ return -1;
+
+ if( !obj1 && !obj2 && !obj3 ){
+ self->a_it = new AdjacencyIterator();
+
+ } else if( BPy_AdjacencyIterator_Check(obj1) ) {
+ self->a_it = new AdjacencyIterator(*( ((BPy_AdjacencyIterator *) obj1)->a_it ));
+
+ } else if( BPy_ViewVertex_Check(obj1) ) {
+ bool restrictToSelection = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+ bool restrictToUnvisited = ( obj3 ) ? bool_from_PyBool(obj3) : true;
+
+ self->a_it = new AdjacencyIterator( ((BPy_ViewVertex *) obj1)->vv, restrictToSelection, restrictToUnvisited );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_it.it = self->a_it;
+
+ return 0;
+
+}
+
+static PyObject * AdjacencyIterator_iternext(BPy_AdjacencyIterator *self) {
+ if (self->a_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ ViewEdge *ve = self->a_it->operator*();
+ self->a_it->increment();
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+}
+
+static char AdjacencyIterator_isIncoming___doc__[] =
+".. method:: isIncoming()\n"
+"\n"
+" Returns true if the current ViewEdge is coming towards the\n"
+" iteration vertex. False otherwise.\n"
+"\n"
+" :return: True if the current ViewEdge is coming towards the\n"
+" iteration vertex\n"
+" :rtype: bool\n";
+
+static PyObject * AdjacencyIterator_isIncoming(BPy_AdjacencyIterator *self) {
+ return PyBool_from_bool(self->a_it->isIncoming());
+}
+
+static char AdjacencyIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed ViewEdge.\n"
+"\n"
+" :return: The pointed ViewEdge.\n"
+" :rtype: ViewEdge* operator\n";
+
+static PyObject * AdjacencyIterator_getObject(BPy_AdjacencyIterator *self) {
+
+ ViewEdge *ve = self->a_it->operator*();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------AdjacencyIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_AdjacencyIterator_methods[] = {
+ {"isIncoming", ( PyCFunction ) AdjacencyIterator_isIncoming, METH_NOARGS, AdjacencyIterator_isIncoming___doc__},
+ {"getObject", ( PyCFunction ) AdjacencyIterator_getObject, METH_NOARGS, AdjacencyIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_AdjacencyIterator type definition ------------------------------*/
+
+PyTypeObject AdjacencyIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "AdjacencyIterator", /* tp_name */
+ sizeof(BPy_AdjacencyIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ AdjacencyIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)AdjacencyIterator_iternext, /* tp_iternext */
+ BPy_AdjacencyIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)AdjacencyIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
new file mode 100644
index 00000000000..733a9f2fcab
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_ADJACENCYITERATOR_H
+#define FREESTYLE_PYTHON_ADJACENCYITERATOR_H
+
+#include "../../stroke/ChainingIterators.h"
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject AdjacencyIterator_Type;
+
+#define BPy_AdjacencyIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &AdjacencyIterator_Type) )
+
+/*---------------------------Python BPy_AdjacencyIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ AdjacencyIterator *a_it;
+} BPy_AdjacencyIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ADJACENCYITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
new file mode 100644
index 00000000000..624d983da4d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp
@@ -0,0 +1,203 @@
+#include "BPy_ChainPredicateIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_BinaryPredicate1D.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainPredicateIterator___doc__[] =
+"A \"generic\" user-controlled ViewEdge iterator. This iterator is in\n"
+"particular built from a unary predicate and a binary predicate.\n"
+"First, the unary predicate is evaluated for all potential next\n"
+"ViewEdges in order to only keep the ones respecting a certain\n"
+"constraint. Then, the binary predicate is evaluated on the current\n"
+"ViewEdge together with each ViewEdge of the previous selection. The\n"
+"first ViewEdge respecting both the unary predicate and the binary\n"
+"predicate is kept as the next one. If none of the potential next\n"
+"ViewEdge respects these two predicates, None is returned.\n"
+"\n"
+".. method:: __init__(iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainPredicateIterator from a starting ViewEdge and its\n"
+" orientation.\n"
+"\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin. \n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(upred, bpred, iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainPredicateIterator from a unary predicate, a binary\n"
+" predicate, a starting ViewEdge and its orientation.\n"
+"\n"
+" :arg upred: The unary predicate that the next ViewEdge must satisfy.\n"
+" :type upred: :class:`UnaryPredicate1D`\n"
+" :arg bpred: The binary predicate that the next ViewEdge must\n"
+" satisfy together with the actual pointed ViewEdge.\n"
+" :type bpred: :class:`BinaryPredicate1D`\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge`\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ChainPredicateIterator object.\n"
+" :type brother: :class:`ChainPredicateIterator`\n";
+
+static int ChainPredicateIterator___init__(BPy_ChainPredicateIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0, *obj5 = 0, *obj6 = 0;
+
+ if (!( PyArg_ParseTuple(args, "|OOOOOO", &obj1, &obj2, &obj3, &obj4, &obj5, &obj6) ))
+ return -1;
+
+ if( obj1 && BPy_ChainPredicateIterator_Check(obj1) ) {
+ self->cp_it = new ChainPredicateIterator(*( ((BPy_ChainPredicateIterator *) obj1)->cp_it ));
+ self->upred = NULL;
+ self->bpred = NULL;
+
+ } else if( obj1 && BPy_UnaryPredicate1D_Check(obj1) &&
+ obj2 && BPy_BinaryPredicate1D_Check(obj2) ) {
+
+ if (!((BPy_UnaryPredicate1D *) obj1)->up1D) {
+ PyErr_SetString(PyExc_TypeError, "1st argument: invalid UnaryPredicate1D object");
+ return -1;
+ }
+ if (!((BPy_BinaryPredicate1D *) obj2)->bp1D) {
+ PyErr_SetString(PyExc_TypeError, "2nd argument: invalid BinaryPredicate1D object");
+ return -1;
+ }
+ UnaryPredicate1D *up1D = ((BPy_UnaryPredicate1D *) obj1)->up1D;
+ BinaryPredicate1D *bp1D = ((BPy_BinaryPredicate1D *) obj2)->bp1D;
+ bool restrictToSelection = ( obj3 ) ? bool_from_PyBool(obj3) : true;
+ bool restrictToUnvisited = ( obj4 ) ? bool_from_PyBool(obj4) : true;
+ ViewEdge *begin;
+ if ( !obj5 || obj5 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj5) )
+ begin = ((BPy_ViewEdge *) obj5)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "5th argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj6 ) ? bool_from_PyBool(obj6) : true;
+
+ self->cp_it = new ChainPredicateIterator( *up1D, *bp1D, restrictToSelection, restrictToUnvisited, begin, orientation);
+ self->upred = obj1;
+ self->bpred = obj2;
+ Py_INCREF( self->upred );
+ Py_INCREF( self->bpred );
+
+ } else {
+ bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true;
+ bool restrictToUnvisited = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+ ViewEdge *begin;
+ if ( !obj3 || obj3 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj3) )
+ begin = ((BPy_ViewEdge *) obj3)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "3rd argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj4 ) ? bool_from_PyBool(obj4) : true;
+
+ self->cp_it = new ChainPredicateIterator( restrictToSelection, restrictToUnvisited, begin, orientation);
+ self->upred = NULL;
+ self->bpred = NULL;
+ }
+
+ self->py_c_it.c_it = self->cp_it;
+ self->py_c_it.py_ve_it.ve_it = self->cp_it;
+ self->py_c_it.py_ve_it.py_it.it = self->cp_it;
+
+
+ return 0;
+
+}
+
+static void ChainPredicateIterator___dealloc__(BPy_ChainPredicateIterator *self)
+{
+ Py_XDECREF( self->upred );
+ Py_XDECREF( self->bpred );
+ ChainingIterator_Type.tp_dealloc((PyObject *)self);
+}
+
+/*-----------------------BPy_ChainPredicateIterator type definition ------------------------------*/
+
+PyTypeObject ChainPredicateIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainPredicateIterator", /* tp_name */
+ sizeof(BPy_ChainPredicateIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)ChainPredicateIterator___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainPredicateIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ChainingIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainPredicateIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h
new file mode 100644
index 00000000000..5a31ac407d5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h
@@ -0,0 +1,35 @@
+#ifndef FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H
+#define FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ChainingIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainPredicateIterator_Type;
+
+#define BPy_ChainPredicateIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainPredicateIterator_Type) )
+
+/*---------------------------Python BPy_ChainPredicateIterator structure definition----------*/
+typedef struct {
+ BPy_ChainingIterator py_c_it;
+ ChainPredicateIterator *cp_it;
+ PyObject *upred;
+ PyObject *bpred;
+} BPy_ChainPredicateIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAINPREDICATEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
new file mode 100644
index 00000000000..00e62ad30d4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp
@@ -0,0 +1,129 @@
+#include "BPy_ChainSilhouetteIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+// ChainSilhouetteIterator (bool iRestrictToSelection=true, ViewEdge *begin=NULL, bool orientation=true)
+// ChainSilhouetteIterator (const ChainSilhouetteIterator &brother)
+
+static char ChainSilhouetteIterator___doc__[] =
+"A ViewEdge Iterator used to follow ViewEdges the most naturally. For\n"
+"example, it will follow visible ViewEdges of same nature. As soon, as\n"
+"the nature or the visibility changes, the iteration stops (by setting\n"
+"the pointed ViewEdge to 0). In the case of an iteration over a set of\n"
+"ViewEdge that are both Silhouette and Crease, there will be a\n"
+"precedence of the silhouette over the crease criterion.\n"
+"\n"
+".. method:: __init__(iRestrictToSelection=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a ChainSilhouetteIterator from the first ViewEdge used for\n"
+" iteration and its orientation.\n"
+"\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge`\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A ChainSilhouetteIterator object.\n"
+" :type brother: :class:`ChainSilhouetteIterator`\n";
+
+static int ChainSilhouetteIterator___init__(BPy_ChainSilhouetteIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0;
+
+ if (!( PyArg_ParseTuple(args, "|OOO", &obj1, &obj2, &obj3) ))
+ return -1;
+
+ if( obj1 && BPy_ChainSilhouetteIterator_Check(obj1) ) {
+ self->cs_it = new ChainSilhouetteIterator(*( ((BPy_ChainSilhouetteIterator *) obj1)->cs_it ));
+
+ } else {
+ bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true;
+ ViewEdge *begin;
+ if ( !obj2 || obj2 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj2) )
+ begin = ((BPy_ViewEdge *) obj2)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "2nd argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj3 ) ? bool_from_PyBool(obj3) : true;
+
+ self->cs_it = new ChainSilhouetteIterator( restrictToSelection, begin, orientation);
+ }
+
+ self->py_c_it.c_it = self->cs_it;
+ self->py_c_it.py_ve_it.ve_it = self->cs_it;
+ self->py_c_it.py_ve_it.py_it.it = self->cs_it;
+
+ return 0;
+
+}
+
+/*-----------------------BPy_ChainSilhouetteIterator type definition ------------------------------*/
+
+PyTypeObject ChainSilhouetteIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainSilhouetteIterator", /* tp_name */
+ sizeof(BPy_ChainSilhouetteIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainSilhouetteIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ChainingIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainSilhouetteIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
new file mode 100644
index 00000000000..912d397d279
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H
+#define FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ChainingIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainSilhouetteIterator_Type;
+
+#define BPy_ChainSilhouetteIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainSilhouetteIterator_Type) )
+
+/*---------------------------Python BPy_ChainSilhouetteIterator structure definition----------*/
+typedef struct {
+ BPy_ChainingIterator py_c_it;
+ ChainSilhouetteIterator *cs_it;
+} BPy_ChainSilhouetteIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAINSILHOUETTEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
new file mode 100644
index 00000000000..9d3b1e5c0be
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp
@@ -0,0 +1,234 @@
+#include "BPy_ChainingIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_ViewVertex.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+#include "BPy_AdjacencyIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainingIterator___doc__[] =
+"Base class for chaining iterators. This class is designed to be\n"
+"overloaded in order to describe chaining rules. It makes the\n"
+"description of chaining rules easier. The two main methods that need\n"
+"to overloaded are traverse() and init(). traverse() tells which\n"
+":class:`ViewEdge` to follow, among the adjacent ones. If you specify\n"
+"restriction rules (such as \"Chain only ViewEdges of the selection\"),\n"
+"they will be included in the adjacency iterator (i.e, the adjacent\n"
+"iterator will only stop on \"valid\" edges).\n"
+"\n"
+".. method:: __init__(iRestrictToSelection=True, iRestrictToUnvisited=True, begin=None, orientation=True)\n"
+"\n"
+" Builds a Chaining Iterator from the first ViewEdge used for\n"
+" iteration and its orientation.\n"
+"\n"
+" :arg iRestrictToSelection: Indicates whether to force the chaining\n"
+" to stay within the set of selected ViewEdges or not.\n"
+" :type iRestrictToSelection: bool\n"
+" :arg iRestrictToUnvisited: Indicates whether a ViewEdge that has\n"
+" already been chained must be ignored ot not.\n"
+" :type iRestrictToUnvisited: bool\n"
+" :arg begin: The ViewEdge from which to start the chain.\n"
+" :type begin: :class:`ViewEdge` or None\n"
+" :arg orientation: The direction to follow to explore the graph. If\n"
+" true, the direction indicated by the first ViewEdge is used.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: \n"
+" :type brother: ChainingIterator\n";
+
+static int ChainingIterator___init__(BPy_ChainingIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+
+ if (!( PyArg_ParseTuple(args, "|OOOO", &obj1, &obj2, &obj3, &obj4) ))
+ return -1;
+
+ if( obj1 && BPy_ChainingIterator_Check(obj1) ) {
+ self->c_it = new ChainingIterator(*( ((BPy_ChainingIterator *) obj1)->c_it ));
+
+ } else {
+ bool restrictToSelection = ( obj1 ) ? bool_from_PyBool(obj1) : true;
+ bool restrictToUnvisited = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+ ViewEdge *begin;
+ if ( !obj3 || obj3 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj3) )
+ begin = ((BPy_ViewEdge *) obj3)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "3rd argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj4 ) ? bool_from_PyBool(obj4) : true;
+
+ self->c_it = new ChainingIterator( restrictToSelection, restrictToUnvisited, begin, orientation);
+ }
+
+ self->py_ve_it.ve_it = self->c_it;
+ self->py_ve_it.py_it.it = self->c_it;
+
+ self->c_it->py_c_it = (PyObject *) self;
+
+ return 0;
+}
+
+static char ChainingIterator_init___doc__[] =
+".. method:: init()\n"
+"\n"
+" Initializes the iterator context. This method is called each\n"
+" time a new chain is started. It can be used to reset some\n"
+" history information that you might want to keep.\n";
+
+static PyObject *ChainingIterator_init( BPy_ChainingIterator *self ) {
+ if( typeid(*(self->c_it)) == typeid(ChainingIterator) ) {
+ PyErr_SetString(PyExc_TypeError, "init() method not properly overridden");
+ return NULL;
+ }
+ self->c_it->init();
+
+ Py_RETURN_NONE;
+}
+
+static char ChainingIterator_traverse___doc__[] =
+".. method:: traverse(it)\n"
+"\n"
+" This method iterates over the potential next ViewEdges and returns\n"
+" the one that will be followed next. Returns the next ViewEdge to\n"
+" follow or None when the end of the chain is reached.\n"
+"\n"
+" :arg it: The iterator over the ViewEdges adjacent to the end vertex\n"
+" of the current ViewEdge. The adjacency iterator reflects the\n"
+" restriction rules by only iterating over the valid ViewEdges.\n"
+" :type it: :class:`AdjacencyIterator`\n"
+" :return: Returns the next ViewEdge to follow, or None if chaining ends.\n"
+" :rtype: :class:`ViewEdge` or None\n";
+
+static PyObject *ChainingIterator_traverse( BPy_ChainingIterator *self, PyObject *args ) {
+ PyObject *py_a_it;
+
+ if(!( PyArg_ParseTuple(args, "O!", &AdjacencyIterator_Type, &py_a_it) ))
+ return NULL;
+
+ if( typeid(*(self->c_it)) == typeid(ChainingIterator) ) {
+ PyErr_SetString(PyExc_TypeError, "traverse() method not properly overridden");
+ return NULL;
+ }
+ if( ((BPy_AdjacencyIterator *) py_a_it)->a_it )
+ self->c_it->traverse(*( ((BPy_AdjacencyIterator *) py_a_it)->a_it ));
+
+ Py_RETURN_NONE;
+}
+
+static char ChainingIterator_getVertex___doc__[] =
+".. method:: getVertex()\n"
+"\n"
+" Returns the vertex which is the next crossing.\n"
+"\n"
+" :return: The vertex which is the next crossing.\n"
+" :rtype: :class:`ViewVertex`\n";
+
+static PyObject *ChainingIterator_getVertex( BPy_ChainingIterator *self ) {
+ ViewVertex *v = self->c_it->getVertex();
+ if( v )
+ return Any_BPy_ViewVertex_from_ViewVertex( *v );
+
+ Py_RETURN_NONE;
+}
+
+static char ChainingIterator_isIncrementing___doc__[] =
+".. method:: isIncrementing()\n"
+"\n"
+" Returns true if the current iteration is an incrementation.\n"
+"\n"
+" :return: True if the current iteration is an incrementation.\n"
+" :rtype: bool\n";
+
+static PyObject *ChainingIterator_isIncrementing( BPy_ChainingIterator *self ) {
+ return PyBool_from_bool( self->c_it->isIncrementing() );
+}
+
+static char ChainingIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed ViewEdge.\n"
+"\n"
+" :return: The pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * ChainingIterator_getObject( BPy_ChainingIterator *self) {
+
+ ViewEdge *ve = self->c_it->operator*();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------ChainingIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_ChainingIterator_methods[] = {
+ {"init", ( PyCFunction ) ChainingIterator_init, METH_NOARGS, ChainingIterator_init___doc__},
+ {"traverse", ( PyCFunction ) ChainingIterator_traverse, METH_VARARGS, ChainingIterator_traverse___doc__},
+ {"getVertex", ( PyCFunction ) ChainingIterator_getVertex, METH_NOARGS, ChainingIterator_getVertex___doc__},
+ {"isIncrementing", ( PyCFunction ) ChainingIterator_isIncrementing, METH_NOARGS, ChainingIterator_isIncrementing___doc__},
+ {"getObject", ( PyCFunction ) ChainingIterator_getObject, METH_NOARGS, ChainingIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ChainingIterator type definition ------------------------------*/
+
+PyTypeObject ChainingIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainingIterator", /* tp_name */
+ sizeof(BPy_ChainingIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainingIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ChainingIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &ViewEdgeIterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainingIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
new file mode 100644
index 00000000000..2a00aa8072f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_CHAININGITERATOR_H
+#define FREESTYLE_PYTHON_CHAININGITERATOR_H
+
+
+#include "../../stroke/ChainingIterators.h"
+
+#include "BPy_ViewEdgeIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainingIterator_Type;
+
+#define BPy_ChainingIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainingIterator_Type) )
+
+/*---------------------------Python BPy_ChainingIterator structure definition----------*/
+typedef struct {
+ BPy_ViewEdgeIterator py_ve_it;
+ ChainingIterator *c_it;
+} BPy_ChainingIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAININGITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
new file mode 100644
index 00000000000..9af842b7612
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp
@@ -0,0 +1,169 @@
+#include "BPy_CurvePointIterator.h"
+
+#include "../BPy_Convert.h"
+#include "BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurvePointIterator___doc__[] =
+"Class representing an iterator on a curve. Allows an iterating\n"
+"outside initial vertices. A CurvePoint is instanciated and returned\n"
+"by getObject().\n"
+"\n"
+".. method:: __init__(step=0.0)\n"
+"\n"
+" Builds a CurvePointIterator object.\n"
+"\n"
+" :arg step: A resampling resolution with which the curve is resampled.\n"
+" If zero, no resampling is done (i.e., the iterator iterates over\n"
+" initial vertices).\n"
+" :type step: float\n"
+"\n"
+".. method:: __init__(brother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg brother: A CurvePointIterator object.\n"
+" :type brother: :class:`CurvePointIterator`\n";
+
+static int CurvePointIterator___init__(BPy_CurvePointIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->cp_it = new CurveInternal::CurvePointIterator();
+
+ } else if( BPy_CurvePointIterator_Check(obj) ) {
+ self->cp_it = new CurveInternal::CurvePointIterator(*( ((BPy_CurvePointIterator *) obj)->cp_it ));
+
+ } else if( PyFloat_Check(obj) ) {
+ self->cp_it = new CurveInternal::CurvePointIterator( PyFloat_AsDouble(obj) );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_it.it = self->cp_it;
+
+ return 0;
+}
+
+static char CurvePointIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+PyObject * CurvePointIterator_t( BPy_CurvePointIterator *self ) {
+ return PyFloat_FromDouble( self->cp_it->t() );
+}
+
+static char CurvePointIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter in the curve (0<=u<=1).\n"
+"\n"
+" :return: The point parameter.\n"
+" :rtype: float\n";
+
+static PyObject * CurvePointIterator_u( BPy_CurvePointIterator *self ) {
+ return PyFloat_FromDouble( self->cp_it->u() );
+}
+
+static char CurvePointIterator_castToInterface0DIterator___doc__[] =
+".. method:: castToInterface0DIterator()\n"
+"\n"
+" Returns an Interface0DIterator converted from this\n"
+" CurvePointIterator. Useful for any call to a function of the\n"
+" UnaryFunction0D type.\n"
+"\n"
+" :return: An Interface0DIterator object converted from the\n"
+" iterator.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * CurvePointIterator_castToInterface0DIterator( BPy_CurvePointIterator *self ) {
+ Interface0DIterator it( self->cp_it->castToInterface0DIterator() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( it, 0 );
+}
+
+static char CurvePointIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns a CurvePoint pointed by the iterator.\n"
+"\n"
+" :return: \n"
+" :rtype: :class:`CurvePoint`\n";
+
+static PyObject * CurvePointIterator_getObject(BPy_CurvePointIterator *self) {
+ return BPy_CurvePoint_from_CurvePoint( self->cp_it->operator*() );
+}
+
+/*----------------------CurvePointIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_CurvePointIterator_methods[] = {
+ {"t", ( PyCFunction ) CurvePointIterator_t, METH_NOARGS, CurvePointIterator_t___doc__},
+ {"u", ( PyCFunction ) CurvePointIterator_u, METH_NOARGS, CurvePointIterator_u___doc__},
+ {"castToInterface0DIterator", ( PyCFunction ) CurvePointIterator_castToInterface0DIterator, METH_NOARGS, CurvePointIterator_castToInterface0DIterator___doc__},
+ {"getObject", ( PyCFunction ) CurvePointIterator_getObject, METH_NOARGS, CurvePointIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_CurvePointIterator type definition ------------------------------*/
+
+PyTypeObject CurvePointIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurvePointIterator", /* tp_name */
+ sizeof(BPy_CurvePointIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurvePointIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_CurvePointIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurvePointIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
new file mode 100644
index 00000000000..ad04c7208bb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h
@@ -0,0 +1,32 @@
+#ifndef FREESTYLE_PYTHON_CURVEPOINTITERATOR_H
+#define FREESTYLE_PYTHON_CURVEPOINTITERATOR_H
+
+#include "../../stroke/CurveIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurvePointIterator_Type;
+
+#define BPy_CurvePointIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurvePointIterator_Type) )
+
+/*---------------------------Python BPy_CurvePointIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ CurveInternal::CurvePointIterator *cp_it;
+} BPy_CurvePointIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVEPOINTITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
new file mode 100644
index 00000000000..7276f7cd46b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp
@@ -0,0 +1,149 @@
+#include "BPy_Interface0DIterator.h"
+
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Interface0DIterator___doc__[] =
+"Class defining an iterator over Interface0D elements. An instance of\n"
+"this iterator is always obtained from a 1D element.\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n";
+
+static int Interface0DIterator___init__(BPy_Interface0DIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (!( PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj) ))
+ return -1;
+
+ self->if0D_it = new Interface0DIterator(*( ((BPy_Interface0DIterator *) obj)->if0D_it ));
+ self->py_it.it = self->if0D_it;
+ self->reversed = 0;
+
+ return 0;
+}
+
+static PyObject * Interface0DIterator_iternext( BPy_Interface0DIterator *self ) {
+ Interface0D *if0D;
+ if (self->reversed) {
+ if (self->if0D_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->if0D_it->decrement();
+ if0D = self->if0D_it->operator->();
+ } else {
+ if (self->if0D_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ if0D = self->if0D_it->operator->();
+ self->if0D_it->increment();
+ }
+ return Any_BPy_Interface0D_from_Interface0D( *if0D );
+}
+
+static char Interface0DIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * Interface0DIterator_t( BPy_Interface0DIterator *self ) {
+ return PyFloat_FromDouble( self->if0D_it->t() );
+}
+
+static char Interface0DIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter in the curve 0<=u<=1.\n"
+"\n"
+" :return: The point parameter.\n"
+" :rtype: float\n";
+
+static PyObject * Interface0DIterator_u( BPy_Interface0DIterator *self ) {
+ return PyFloat_FromDouble( self->if0D_it->u() );
+}
+
+static char Interface0DIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed Interface0D.\n"
+"\n"
+" :return: The pointed Interface0D.\n"
+" :rtype: :class:`Interface0D`\n";
+
+static PyObject * Interface0DIterator_getObject(BPy_Interface0DIterator *self) {
+ return Any_BPy_Interface0D_from_Interface0D( self->if0D_it->operator*() );
+}
+
+/*----------------------Interface0DIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_Interface0DIterator_methods[] = {
+ {"t", ( PyCFunction ) Interface0DIterator_t, METH_NOARGS, Interface0DIterator_t___doc__},
+ {"u", ( PyCFunction ) Interface0DIterator_u, METH_NOARGS, Interface0DIterator_u___doc__},
+ {"getObject", ( PyCFunction ) Interface0DIterator_getObject, METH_NOARGS, Interface0DIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_Interface0DIterator type definition ------------------------------*/
+
+PyTypeObject Interface0DIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Interface0DIterator", /* tp_name */
+ sizeof(BPy_Interface0DIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Interface0DIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)Interface0DIterator_iternext, /* tp_iternext */
+ BPy_Interface0DIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Interface0DIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
new file mode 100644
index 00000000000..1972763b2eb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_INTERFACE0DITERATOR_H
+#define FREESTYLE_PYTHON_INTERFACE0DITERATOR_H
+
+#include "../../view_map/Interface0D.h"
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Interface0DIterator_Type;
+
+#define BPy_Interface0DIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Interface0DIterator_Type) )
+
+/*---------------------------Python BPy_Interface0DIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ Interface0DIterator *if0D_it;
+ int reversed;
+} BPy_Interface0DIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INTERFACE0DITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
new file mode 100644
index 00000000000..06329ce2e30
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp
@@ -0,0 +1,179 @@
+#include "BPy_SVertexIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface0D/BPy_SVertex.h"
+#include "../Interface1D/BPy_FEdge.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SVertexIterator___doc__[] =
+"Class representing an iterator over :class:`SVertex` of a\n"
+":class:`ViewEdge`. An instance of an SVertexIterator can be obtained\n"
+"from a ViewEdge by calling verticesBegin() or verticesEnd().\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: An SVertexIterator object.\n"
+" :type it: :class:`SVertexIterator`\n"
+"\n"
+".. method:: __init__(v, begin, prev, next, t)\n"
+"\n"
+" Builds an SVertexIterator that starts iteration from an SVertex\n"
+" object v.\n"
+"\n"
+" :arg v: The SVertex from which the iterator starts iteration.\n"
+" :type v: :class:`SVertex`\n"
+" :arg begin: The first vertex of a view edge.\n"
+" :type begin: :class:`SVertex`\n"
+" :arg prev: The previous FEdge coming to v.\n"
+" :type prev: :class:`FEdge`\n"
+" :arg next: The next FEdge going out from v.\n"
+" :type next: :class:`FEdge`\n"
+" :arg t: The curvilinear abscissa at v.\n"
+" :type t: float\n";
+
+static int SVertexIterator___init__(BPy_SVertexIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0, *obj3 = 0, *obj4 = 0;
+ float f = 0;
+
+ if (! PyArg_ParseTuple(args, "|OOOOf", &obj1, &obj2, &obj3, &obj4, f) )
+ return -1;
+
+ if( !obj1 ){
+ self->sv_it = new ViewEdgeInternal::SVertexIterator();
+
+ } else if( BPy_SVertexIterator_Check(obj1) ) {
+ self->sv_it = new ViewEdgeInternal::SVertexIterator(*( ((BPy_SVertexIterator *) obj1)->sv_it ));
+
+ } else if( obj1 && BPy_SVertex_Check(obj1) &&
+ obj2 && BPy_SVertex_Check(obj2) &&
+ obj3 && BPy_FEdge_Check(obj3) &&
+ obj4 && BPy_FEdge_Check(obj4) ) {
+
+ self->sv_it = new ViewEdgeInternal::SVertexIterator(
+ ((BPy_SVertex *) obj1)->sv,
+ ((BPy_SVertex *) obj2)->sv,
+ ((BPy_FEdge *) obj3)->fe,
+ ((BPy_FEdge *) obj4)->fe,
+ f );
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument(s)");
+ return -1;
+ }
+
+ self->py_it.it = self->sv_it;
+
+ return 0;
+}
+
+static char SVertexIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa.\n"
+"\n"
+" :return: The curvilinear abscissa.\n"
+" :rtype: float\n";
+
+static PyObject * SVertexIterator_t( BPy_SVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->t() );
+}
+
+static char SVertexIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter (0<=u<=1).\n"
+"\n"
+" :return: The point parameter.\n"
+" :rtype: float\n";
+
+static PyObject * SVertexIterator_u( BPy_SVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->u() );
+}
+
+static char SVertexIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed SVertex.\n"
+"\n"
+" :return: the pointed SVertex.\n"
+" :rtype: :class:`SVertex`\n";
+
+static PyObject * SVertexIterator_getObject( BPy_SVertexIterator *self) {
+ SVertex *sv = self->sv_it->operator->();
+
+ if( sv )
+ return BPy_SVertex_from_SVertex( *sv );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------SVertexIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_SVertexIterator_methods[] = {
+ {"t", ( PyCFunction ) SVertexIterator_t, METH_NOARGS, SVertexIterator_t___doc__},
+ {"u", ( PyCFunction ) SVertexIterator_u, METH_NOARGS, SVertexIterator_u___doc__},
+ {"getObject", ( PyCFunction ) SVertexIterator_getObject, METH_NOARGS, SVertexIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_SVertexIterator type definition ------------------------------*/
+
+PyTypeObject SVertexIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SVertexIterator", /* tp_name */
+ sizeof(BPy_SVertexIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SVertexIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_SVertexIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SVertexIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
new file mode 100644
index 00000000000..b40f4d36420
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_SVERTEXITERATOR_H
+#define FREESTYLE_PYTHON_SVERTEXITERATOR_H
+
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SVertexIterator_Type;
+
+#define BPy_SVertexIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SVertexIterator_Type) )
+
+/*---------------------------Python BPy_SVertexIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewEdgeInternal::SVertexIterator *sv_it;
+} BPy_SVertexIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SVERTEXITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
new file mode 100644
index 00000000000..607109ce3ad
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp
@@ -0,0 +1,194 @@
+#include "BPy_StrokeVertexIterator.h"
+
+#include "../BPy_Convert.h"
+#include "BPy_Interface0DIterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeVertexIterator___doc__[] =
+
+"Class defining an iterator designed to iterate over the\n"
+":class:`StrokeVertex` of a :class:`Stroke`. An instance of a\n"
+"StrokeVertexIterator can only be obtained from a Stroke by calling\n"
+"strokeVerticesBegin() or strokeVerticesEnd(). It is iterating over\n"
+"the same vertices as an :class:`Interface0DIterator`. The difference\n"
+"resides in the object access. Indeed, an Interface0DIterator allows\n"
+"only an access to an Interface0D whereas we could need to access the\n"
+"specialized StrokeVertex type. In this case, one should use a\n"
+"StrokeVertexIterator. The castToInterface0DIterator() method is\n"
+"useful to get an Interface0DIterator from a StrokeVertexIterator in\n"
+"order to call any functions of the UnaryFunction0D type.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: A StrokeVertexIterator object.\n"
+" :type it: :class:`StrokeVertexIterator`\n";
+
+static int StrokeVertexIterator___init__(BPy_StrokeVertexIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (! PyArg_ParseTuple(args, "|O", &obj) )
+ return -1;
+
+ if( !obj ){
+ self->sv_it = new StrokeInternal::StrokeVertexIterator();
+
+ } else if( BPy_StrokeVertexIterator_Check(obj) ) {
+ self->sv_it = new StrokeInternal::StrokeVertexIterator(*( ((BPy_StrokeVertexIterator *) obj)->sv_it ));
+
+ } else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_it.it = self->sv_it;
+ self->reversed = 0;
+
+ return 0;
+}
+
+static PyObject * StrokeVertexIterator_iternext( BPy_StrokeVertexIterator *self ) {
+ StrokeVertex *sv;
+ if (self->reversed) {
+ if (self->sv_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->sv_it->decrement();
+ sv = self->sv_it->operator->();
+ } else {
+ if (self->sv_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ sv = self->sv_it->operator->();
+ self->sv_it->increment();
+ }
+ return BPy_StrokeVertex_from_StrokeVertex( *sv );
+}
+
+static char StrokeVertexIterator_t___doc__[] =
+".. method:: t()\n"
+"\n"
+" Returns the curvilinear abscissa of the current point.\n"
+"\n"
+" :return: The curvilinear abscissa of the current point.\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertexIterator_t( BPy_StrokeVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->t() );
+}
+
+static char StrokeVertexIterator_u___doc__[] =
+".. method:: u()\n"
+"\n"
+" Returns the point parameter in the stroke (0<=u<=1).\n"
+"\n"
+" :return: The point parameter in the stroke\n"
+" :rtype: float\n";
+
+static PyObject * StrokeVertexIterator_u( BPy_StrokeVertexIterator *self ) {
+ return PyFloat_FromDouble( self->sv_it->u() );
+}
+
+static char StrokeVertexIterator_castToInterface0DIterator___doc__[] =
+".. method:: castToInterface0DIterator()\n"
+"\n"
+" Returns an Interface0DIterator converted from this\n"
+" StrokeVertexIterator. Useful for any call to a function of the\n"
+" UnaryFunction0D type.\n"
+"\n"
+" :return: An Interface0DIterator converted from the StrokeVertexIterator.\n"
+" :rtype: :class:`Interface0DIterator`\n";
+
+static PyObject * StrokeVertexIterator_castToInterface0DIterator( BPy_StrokeVertexIterator *self ) {
+ Interface0DIterator it( self->sv_it->castToInterface0DIterator() );
+ return BPy_Interface0DIterator_from_Interface0DIterator( it, 0 );
+}
+
+static char StrokeVertexIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed StrokeVertex.\n"
+"\n"
+" :return: The pointed StrokeVertex.\n"
+" :rtype: :class:`StrokeVertex`\n";
+
+static PyObject * StrokeVertexIterator_getObject( BPy_StrokeVertexIterator *self) {
+ StrokeVertex *sv = self->sv_it->operator->();
+ if( sv )
+ return BPy_StrokeVertex_from_StrokeVertex( *sv );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------StrokeVertexIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_StrokeVertexIterator_methods[] = {
+ {"t", ( PyCFunction ) StrokeVertexIterator_t, METH_NOARGS, StrokeVertexIterator_t___doc__},
+ {"u", ( PyCFunction ) StrokeVertexIterator_u, METH_NOARGS, StrokeVertexIterator_u___doc__},
+ {"castToInterface0DIterator", ( PyCFunction ) StrokeVertexIterator_castToInterface0DIterator, METH_NOARGS, StrokeVertexIterator_castToInterface0DIterator___doc__},
+ {"getObject", ( PyCFunction ) StrokeVertexIterator_getObject, METH_NOARGS, StrokeVertexIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_StrokeVertexIterator type definition ------------------------------*/
+
+PyTypeObject StrokeVertexIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeVertexIterator", /* tp_name */
+ sizeof(BPy_StrokeVertexIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeVertexIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)StrokeVertexIterator_iternext, /* tp_iternext */
+ BPy_StrokeVertexIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeVertexIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
new file mode 100644
index 00000000000..0c4b6e4bb6c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H
+#define FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H
+
+#include "../../stroke/StrokeIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeVertexIterator_Type;
+
+#define BPy_StrokeVertexIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeVertexIterator_Type) )
+
+/*---------------------------Python BPy_StrokeVertexIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ StrokeInternal::StrokeVertexIterator *sv_it;
+ int reversed;
+} BPy_StrokeVertexIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_STROKEVERTEXITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
new file mode 100644
index 00000000000..856cebb308c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp
@@ -0,0 +1,264 @@
+#include "BPy_ViewEdgeIterator.h"
+
+#include "../BPy_Convert.h"
+#include "../Interface1D/BPy_ViewEdge.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ViewEdgeIterator___doc__[] =
+"Base class for iterators over ViewEdges of the :class:`ViewMap` Graph.\n"
+"Basically the increment() operator of this class should be able to\n"
+"take the decision of \"where\" (on which ViewEdge) to go when pointing\n"
+"on a given ViewEdge.\n"
+"\n"
+".. method:: __init__(begin=None, orientation=True)\n"
+"\n"
+" Builds a ViewEdgeIterator from a starting ViewEdge and its\n"
+" orientation.\n"
+"\n"
+" :arg begin: The ViewEdge from where to start the iteration.\n"
+" :type begin: :class:`ViewEdge`\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n"
+"\n"
+".. method:: __init__(it)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg it: A ViewEdgeIterator object.\n"
+" :type it: :class:`ViewEdgeIterator`\n";
+
+static int ViewEdgeIterator___init__(BPy_ViewEdgeIterator *self, PyObject *args )
+{
+ PyObject *obj1 = 0, *obj2 = 0;
+
+ if (!( PyArg_ParseTuple(args, "O|O", &obj1, &obj2) ))
+ return -1;
+
+ if( obj1 && BPy_ViewEdgeIterator_Check(obj1) ) {
+ self->ve_it = new ViewEdgeInternal::ViewEdgeIterator(*( ((BPy_ViewEdgeIterator *) obj1)->ve_it ));
+
+ } else {
+ ViewEdge *begin;
+ if ( !obj1 || obj1 == Py_None )
+ begin = NULL;
+ else if ( BPy_ViewEdge_Check(obj1) )
+ begin = ((BPy_ViewEdge *) obj1)->ve;
+ else {
+ PyErr_SetString(PyExc_TypeError, "1st argument must be either a ViewEdge object or None");
+ return -1;
+ }
+ bool orientation = ( obj2 ) ? bool_from_PyBool(obj2) : true;
+
+ self->ve_it = new ViewEdgeInternal::ViewEdgeIterator( begin, orientation);
+
+ }
+
+ self->py_it.it = self->ve_it;
+
+ return 0;
+}
+
+static char ViewEdgeIterator_getCurrentEdge___doc__[] =
+".. method:: getCurrentEdge()\n"
+"\n"
+" Returns the current pointed ViewEdge.\n"
+"\n"
+" :return: The current pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_getCurrentEdge( BPy_ViewEdgeIterator *self ) {
+ ViewEdge *ve = self->ve_it->getCurrentEdge();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_setCurrentEdge___doc__[] =
+".. method:: setCurrentEdge(edge)\n"
+"\n"
+" Sets the current pointed ViewEdge.\n"
+"\n"
+" :arg edge: The current pointed ViewEdge.\n"
+" :type edge: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_setCurrentEdge( BPy_ViewEdgeIterator *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ self->ve_it->setCurrentEdge( ((BPy_ViewEdge *) py_ve)->ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_getBegin___doc__[] =
+".. method:: getBegin()\n"
+"\n"
+" Returns the first ViewEdge used for the iteration.\n"
+"\n"
+" :return: The first ViewEdge used for the iteration.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_getBegin( BPy_ViewEdgeIterator *self ) {
+ ViewEdge *ve = self->ve_it->getBegin();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_setBegin___doc__[] =
+".. method:: setBegin(begin)\n"
+"\n"
+" Sets the first ViewEdge used for the iteration.\n"
+"\n"
+" :arg begin: The first ViewEdge used for the iteration.\n"
+" :type begin: :class:`ViewEdge`\n";
+
+static PyObject *ViewEdgeIterator_setBegin( BPy_ViewEdgeIterator *self, PyObject *args ) {
+ PyObject *py_ve;
+
+ if(!( PyArg_ParseTuple(args, "O!", &ViewEdge_Type, &py_ve) ))
+ return NULL;
+
+ self->ve_it->setBegin( ((BPy_ViewEdge *) py_ve)->ve );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_getOrientation___doc__[] =
+".. method:: getOrientation()\n"
+"\n"
+" Returns the orientation of the pointed ViewEdge in the iteration.\n"
+"\n"
+" :return: The orientation of the pointed ViewEdge in the iteration.\n"
+" :rtype: bool\n";
+
+static PyObject *ViewEdgeIterator_getOrientation( BPy_ViewEdgeIterator *self ) {
+ return PyBool_from_bool( self->ve_it->getOrientation() );
+}
+
+static char ViewEdgeIterator_setOrientation___doc__[] =
+".. method:: setOrientation(orientation)\n"
+"\n"
+" Sets the orientation of the pointed ViewEdge in the iteration.\n"
+"\n"
+" :arg orientation: If true, we'll look for the next ViewEdge among\n"
+" the ViewEdges that surround the ending ViewVertex of begin. If\n"
+" false, we'll search over the ViewEdges surrounding the ending\n"
+" ViewVertex of begin.\n"
+" :type orientation: bool\n";
+
+static PyObject *ViewEdgeIterator_setOrientation( BPy_ViewEdgeIterator *self, PyObject *args ) {
+ PyObject *py_b;
+
+ if(!( PyArg_ParseTuple(args, "O", &py_b) ))
+ return NULL;
+
+ self->ve_it->setOrientation( bool_from_PyBool(py_b) );
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_changeOrientation___doc__[] =
+".. method:: changeOrientation()\n"
+"\n"
+" Changes the current orientation.\n";
+
+static PyObject *ViewEdgeIterator_changeOrientation( BPy_ViewEdgeIterator *self ) {
+ self->ve_it->changeOrientation();
+
+ Py_RETURN_NONE;
+}
+
+static char ViewEdgeIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed ViewEdge.\n"
+"\n"
+" :return: The pointed ViewEdge.\n"
+" :rtype: :class:`ViewEdge`\n";
+
+static PyObject * ViewEdgeIterator_getObject( BPy_ViewEdgeIterator *self) {
+
+ ViewEdge *ve = self->ve_it->operator*();
+ if( ve )
+ return BPy_ViewEdge_from_ViewEdge( *ve );
+
+ Py_RETURN_NONE;
+}
+
+/*----------------------ViewEdgeIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_ViewEdgeIterator_methods[] = {
+ {"getCurrentEdge", ( PyCFunction ) ViewEdgeIterator_getCurrentEdge, METH_NOARGS, ViewEdgeIterator_getCurrentEdge___doc__},
+ {"setCurrentEdge", ( PyCFunction ) ViewEdgeIterator_setCurrentEdge, METH_VARARGS, ViewEdgeIterator_setCurrentEdge___doc__},
+ {"getBegin", ( PyCFunction ) ViewEdgeIterator_getBegin, METH_NOARGS, ViewEdgeIterator_getBegin___doc__},
+ {"setBegin", ( PyCFunction ) ViewEdgeIterator_setBegin, METH_VARARGS, ViewEdgeIterator_setBegin___doc__},
+ {"getOrientation", ( PyCFunction ) ViewEdgeIterator_getOrientation, METH_NOARGS, ViewEdgeIterator_getOrientation___doc__},
+ {"setOrientation", ( PyCFunction ) ViewEdgeIterator_setOrientation, METH_VARARGS, ViewEdgeIterator_setOrientation___doc__},
+ {"changeOrientation", ( PyCFunction ) ViewEdgeIterator_changeOrientation, METH_NOARGS, ViewEdgeIterator_changeOrientation___doc__},
+ {"getObject", ( PyCFunction ) ViewEdgeIterator_getObject, METH_NOARGS, ViewEdgeIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_ViewEdgeIterator type definition ------------------------------*/
+
+PyTypeObject ViewEdgeIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ViewEdgeIterator", /* tp_name */
+ sizeof(BPy_ViewEdgeIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ViewEdgeIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_ViewEdgeIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ViewEdgeIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
new file mode 100644
index 00000000000..dce90efc8cf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h
@@ -0,0 +1,33 @@
+#ifndef FREESTYLE_PYTHON_VIEWEDGEITERATOR_H
+#define FREESTYLE_PYTHON_VIEWEDGEITERATOR_H
+
+
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ViewEdgeIterator_Type;
+
+#define BPy_ViewEdgeIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ViewEdgeIterator_Type) )
+
+/*---------------------------Python BPy_ViewEdgeIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewEdgeInternal::ViewEdgeIterator *ve_it;
+} BPy_ViewEdgeIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VIEWEDGEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
new file mode 100644
index 00000000000..c080426daa8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp
@@ -0,0 +1,138 @@
+#include "BPy_orientedViewEdgeIterator.h"
+
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char orientedViewEdgeIterator___doc__[] =
+"Class representing an iterator over oriented ViewEdges around a\n"
+":class:`ViewVertex`. This iterator allows a CCW iteration (in the image\n"
+"plane). An instance of an orientedViewEdgeIterator can only be\n"
+"obtained from a ViewVertex by calling edgesBegin() or edgesEnd().\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(iBrother)\n"
+"\n"
+" Copy constructor.\n"
+"\n"
+" :arg iBrother: An orientedViewEdgeIterator object.\n"
+" :type iBrother: :class:`orientedViewEdgeIterator`\n";
+
+static int orientedViewEdgeIterator___init__(BPy_orientedViewEdgeIterator *self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if (!( PyArg_ParseTuple(args, "|O", &obj) ))
+ return -1;
+
+ if( !obj )
+ self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator();
+ else if( BPy_orientedViewEdgeIterator_Check(obj) )
+ self->ove_it = new ViewVertexInternal::orientedViewEdgeIterator(*( ((BPy_orientedViewEdgeIterator *) obj)->ove_it ));
+ else {
+ PyErr_SetString(PyExc_TypeError, "invalid argument");
+ return -1;
+ }
+
+ self->py_it.it = self->ove_it;
+ self->reversed = 0;
+
+ return 0;
+}
+
+static PyObject * orientedViewEdgeIterator_iternext( BPy_orientedViewEdgeIterator *self ) {
+ ViewVertex::directedViewEdge *dve;
+ if (self->reversed) {
+ if (self->ove_it->isBegin()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ self->ove_it->decrement();
+ dve = self->ove_it->operator->();
+ } else {
+ if (self->ove_it->isEnd()) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+ dve = self->ove_it->operator->();
+ self->ove_it->increment();
+ }
+ return BPy_directedViewEdge_from_directedViewEdge( *dve );
+}
+
+static char orientedViewEdgeIterator_getObject___doc__[] =
+".. method:: getObject()\n"
+"\n"
+" Returns the pointed oriented ViewEdge.\n"
+"\n"
+" :return: A tuple of the pointed ViewEdge and a boolean value. If\n"
+" the boolean value is true, the ViewEdge is incoming.\n"
+" :rtype: (:class:`directedViewEdge`, bool)\n";
+
+static PyObject * orientedViewEdgeIterator_getObject( BPy_orientedViewEdgeIterator *self) {
+ return BPy_directedViewEdge_from_directedViewEdge( self->ove_it->operator*() );
+}
+
+/*----------------------orientedViewEdgeIterator instance definitions ----------------------------*/
+static PyMethodDef BPy_orientedViewEdgeIterator_methods[] = {
+ {"getObject", ( PyCFunction ) orientedViewEdgeIterator_getObject, METH_NOARGS, orientedViewEdgeIterator_getObject___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_orientedViewEdgeIterator type definition ------------------------------*/
+
+PyTypeObject orientedViewEdgeIterator_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "orientedViewEdgeIterator", /* tp_name */
+ sizeof(BPy_orientedViewEdgeIterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ orientedViewEdgeIterator___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)orientedViewEdgeIterator_iternext, /* tp_iternext */
+ BPy_orientedViewEdgeIterator_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &Iterator_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)orientedViewEdgeIterator___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h
new file mode 100644
index 00000000000..cd9edf1e224
--- /dev/null
+++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H
+#define FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H
+
+#include "../../stroke/Stroke.h"
+#include "../../view_map/ViewMapIterators.h"
+
+#include "../BPy_Iterator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject orientedViewEdgeIterator_Type;
+
+#define BPy_orientedViewEdgeIterator_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &orientedViewEdgeIterator_Type) )
+
+/*---------------------------Python BPy_orientedViewEdgeIterator structure definition----------*/
+typedef struct {
+ BPy_Iterator py_it;
+ ViewVertexInternal::orientedViewEdgeIterator *ove_it;
+ int reversed;
+} BPy_orientedViewEdgeIterator;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ORIENTEDVIEWEDGEITERATOR_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
new file mode 100644
index 00000000000..7ead138defb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp
@@ -0,0 +1,89 @@
+#include "BPy_BackboneStretcherShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BackboneStretcherShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iAmount=2.0)\n"
+"\n"
+" Builds a BackboneStretcherShader object.\n"
+"\n"
+" :arg iAmount: The stretching amount value.\n"
+" :type iAmount: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Stretches the stroke at its two extremities and following the\n"
+" respective directions: v(1)v(0) and v(n-1)v(n).\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int BackboneStretcherShader___init__( BPy_BackboneStretcherShader* self, PyObject *args)
+{
+ float f = 2.0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::BackboneStretcherShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_BackboneStretcherShader type definition ------------------------------*/
+
+PyTypeObject BackboneStretcherShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BackboneStretcherShader", /* tp_name */
+ sizeof(BPy_BackboneStretcherShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BackboneStretcherShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BackboneStretcherShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
new file mode 100644
index 00000000000..35a74c0bda2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H
+#define FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject BackboneStretcherShader_Type;
+
+#define BPy_BackboneStretcherShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BackboneStretcherShader_Type) )
+
+/*---------------------------Python BPy_BackboneStretcherShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_BackboneStretcherShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BACKBONESTRETCHERSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
new file mode 100644
index 00000000000..1ead40f4f6d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp
@@ -0,0 +1,91 @@
+#include "BPy_BezierCurveShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char BezierCurveShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(error=4.0)\n"
+"\n"
+" Builds a BezierCurveShader object.\n"
+"\n"
+" :arg error: The error we're allowing for the approximation. This\n"
+" error is the max distance allowed between the new curve and the\n"
+" original geometry.\n"
+" :type error: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Transforms the stroke backbone geometry so that it corresponds to a\n"
+" Bezier Curve approximation of the original backbone geometry.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int BezierCurveShader___init__( BPy_BezierCurveShader* self, PyObject *args)
+{
+ float f = 4.0;
+
+ if(!( PyArg_ParseTuple(args, "|f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::BezierCurveShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_BezierCurveShader type definition ------------------------------*/
+
+PyTypeObject BezierCurveShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "BezierCurveShader", /* tp_name */
+ sizeof(BPy_BezierCurveShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ BezierCurveShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)BezierCurveShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
new file mode 100644
index 00000000000..b94ef88acea
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_BEZIERCURVESHADER_H
+#define FREESTYLE_PYTHON_BEZIERCURVESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject BezierCurveShader_Type;
+
+#define BPy_BezierCurveShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &BezierCurveShader_Type) )
+
+/*---------------------------Python BPy_BezierCurveShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_BezierCurveShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_BEZIERCURVESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
new file mode 100644
index 00000000000..acb2569f83c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp
@@ -0,0 +1,111 @@
+#include "BPy_CalligraphicShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CalligraphicShader___doc__[] =
+"[Thickness Shader]\n"
+"\n"
+".. method:: __init__(iMinThickness, iMaxThickness, iOrientation, iClamp)\n"
+"\n"
+" Builds a CalligraphicShader object.\n"
+"\n"
+" :arg iMinThickness: The minimum thickness in the direction\n"
+" perpandicular to the main direction.\n"
+" :type iMinThickness: float\n"
+" :arg iMaxThickness: The maximum thickness in the main direction.\n"
+" :type iMaxThickness: float\n"
+" :arg iOrientation: The 2D vector giving the main direction.\n"
+" :type iOrientation: :class:`mathutils.Vector`\n"
+" :arg iClamp: If true, the strokes are drawn in black when the stroke\n"
+" direction is between -90 and 90 degrees with respect to the main\n"
+" direction and drawn in white otherwise. If false, the strokes\n"
+" are always drawn in black.\n"
+" :type iClamp: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns thicknesses to the stroke vertices so that the stroke looks\n"
+" like made with a calligraphic tool, i.e. the stroke will be the\n"
+" thickest in a main direction, and the thinest in the direction\n"
+" perpendicular to this one, and an interpolation inbetween.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int CalligraphicShader___init__( BPy_CalligraphicShader* self, PyObject *args)
+{
+ double d1, d2;
+ PyObject *obj3 = 0, *obj4 = 0;
+
+
+ if(!( PyArg_ParseTuple(args, "ddOO", &d1, &d2, &obj3, &obj4) ))
+ return -1;
+ Vec2f *v = Vec2f_ptr_from_PyObject(obj3);
+ if( !v ) {
+ PyErr_SetString(PyExc_TypeError, "argument 3 must be a 2D vector (either a list of 2 elements or Vector)");
+ return -1;
+ }
+ self->py_ss.ss = new CalligraphicShader(d1, d2, *v, bool_from_PyBool(obj4) );
+ delete v;
+
+ return 0;
+
+}
+
+/*-----------------------BPy_CalligraphicShader type definition ------------------------------*/
+
+PyTypeObject CalligraphicShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CalligraphicShader", /* tp_name */
+ sizeof(BPy_CalligraphicShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CalligraphicShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CalligraphicShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
new file mode 100644
index 00000000000..c573b0184ad
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H
+#define FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CalligraphicShader_Type;
+
+#define BPy_CalligraphicShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CalligraphicShader_Type)
+
+/*---------------------------Python BPy_CalligraphicShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_CalligraphicShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CALLIGRAPHICSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
new file mode 100644
index 00000000000..5293e449cf2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp
@@ -0,0 +1,90 @@
+#include "BPy_ColorNoiseShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ColorNoiseShader___doc__[] =
+"[Color shader]\n"
+"\n"
+".. method:: __init__(iAmplitude, iPeriod)\n"
+"\n"
+" Builds a ColorNoiseShader object.\n"
+"\n"
+" :arg iAmplitude: The amplitude of the noise signal.\n"
+" :type iAmplitude: float\n"
+" :arg iPeriod: The period of the noise signal.\n"
+" :type iPeriod: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Shader to add noise to the stroke colors.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ColorNoiseShader___init__( BPy_ColorNoiseShader* self, PyObject *args)
+{
+ float f1, f2;
+
+ if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ColorNoiseShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_ColorNoiseShader type definition ------------------------------*/
+
+PyTypeObject ColorNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ColorNoiseShader", /* tp_name */
+ sizeof(BPy_ColorNoiseShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ColorNoiseShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ColorNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
new file mode 100644
index 00000000000..694b847565e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_COLORNOISESHADER_H
+#define FREESTYLE_PYTHON_COLORNOISESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ColorNoiseShader_Type;
+
+#define BPy_ColorNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ColorNoiseShader_Type) )
+
+/*---------------------------Python BPy_ColorNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ColorNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_COLORNOISESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
new file mode 100644
index 00000000000..4e64e7d6c51
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.cpp
@@ -0,0 +1,96 @@
+#include "BPy_ColorVariationPatternShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ColorVariationPatternShader___doc__[] =
+"[Color shader]\n"
+"\n"
+".. method:: __init__(pattern_name, stretch=True)\n"
+"\n"
+" Builds a ColorVariationPatternShader object.\n"
+"\n"
+" :arg pattern_name: The file name of the texture file to use as\n"
+" pattern.\n"
+" :type pattern_name: string\n"
+" :arg stretch: Tells whether the texture must be strecthed or\n"
+" repeted to fit the stroke.\n"
+" :type stretch: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Applies a pattern to vary the original color. The new color is the\n"
+" result of the multiplication of the pattern and the original color.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ColorVariationPatternShader___init__( BPy_ColorVariationPatternShader* self, PyObject *args)
+{
+ const char *s;
+ PyObject *obj = 0;
+
+ if(!( PyArg_ParseTuple(args, "s|O", &s, &obj) ))
+ return -1;
+
+ bool b = (obj) ? bool_from_PyBool(obj) : true;
+ self->py_ss.ss = new StrokeShaders::ColorVariationPatternShader(s,b);
+ return 0;
+}
+
+/*-----------------------BPy_ColorVariationPatternShader type definition ------------------------------*/
+
+PyTypeObject ColorVariationPatternShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ColorVariationPatternShader", /* tp_name */
+ sizeof(BPy_ColorVariationPatternShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ColorVariationPatternShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ColorVariationPatternShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
new file mode 100644
index 00000000000..b1898ebfecf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorVariationPatternShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H
+#define FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ColorVariationPatternShader_Type;
+
+#define BPy_ColorVariationPatternShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ColorVariationPatternShader_Type) )
+
+/*---------------------------Python BPy_ColorVariationPatternShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ColorVariationPatternShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_COLORVARIATIONPATTERNSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
new file mode 100644
index 00000000000..2b21acabc42
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp
@@ -0,0 +1,94 @@
+#include "BPy_ConstantColorShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstantColorShader___doc__[] =
+"[Color shader]\n"
+"\n"
+".. method:: __init__(iR, iG, iB, iAlpha=1.0)\n"
+"\n"
+" Builds a ConstantColorShader object.\n"
+"\n"
+" :arg iR: The red component.\n"
+" :type iR: float\n"
+" :arg iG: The green component.\n"
+" :type iG: float\n"
+" :arg iB: The blue component.\n"
+" :type iB: float\n"
+" :arg iAlpha: The alpha value.\n"
+" :type iAlpha: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a constant color to every vertex of the Stroke.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ConstantColorShader___init__( BPy_ConstantColorShader* self, PyObject *args)
+{
+ float f1, f2, f3, f4 = 1.0;
+
+ if(!( PyArg_ParseTuple(args, "fff|f", &f1, &f2, &f3, &f4) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ConstantColorShader(f1, f2, f3, f4);
+ return 0;
+}
+
+/*-----------------------BPy_ConstantColorShader type definition ------------------------------*/
+
+PyTypeObject ConstantColorShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstantColorShader", /* tp_name */
+ sizeof(BPy_ConstantColorShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ConstantColorShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ConstantColorShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
new file mode 100644
index 00000000000..30a09d852fd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H
+#define FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstantColorShader_Type;
+
+#define BPy_ConstantColorShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstantColorShader_Type) )
+
+/*---------------------------Python BPy_ConstantColorShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstantColorShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONSTANTCOLORSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
new file mode 100644
index 00000000000..2db3685122f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp
@@ -0,0 +1,88 @@
+#include "BPy_ConstantThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstantThicknessShader___doc__[] =
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(thickness)\n"
+"\n"
+" Builds a ConstantThicknessShader object.\n"
+"\n"
+" :arg thickness: The thickness that must be assigned to the stroke.\n"
+" :type thickness: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns an absolute constant thickness to every vertex of the Stroke.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ConstantThicknessShader___init__( BPy_ConstantThicknessShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ConstantThicknessShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_ConstantThicknessShader type definition ------------------------------*/
+
+PyTypeObject ConstantThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstantThicknessShader", /* tp_name */
+ sizeof(BPy_ConstantThicknessShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ConstantThicknessShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ConstantThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
new file mode 100644
index 00000000000..bb7f3c0f622
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H
+#define FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstantThicknessShader_Type;
+
+#define BPy_ConstantThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstantThicknessShader_Type) )
+
+/*---------------------------Python BPy_ConstantThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstantThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONSTANTTHICKNESSSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
new file mode 100644
index 00000000000..6dacca246b3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp
@@ -0,0 +1,94 @@
+#include "BPy_ConstrainedIncreasingThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ConstrainedIncreasingThicknessShader___doc__[] =
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(iThicknessMin, iThicknessMax, iRatio)\n"
+"\n"
+" Builds a ConstrainedIncreasingThicknessShader object.\n"
+"\n"
+" :arg iThicknessMin: The minimum thickness.\n"
+" :type iThicknessMin: float\n"
+" :arg iThicknessMax: The maximum thickness.\n"
+" :type iThicknessMax: float\n"
+" :arg iRatio: The thickness/length ratio that we don't want to exceed. \n"
+" :type iRatio: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Same as the :class:`IncreasingThicknessShader`, but here we allow\n"
+" the user to control the thickness/length ratio so that we don't get\n"
+" fat short lines.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ConstrainedIncreasingThicknessShader___init__( BPy_ConstrainedIncreasingThicknessShader* self, PyObject *args)
+{
+ float f1, f2, f3;
+
+ if(!( PyArg_ParseTuple(args, "fff", &f1, &f2, &f3) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ConstrainedIncreasingThicknessShader(f1, f2, f3);
+ return 0;
+}
+
+/*-----------------------BPy_ConstrainedIncreasingThicknessShader type definition ------------------------------*/
+
+PyTypeObject ConstrainedIncreasingThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ConstrainedIncreasingThicknessShader", /* tp_name */
+ sizeof(BPy_ConstrainedIncreasingThicknessShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ConstrainedIncreasingThicknessShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ConstrainedIncreasingThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
new file mode 100644
index 00000000000..38a8aa2bfe0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H
+#define FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ConstrainedIncreasingThicknessShader_Type;
+
+#define BPy_ConstrainedIncreasingThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ConstrainedIncreasingThicknessShader_Type) )
+
+/*---------------------------Python BPy_ConstrainedIncreasingThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ConstrainedIncreasingThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_CONSTRAINEDINCREASINGTHICKNESSSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
new file mode 100644
index 00000000000..4be1358147a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp
@@ -0,0 +1,96 @@
+#include "BPy_GuidingLinesShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GuidingLinesShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iOffset)\n"
+"\n"
+" Builds a GuidingLinesShader object.\n"
+"\n"
+" :arg iOffset: The line that replaces the stroke is initially in the\n"
+" middle of the initial stroke bounding box. iOffset is the value\n"
+" of the displacement which is applied to this line along its\n"
+" normal.\n"
+" :type iOffset: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Shader to modify the Stroke geometry so that it corresponds to its\n"
+" main direction line. This shader must be used together with the\n"
+" splitting operator using the curvature criterion. Indeed, the\n"
+" precision of the approximation will depend on the size of the\n"
+" stroke's pieces. The bigger the pieces are, the rougher the\n"
+" approximation is.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int GuidingLinesShader___init__( BPy_GuidingLinesShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::GuidingLinesShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_GuidingLinesShader type definition ------------------------------*/
+
+PyTypeObject GuidingLinesShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GuidingLinesShader", /* tp_name */
+ sizeof(BPy_GuidingLinesShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GuidingLinesShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GuidingLinesShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
new file mode 100644
index 00000000000..e25704c33ba
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_GUIDINGLINESSHADER_H
+#define FREESTYLE_PYTHON_GUIDINGLINESSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GuidingLinesShader_Type;
+
+#define BPy_GuidingLinesShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GuidingLinesShader_Type) )
+
+/*---------------------------Python BPy_GuidingLinesShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_GuidingLinesShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_GUIDINGLINESSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
new file mode 100644
index 00000000000..892585bf842
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp
@@ -0,0 +1,104 @@
+#include "BPy_IncreasingColorShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncreasingColorShader___doc__[] =
+"[Color shader]\n"
+"\n"
+".. method:: __init__(iRm, iGm, iBm, iAlpham, iRM, iGM, iBM, iAlphaM)\n"
+"\n"
+" Builds an IncreasingColorShader object.\n"
+"\n"
+" :arg iRm: The first color red component.\n"
+" :type iRm: float\n"
+" :arg iGm: The first color green component.\n"
+" :type iGm: float\n"
+" :arg iBm: The first color blue component.\n"
+" :type iBm: float\n"
+" :arg iAlpham: The first color alpha value.\n"
+" :type iAlpham: float\n"
+" :arg iRM: The second color red component.\n"
+" :type iRM: float\n"
+" :arg iGM: The second color green component.\n"
+" :type iGM: float\n"
+" :arg iBM: The second color blue component.\n"
+" :type iBM: float\n"
+" :arg iAlphaM: The second color alpha value.\n"
+" :type iAlphaM: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a varying color to the stroke. The user specifies two\n"
+" colors A and B. The stroke color will change linearly from A to B\n"
+" between the first and the last vertex.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int IncreasingColorShader___init__( BPy_IncreasingColorShader* self, PyObject *args)
+{
+ float f1, f2, f3, f4, f5, f6, f7, f8;
+
+ if(!( PyArg_ParseTuple(args, "ffffffff", &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::IncreasingColorShader(f1, f2, f3, f4, f5, f6, f7, f8);
+ return 0;
+}
+
+/*-----------------------BPy_IncreasingColorShader type definition ------------------------------*/
+
+PyTypeObject IncreasingColorShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncreasingColorShader", /* tp_name */
+ sizeof(BPy_IncreasingColorShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ IncreasingColorShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncreasingColorShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
new file mode 100644
index 00000000000..9bc82e98098
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H
+#define FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncreasingColorShader_Type;
+
+#define BPy_IncreasingColorShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncreasingColorShader_Type) )
+
+/*---------------------------Python BPy_IncreasingColorShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_IncreasingColorShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_INCREASINGCOLORSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
new file mode 100644
index 00000000000..b5d067a4e44
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp
@@ -0,0 +1,94 @@
+#include "BPy_IncreasingThicknessShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncreasingThicknessShader___doc__[] =
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(iThicknessA, iThicknessB)\n"
+"\n"
+" Builds an IncreasingThicknessShader object.\n"
+"\n"
+" :arg iThicknessA: The first thickness value.\n"
+" :type iThicknessA: float\n"
+" :arg iThicknessB: The second thickness value.\n"
+" :type iThicknessB: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns thicknesses values such as the thickness increases from a\n"
+" thickness value A to a thickness value B between the first vertex\n"
+" to the midpoint vertex and then decreases from B to a A between\n"
+" this midpoint vertex and the last vertex. The thickness is\n"
+" linearly interpolated from A to B.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int IncreasingThicknessShader___init__( BPy_IncreasingThicknessShader* self, PyObject *args)
+{
+ float f1, f2;
+
+ if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::IncreasingThicknessShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_IncreasingThicknessShader type definition ------------------------------*/
+
+PyTypeObject IncreasingThicknessShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncreasingThicknessShader", /* tp_name */
+ sizeof(BPy_IncreasingThicknessShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ IncreasingThicknessShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncreasingThicknessShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
new file mode 100644
index 00000000000..33d883b1860
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H
+#define FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncreasingThicknessShader_Type;
+
+#define BPy_IncreasingThicknessShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncreasingThicknessShader_Type) )
+
+/*---------------------------Python BPy_IncreasingThicknessShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_IncreasingThicknessShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_INCREASINGTHICKNESSSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
new file mode 100644
index 00000000000..7c0c758a318
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp
@@ -0,0 +1,95 @@
+#include "BPy_PolygonalizationShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char PolygonalizationShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iError)\n"
+"\n"
+" Builds a PolygonalizationShader object.\n"
+"\n"
+" :arg iError: The error we want our polygonal approximation to have\n"
+" with respect to the original geometry. The smaller, the closer\n"
+" the new stroke is to the orinal one. This error corresponds to\n"
+" the maximum distance between the new stroke and the old one.\n"
+" :type iError: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Modifies the Stroke geometry so that it looks more \"polygonal\".\n"
+" The basic idea is to start from the minimal stroke approximation\n"
+" consisting in a line joining the first vertex to the last one and\n"
+" to subdivide using the original stroke vertices until a certain\n"
+" error is reached.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int PolygonalizationShader___init__( BPy_PolygonalizationShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::PolygonalizationShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_PolygonalizationShader type definition ------------------------------*/
+
+PyTypeObject PolygonalizationShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "PolygonalizationShader", /* tp_name */
+ sizeof(BPy_PolygonalizationShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ PolygonalizationShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)PolygonalizationShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
new file mode 100644
index 00000000000..85bcc00e869
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H
+#define FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject PolygonalizationShader_Type;
+
+#define BPy_PolygonalizationShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &PolygonalizationShader_Type) )
+
+/*---------------------------Python BPy_PolygonalizationShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_PolygonalizationShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_POLYGONALIZATIONSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
new file mode 100644
index 00000000000..1dacb1499e9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp
@@ -0,0 +1,88 @@
+#include "BPy_SamplingShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SamplingShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(sampling)\n"
+"\n"
+" Builds a SamplingShader object.\n"
+"\n"
+" :arg sampling: The sampling to use for the stroke resampling.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Resamples the stroke.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int SamplingShader___init__( BPy_SamplingShader* self, PyObject *args)
+{
+ float f;
+
+ if(!( PyArg_ParseTuple(args, "f", &f) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::SamplingShader(f);
+ return 0;
+}
+
+/*-----------------------BPy_SamplingShader type definition ------------------------------*/
+
+PyTypeObject SamplingShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SamplingShader", /* tp_name */
+ sizeof(BPy_SamplingShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SamplingShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SamplingShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
new file mode 100644
index 00000000000..dfc6efb3319
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_SAMPLINGSHADER_H
+#define FREESTYLE_PYTHON_SAMPLINGSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SamplingShader_Type;
+
+#define BPy_SamplingShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SamplingShader_Type) )
+
+/*---------------------------Python BPy_SamplingShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SamplingShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_SAMPLINGSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
new file mode 100644
index 00000000000..20be1575bb3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp
@@ -0,0 +1,106 @@
+#include "BPy_SmoothingShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SmoothingShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iNbIteration, iFactorPoint, ifactorCurvature, iFactorCurvatureDifference, iAnisoPoint, iAnisNormal, iAnisoCurvature, icarricatureFactor)\n"
+"\n"
+" Builds a SmoothingShader object.\n"
+"\n"
+" :arg iNbIteration: The number of iterations (400).\n"
+" :type iNbIteration: int\n"
+" :arg iFactorPoint: 0.0\n"
+" :type iFactorPoint: float\n"
+" :arg ifactorCurvature: 0.0\n"
+" :type ifactorCurvature: float\n"
+" :arg iFactorCurvatureDifference: 0.2\n"
+" :type iFactorCurvatureDifference: float\n"
+" :arg iAnisoPoint: \n"
+" :type iAnisoPoint: float\n"
+" :arg iAnisNormal: 0.0\n"
+" :type iAnisNormal: float\n"
+" :arg iAnisoCurvature: 0.0\n"
+" :type iAnisoCurvature: float\n"
+" :arg icarricatureFactor: 1.0\n"
+" :type icarricatureFactor: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Smoothes the stroke by moving the vertices to make the stroke\n"
+" smoother. Uses curvature flow to converge towards a curve of\n"
+" constant curvature. The diffusion method we use is anisotropic to\n"
+" prevent the diffusion accross corners.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int SmoothingShader___init__( BPy_SmoothingShader* self, PyObject *args)
+{
+ int i1;
+ double d2, d3, d4, d5, d6, d7, d8;
+
+ if(!( PyArg_ParseTuple(args, "iddddddd", &i1, &d2, &d3, &d4, &d5, &d6, &d7, &d8) ))
+ return -1;
+
+ self->py_ss.ss = new SmoothingShader(i1, d2, d3, d4, d5, d6, d7, d8);
+ return 0;
+}
+
+/*-----------------------BPy_SmoothingShader type definition ------------------------------*/
+
+PyTypeObject SmoothingShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SmoothingShader", /* tp_name */
+ sizeof(BPy_SmoothingShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SmoothingShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SmoothingShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
new file mode 100644
index 00000000000..18d6ca3cc30
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHONSMOOTHINGSHADER_H
+#define FREESTYLE_PYTHONSMOOTHINGSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SmoothingShader_Type;
+
+#define BPy_SmoothingShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SmoothingShader_Type) )
+
+/*---------------------------Python BPy_SmoothingShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SmoothingShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHONSMOOTHINGSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
new file mode 100644
index 00000000000..7df1d31a16d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp
@@ -0,0 +1,100 @@
+#include "BPy_SpatialNoiseShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char SpatialNoiseShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(iAmount, ixScale, nbOctave, smooth, pureRandom)\n"
+"\n"
+" Builds a SpatialNoiseShader object.\n"
+"\n"
+" :arg iAmount: The amplitude of the noise.\n"
+" :type iAmount: float\n"
+" :arg ixScale: The noise frequency.\n"
+" :type ixScale: float\n"
+" :arg nbOctave: The number of octaves\n"
+" :type nbOctave: int\n"
+" :arg smooth: True if you want the noise to be smooth.\n"
+" :type smooth: bool\n"
+" :arg pureRandom: True if you don't want any coherence.\n"
+" :type pureRandom: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Spatial Noise stroke shader. Moves the vertices to make the stroke\n"
+" more noisy.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int SpatialNoiseShader___init__( BPy_SpatialNoiseShader* self, PyObject *args)
+{
+ float f1, f2;
+ int i3;
+ PyObject *obj4 = 0, *obj5 = 0;
+
+ if(!( PyArg_ParseTuple(args, "ffiOO", &f1, &f2, &i3, &obj4, &obj5) ))
+ return -1;
+
+ self->py_ss.ss = new SpatialNoiseShader(f1, f2, i3, bool_from_PyBool(obj4), bool_from_PyBool(obj5) );
+ return 0;
+}
+
+/*-----------------------BPy_SpatialNoiseShader type definition ------------------------------*/
+
+PyTypeObject SpatialNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "SpatialNoiseShader", /* tp_name */
+ sizeof(BPy_SpatialNoiseShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ SpatialNoiseShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)SpatialNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
new file mode 100644
index 00000000000..46e1c12385d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_SPATIALNOISESHADER_H
+#define FREESTYLE_PYTHON_SPATIALNOISESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject SpatialNoiseShader_Type;
+
+#define BPy_SpatialNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &SpatialNoiseShader_Type) )
+
+/*---------------------------Python BPy_SpatialNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_SpatialNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_SPATIALNOISESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
new file mode 100644
index 00000000000..ed42a64eed0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.cpp
@@ -0,0 +1,115 @@
+#include "BPy_StrokeTextureShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+#include "../BPy_Convert.h"
+#include "../BPy_MediumType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char StrokeTextureShader___doc__[] =
+"[Texture shader]\n"
+"\n"
+".. method:: __init__(textureFile, mediumType=MediumType.OPAQUE_MEDIUM, iTips=False)\n"
+"\n"
+" Builds a StrokeTextureShader object.\n"
+"\n"
+" :arg textureFile: \n"
+" :type textureFile: string\n"
+" :arg mediumType: The medium type and therefore, the blending mode\n"
+" that must be used for the rendering of this stroke.\n"
+" :type mediumType: :class:`MediumType`\n"
+" :arg iTips: Tells whether the texture includes tips or not. If it\n"
+" is the case, the texture image must respect the following format.\n"
+" :type iTips: bool\n"
+"\n"
+" The format of a texture image including tips::\n"
+"\n"
+" ___________\n"
+" | |\n"
+" | A |\n"
+" |___________|\n"
+" | | |\n"
+" | B | C |\n"
+" |_____|_____|\n"
+"\n"
+" * A : The stroke's corpus texture.\n"
+" * B : The stroke's left extremity texture.\n"
+" * C : The stroke's right extremity texture.\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a texture and a blending mode to the stroke in order to\n"
+" simulate its marks system.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int StrokeTextureShader___init__( BPy_StrokeTextureShader* self, PyObject *args)
+{
+ const char *s1;
+ PyObject *obj2 = 0, *obj3 = 0;
+
+ if(!( PyArg_ParseTuple(args, "s|O!O", &s1, &MediumType_Type, &obj2, &obj3) ))
+ return -1;
+
+ Stroke::MediumType mt = (obj2) ? MediumType_from_BPy_MediumType(obj2) : Stroke::OPAQUE_MEDIUM;
+ bool b = (obj3) ? bool_from_PyBool(obj3) : true;
+
+ self->py_ss.ss = new StrokeShaders::StrokeTextureShader(s1,mt,b);
+ return 0;
+}
+
+/*-----------------------BPy_StrokeTextureShader type definition ------------------------------*/
+
+PyTypeObject StrokeTextureShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "StrokeTextureShader", /* tp_name */
+ sizeof(BPy_StrokeTextureShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ StrokeTextureShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)StrokeTextureShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
new file mode 100644
index 00000000000..c65506f2f14
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STROKETEXTURESHADER_H
+#define FREESTYLE_PYTHON_STROKETEXTURESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject StrokeTextureShader_Type;
+
+#define BPy_StrokeTextureShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &StrokeTextureShader_Type) )
+
+/*---------------------------Python BPy_StrokeTextureShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_StrokeTextureShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_STROKETEXTURESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
new file mode 100644
index 00000000000..4df76f6646b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.cpp
@@ -0,0 +1,104 @@
+#include "BPy_TextureAssignerShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TextureAssignerShader___doc__[] =
+"[Texture shader]\n"
+"\n"
+".. method:: __init__(id)\n"
+"\n"
+" Builds a TextureAssignerShader object.\n"
+"\n"
+" :arg id: The preset number to use.\n"
+" :type id: int\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Assigns a texture to the stroke in order to simulate its marks\n"
+" system. This shader takes as input an integer value telling which\n"
+" texture and blending mode to use among a set of predefined\n"
+" textures. Here are the different presets:\n"
+"\n"
+" * 0: `/brushes/charcoalAlpha.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 1: `/brushes/washbrushAlpha.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 2: `/brushes/oil.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 3: `/brushes/oilnoblend.bmp`, `MediumType.HUMID_MEDIUM`\n"
+" * 4: `/brushes/charcoalAlpha.bmp`, `MediumType.DRY_MEDIUM`\n"
+" * 5: `/brushes/washbrushAlpha.bmp`, `MediumType.DRY_MEDIUM`\n"
+" * 6: `/brushes/opaqueDryBrushAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n"
+" * 7: `/brushes/opaqueBrushAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n"
+"\n"
+" Any other value will lead to the following preset:\n"
+"\n"
+" * Default: `/brushes/smoothAlpha.bmp`, `MediumType.OPAQUE_MEDIUM`\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int TextureAssignerShader___init__( BPy_TextureAssignerShader* self, PyObject *args)
+{
+ int i;
+
+ if(!( PyArg_ParseTuple(args, "i", &i) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::TextureAssignerShader(i);
+ return 0;
+}
+
+/*-----------------------BPy_TextureAssignerShader type definition ------------------------------*/
+
+PyTypeObject TextureAssignerShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TextureAssignerShader", /* tp_name */
+ sizeof(BPy_TextureAssignerShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TextureAssignerShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TextureAssignerShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
new file mode 100644
index 00000000000..9cffc1c1662
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TextureAssignerShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H
+#define FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TextureAssignerShader_Type;
+
+#define BPy_TextureAssignerShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TextureAssignerShader_Type) )
+
+/*---------------------------Python BPy_TextureAssignerShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_TextureAssignerShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_TEXTUREASSIGNERSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
new file mode 100644
index 00000000000..c880f05ed7b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp
@@ -0,0 +1,90 @@
+#include "BPy_ThicknessNoiseShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ThicknessNoiseShader___doc__[] =
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(iAmplitude, iPeriod)\n"
+"\n"
+" Builds a ThicknessNoiseShader object.\n"
+"\n"
+" :arg iAmplitude: The amplitude of the noise signal.\n"
+" :type iAmplitude: float\n"
+" :arg iPeriod: The period of the noise signal.\n"
+" :type iPeriod: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Adds some noise to the stroke thickness.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ThicknessNoiseShader___init__( BPy_ThicknessNoiseShader* self, PyObject *args)
+{
+ float f1, f2;
+
+ if(!( PyArg_ParseTuple(args, "ff", &f1, &f2) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::ThicknessNoiseShader(f1, f2);
+ return 0;
+}
+
+/*-----------------------BPy_ThicknessNoiseShader type definition ------------------------------*/
+
+PyTypeObject ThicknessNoiseShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ThicknessNoiseShader", /* tp_name */
+ sizeof(BPy_ThicknessNoiseShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ThicknessNoiseShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ThicknessNoiseShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
new file mode 100644
index 00000000000..c3ef101683e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_THICKNESSNOISESHADER_H
+#define FREESTYLE_PYTHON_THICKNESSNOISESHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ThicknessNoiseShader_Type;
+
+#define BPy_ThicknessNoiseShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ThicknessNoiseShader_Type) )
+
+/*---------------------------Python BPy_ThicknessNoiseShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ThicknessNoiseShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_THICKNESSNOISESHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
new file mode 100644
index 00000000000..f9472ae3444
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.cpp
@@ -0,0 +1,101 @@
+#include "BPy_ThicknessVariationPatternShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+#include "../BPy_Convert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ThicknessVariationPatternShader___doc__[] =
+"[Thickness shader]\n"
+"\n"
+".. method:: __init__(pattern_name, iMinThickness, iMaxThickness, stretch)\n"
+"\n"
+" Builds a ThicknessVariationPatternShader object.\n"
+"\n"
+" :arg pattern_name: The texture file name.\n"
+" :type pattern_name: string\n"
+" :arg iMinThickness: The minimum thickness we don't want to exceed.\n"
+" :type iMinThickness: float\n"
+" :arg iMaxThickness: The maximum thickness we don't want to exceed.\n"
+" :type iMaxThickness: float\n"
+" :arg stretch: Tells whether the pattern texture must be stretched\n"
+" or repeted to fit the stroke.\n"
+" :type stretch: bool\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Applies a pattern (texture) to vary thickness. The new thicknesses\n"
+" are the result of the multiplication of the pattern and the\n"
+" original thickness.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int ThicknessVariationPatternShader___init__( BPy_ThicknessVariationPatternShader* self, PyObject *args)
+{
+ const char *s1;
+ float f2 = 1.0, f3 = 5.0;
+ PyObject *obj4 = 0;
+
+ if(!( PyArg_ParseTuple(args, "s|ffO", &s1, &f2, &f3, &obj4) ))
+ return -1;
+
+ bool b = (obj4) ? bool_from_PyBool(obj4) : true;
+ self->py_ss.ss = new StrokeShaders::ThicknessVariationPatternShader(s1, f2, f3, b);
+ return 0;
+}
+
+/*-----------------------BPy_ThicknessVariationPatternShader type definition ------------------------------*/
+
+PyTypeObject ThicknessVariationPatternShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ThicknessVariationPatternShader", /* tp_name */
+ sizeof(BPy_ThicknessVariationPatternShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ThicknessVariationPatternShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ThicknessVariationPatternShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
new file mode 100644
index 00000000000..302c9e005ae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessVariationPatternShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H
+#define FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ThicknessVariationPatternShader_Type;
+
+#define BPy_ThicknessVariationPatternShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ThicknessVariationPatternShader_Type) )
+
+/*---------------------------Python BPy_ThicknessVariationPatternShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_ThicknessVariationPatternShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_THICKNESSVARIATIONPATTERNSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
new file mode 100644
index 00000000000..ec90499a49b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp
@@ -0,0 +1,89 @@
+#include "BPy_TipRemoverShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TipRemoverShader___doc__[] =
+"[Geometry shader]\n"
+"\n"
+".. method:: __init__(tipLength)\n"
+"\n"
+" Builds a TipRemoverShader object.\n"
+"\n"
+" :arg tipLength: The length of the piece of stroke we want to remove\n"
+" at each extremity.\n"
+" :type tipLength: float\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Removes the stroke's extremities.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int TipRemoverShader___init__( BPy_TipRemoverShader* self, PyObject *args)
+{
+ double d;
+
+ if(!( PyArg_ParseTuple(args, "d", &d) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::TipRemoverShader(d);
+ return 0;
+}
+
+/*-----------------------BPy_TipRemoverShader type definition ------------------------------*/
+
+PyTypeObject TipRemoverShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TipRemoverShader", /* tp_name */
+ sizeof(BPy_TipRemoverShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TipRemoverShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TipRemoverShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
new file mode 100644
index 00000000000..a1b2e3988bc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_TIPREMOVERSHADER_H
+#define FREESTYLE_PYTHON_TIPREMOVERSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TipRemoverShader_Type;
+
+#define BPy_TipRemoverShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TipRemoverShader_Type) )
+
+/*---------------------------Python BPy_TipRemoverShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_TipRemoverShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_TIPREMOVERSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
new file mode 100644
index 00000000000..03881533ef6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.cpp
@@ -0,0 +1,88 @@
+#include "BPy_fstreamShader.h"
+
+#include "../../stroke/AdvancedStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char fstreamShader___doc__[] =
+"[Output shader]\n"
+"\n"
+".. method:: __init__(iFileName)\n"
+"\n"
+" Builds a fstreamShader object.\n"
+"\n"
+" :arg iFileName: The output file name.\n"
+" :type iFileName: string\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Streams the Stroke in a file.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int fstreamShader___init__( BPy_fstreamShader* self, PyObject *args)
+{
+ const char *s;
+
+ if(!( PyArg_ParseTuple(args, "s", &s) ))
+ return -1;
+
+ self->py_ss.ss = new StrokeShaders::fstreamShader(s);
+ return 0;
+}
+
+/*-----------------------BPy_fstreamShader type definition ------------------------------*/
+
+PyTypeObject fstreamShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "fstreamShader", /* tp_name */
+ sizeof(BPy_fstreamShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ fstreamShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)fstreamShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
new file mode 100644
index 00000000000..843d50505db
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_fstreamShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_FSTREAMSHADER_H
+#define FREESTYLE_PYTHON_FSTREAMSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject fstreamShader_Type;
+
+#define BPy_fstreamShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &fstreamShader_Type) )
+
+/*---------------------------Python BPy_fstreamShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_fstreamShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_FSTREAMSHADER_H */
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
new file mode 100644
index 00000000000..31e0971b875
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.cpp
@@ -0,0 +1,82 @@
+#include "BPy_streamShader.h"
+
+#include "../../stroke/BasicStrokeShaders.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char streamShader___doc__[] =
+"[Output shader]\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Builds a streamShader object.\n"
+"\n"
+".. method:: shade(s)\n"
+"\n"
+" Streams the Stroke into stdout.\n"
+"\n"
+" :arg s: A Stroke object.\n"
+" :type s: :class:`Stroke`\n";
+
+static int streamShader___init__( BPy_streamShader* self, PyObject *args)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_ss.ss = new StrokeShaders::streamShader();
+ return 0;
+}
+
+/*-----------------------BPy_streamShader type definition ------------------------------*/
+
+PyTypeObject streamShader_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "streamShader", /* tp_name */
+ sizeof(BPy_streamShader), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ streamShader___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &StrokeShader_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)streamShader___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
new file mode 100644
index 00000000000..38056d5fa59
--- /dev/null
+++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_streamShader.h
@@ -0,0 +1,31 @@
+#ifndef FREESTYLE_PYTHON_STREAMSHADER_H
+#define FREESTYLE_PYTHON_STREAMSHADER_H
+
+#include "../BPy_StrokeShader.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject streamShader_Type;
+
+#define BPy_streamShader_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &streamShader_Type) )
+
+/*---------------------------Python BPy_streamShader structure definition----------*/
+typedef struct {
+ BPy_StrokeShader py_ss;
+} BPy_streamShader;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* FREESTYLE_PYTHON_STREAMSHADER_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
new file mode 100644
index 00000000000..a6810d0a7c5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp
@@ -0,0 +1,213 @@
+#include "BPy_UnaryFunction0DDouble.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h"
+#include "UnaryFunction0D_double/BPy_DensityF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedXF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedYF0D.h"
+#include "UnaryFunction0D_double/BPy_GetProjectedZF0D.h"
+#include "UnaryFunction0D_double/BPy_GetXF0D.h"
+#include "UnaryFunction0D_double/BPy_GetYF0D.h"
+#include "UnaryFunction0D_double/BPy_GetZF0D.h"
+#include "UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h"
+#include "UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h"
+
+#include "../Director.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DDouble_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DDouble_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DDouble_Type );
+ PyModule_AddObject(module, "UnaryFunction0DDouble", (PyObject *)&UnaryFunction0DDouble_Type);
+
+ if( PyType_Ready( &DensityF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &DensityF0D_Type );
+ PyModule_AddObject(module, "DensityF0D", (PyObject *)&DensityF0D_Type);
+
+ if( PyType_Ready( &LocalAverageDepthF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &LocalAverageDepthF0D_Type );
+ PyModule_AddObject(module, "LocalAverageDepthF0D", (PyObject *)&LocalAverageDepthF0D_Type);
+
+ if( PyType_Ready( &Curvature2DAngleF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Curvature2DAngleF0D_Type );
+ PyModule_AddObject(module, "Curvature2DAngleF0D", (PyObject *)&Curvature2DAngleF0D_Type);
+
+ if( PyType_Ready( &GetProjectedXF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedXF0D_Type );
+ PyModule_AddObject(module, "GetProjectedXF0D", (PyObject *)&GetProjectedXF0D_Type);
+
+ if( PyType_Ready( &GetProjectedYF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedYF0D_Type );
+ PyModule_AddObject(module, "GetProjectedYF0D", (PyObject *)&GetProjectedYF0D_Type);
+
+ if( PyType_Ready( &GetProjectedZF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedZF0D_Type );
+ PyModule_AddObject(module, "GetProjectedZF0D", (PyObject *)&GetProjectedZF0D_Type);
+
+ if( PyType_Ready( &GetXF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetXF0D_Type );
+ PyModule_AddObject(module, "GetXF0D", (PyObject *)&GetXF0D_Type);
+
+ if( PyType_Ready( &GetYF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetYF0D_Type );
+ PyModule_AddObject(module, "GetYF0D", (PyObject *)&GetYF0D_Type);
+
+ if( PyType_Ready( &GetZF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetZF0D_Type );
+ PyModule_AddObject(module, "GetZF0D", (PyObject *)&GetZF0D_Type);
+
+ if( PyType_Ready( &ZDiscontinuityF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ZDiscontinuityF0D_Type );
+ PyModule_AddObject(module, "ZDiscontinuityF0D", (PyObject *)&ZDiscontinuityF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DDouble___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DDouble___init__(BPy_UnaryFunction0DDouble* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_double = new UnaryFunction0D<double>();
+ self->uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DDouble___dealloc__(BPy_UnaryFunction0DDouble* self)
+{
+ if (self->uf0D_double)
+ delete self->uf0D_double;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DDouble___repr__(BPy_UnaryFunction0DDouble* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_double->getName().c_str(), self->uf0D_double );
+}
+
+static char UnaryFunction0DDouble_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DDouble_getName( BPy_UnaryFunction0DDouble *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_double->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DDouble___call__( BPy_UnaryFunction0DDouble *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_double)) == typeid(UnaryFunction0D<double>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_double->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it)) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_double->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf0D_double->result );
+
+}
+
+/*----------------------UnaryFunction0DDouble instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DDouble_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DDouble_getName, METH_NOARGS, UnaryFunction0DDouble_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DDouble type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DDouble_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DDouble", /* tp_name */
+ sizeof(BPy_UnaryFunction0DDouble), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DDouble___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DDouble___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DDouble___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DDouble___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DDouble_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DDouble___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
new file mode 100644
index 00000000000..dbeb70cc082
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DDouble_Type;
+
+#define BPy_UnaryFunction0DDouble_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DDouble_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DDouble structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<double> *uf0D_double;
+} BPy_UnaryFunction0DDouble;
+
+/*---------------------------Python BPy_UnaryFunction0DDouble visible prototypes-----------*/
+int UnaryFunction0DDouble_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DDOUBLE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
new file mode 100644
index 00000000000..aa2ae5e36b5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp
@@ -0,0 +1,157 @@
+#include "BPy_UnaryFunction0DEdgeNature.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DEdgeNature_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DEdgeNature_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DEdgeNature_Type );
+ PyModule_AddObject(module, "UnaryFunction0DEdgeNature", (PyObject *)&UnaryFunction0DEdgeNature_Type);
+
+ if( PyType_Ready( &CurveNatureF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurveNatureF0D_Type );
+ PyModule_AddObject(module, "CurveNatureF0D", (PyObject *)&CurveNatureF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DEdgeNature___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`Nature` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DEdgeNature___init__(BPy_UnaryFunction0DEdgeNature* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_edgenature = new UnaryFunction0D<Nature::EdgeNature>();
+ self->uf0D_edgenature->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DEdgeNature___dealloc__(BPy_UnaryFunction0DEdgeNature* self)
+{
+ if (self->uf0D_edgenature)
+ delete self->uf0D_edgenature;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DEdgeNature___repr__(BPy_UnaryFunction0DEdgeNature* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_edgenature->getName().c_str(), self->uf0D_edgenature );
+}
+
+static char UnaryFunction0DEdgeNature_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DEdgeNature_getName( BPy_UnaryFunction0DEdgeNature *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_edgenature->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DEdgeNature___call__( BPy_UnaryFunction0DEdgeNature *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_edgenature)) == typeid(UnaryFunction0D<Nature::EdgeNature>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_edgenature->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_edgenature->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_Nature_from_Nature( self->uf0D_edgenature->result );
+
+}
+
+/*----------------------UnaryFunction0DEdgeNature instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DEdgeNature_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DEdgeNature_getName, METH_NOARGS, UnaryFunction0DEdgeNature_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DEdgeNature type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DEdgeNature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DEdgeNature", /* tp_name */
+ sizeof(BPy_UnaryFunction0DEdgeNature), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DEdgeNature___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DEdgeNature___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DEdgeNature___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DEdgeNature___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DEdgeNature_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DEdgeNature___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h
new file mode 100644
index 00000000000..d6959cae57f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DEdgeNature_Type;
+
+#define BPy_UnaryFunction0DEdgeNature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DEdgeNature_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DEdgeNature structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Nature::EdgeNature> *uf0D_edgenature;
+} BPy_UnaryFunction0DEdgeNature;
+
+/*---------------------------Python BPy_UnaryFunction0DEdgeNature visible prototypes-----------*/
+int UnaryFunction0DEdgeNature_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DEDGENATURE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
new file mode 100644
index 00000000000..ade1082cf64
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp
@@ -0,0 +1,187 @@
+#include "BPy_UnaryFunction0DFloat.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h"
+#include "UnaryFunction0D_float/BPy_GetParameterF0D.h"
+#include "UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadMapPixelF0D.h"
+#include "UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DFloat_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DFloat_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DFloat_Type );
+ PyModule_AddObject(module, "UnaryFunction0DFloat", (PyObject *)&UnaryFunction0DFloat_Type);
+
+ if( PyType_Ready( &GetCurvilinearAbscissaF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetCurvilinearAbscissaF0D_Type );
+ PyModule_AddObject(module, "GetCurvilinearAbscissaF0D", (PyObject *)&GetCurvilinearAbscissaF0D_Type);
+
+ if( PyType_Ready( &GetParameterF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetParameterF0D_Type );
+ PyModule_AddObject(module, "GetParameterF0D", (PyObject *)&GetParameterF0D_Type);
+
+ if( PyType_Ready( &GetViewMapGradientNormF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetViewMapGradientNormF0D_Type );
+ PyModule_AddObject(module, "GetViewMapGradientNormF0D", (PyObject *)&GetViewMapGradientNormF0D_Type);
+
+ if( PyType_Ready( &ReadCompleteViewMapPixelF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ReadCompleteViewMapPixelF0D_Type );
+ PyModule_AddObject(module, "ReadCompleteViewMapPixelF0D", (PyObject *)&ReadCompleteViewMapPixelF0D_Type);
+
+ if( PyType_Ready( &ReadMapPixelF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ReadMapPixelF0D_Type );
+ PyModule_AddObject(module, "ReadMapPixelF0D", (PyObject *)&ReadMapPixelF0D_Type);
+
+ if( PyType_Ready( &ReadSteerableViewMapPixelF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ReadSteerableViewMapPixelF0D_Type );
+ PyModule_AddObject(module, "ReadSteerableViewMapPixelF0D", (PyObject *)&ReadSteerableViewMapPixelF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DFloat___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DFloat___init__(BPy_UnaryFunction0DFloat* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_float = new UnaryFunction0D<float>();
+ self->uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DFloat___dealloc__(BPy_UnaryFunction0DFloat* self)
+{
+ if (self->uf0D_float)
+ delete self->uf0D_float;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DFloat___repr__(BPy_UnaryFunction0DFloat* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_float->getName().c_str(), self->uf0D_float );
+}
+
+static char UnaryFunction0DFloat_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DFloat_getName( BPy_UnaryFunction0DFloat *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_float->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DFloat___call__( BPy_UnaryFunction0DFloat *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_float)) == typeid(UnaryFunction0D<float>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_float->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_float->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf0D_float->result );
+
+}
+
+/*----------------------UnaryFunction0DFloat instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DFloat_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DFloat_getName, METH_NOARGS, UnaryFunction0DFloat_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DFloat type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DFloat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DFloat", /* tp_name */
+ sizeof(BPy_UnaryFunction0DFloat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DFloat___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DFloat___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DFloat___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DFloat___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DFloat_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DFloat___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
new file mode 100644
index 00000000000..fbf207d48c7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DFloat_Type;
+
+#define BPy_UnaryFunction0DFloat_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DFloat_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DFloat structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<float> *uf0D_float;
+} BPy_UnaryFunction0DFloat;
+
+/*---------------------------Python BPy_UnaryFunction0DFloat visible prototypes-----------*/
+int UnaryFunction0DFloat_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DFLOAT_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
new file mode 100644
index 00000000000..a29eabcc063
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp
@@ -0,0 +1,156 @@
+#include "BPy_UnaryFunction0DId.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Id/BPy_ShapeIdF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DId_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DId_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DId_Type );
+ PyModule_AddObject(module, "UnaryFunction0DId", (PyObject *)&UnaryFunction0DId_Type);
+
+ if( PyType_Ready( &ShapeIdF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ShapeIdF0D_Type );
+ PyModule_AddObject(module, "ShapeIdF0D", (PyObject *)&ShapeIdF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DId___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return an :class:`Id` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DId___init__(BPy_UnaryFunction0DId* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_id = new UnaryFunction0D<Id>();
+ self->uf0D_id->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DId___dealloc__(BPy_UnaryFunction0DId* self)
+{
+ if (self->uf0D_id)
+ delete self->uf0D_id;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DId___repr__(BPy_UnaryFunction0DId* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_id->getName().c_str(), self->uf0D_id );
+}
+
+static char UnaryFunction0DId_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DId_getName( BPy_UnaryFunction0DId *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_id->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DId___call__( BPy_UnaryFunction0DId *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_id)) == typeid(UnaryFunction0D<Id>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_id->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_id->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_Id_from_Id( self->uf0D_id->result );
+}
+
+/*----------------------UnaryFunction0DId instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DId_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DId_getName, METH_NOARGS, UnaryFunction0DId_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DId type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DId_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DId", /* tp_name */
+ sizeof(BPy_UnaryFunction0DId), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DId___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DId___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DId___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DId___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DId_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DId___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h
new file mode 100644
index 00000000000..159e24e2674
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DID_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DID_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../system/Id.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DId_Type;
+
+#define BPy_UnaryFunction0DId_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DId_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DId structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Id> *uf0D_id;
+} BPy_UnaryFunction0DId;
+
+/*---------------------------Python BPy_UnaryFunction0DId visible prototypes-----------*/
+int UnaryFunction0DId_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DID_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
new file mode 100644
index 00000000000..d7518b107a6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp
@@ -0,0 +1,158 @@
+#include "BPy_UnaryFunction0DMaterial.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Material/BPy_MaterialF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DMaterial_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DMaterial_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DMaterial_Type );
+ PyModule_AddObject(module, "UnaryFunction0DMaterial", (PyObject *)&UnaryFunction0DMaterial_Type);
+
+ if( PyType_Ready( &MaterialF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &MaterialF0D_Type );
+ PyModule_AddObject(module, "MaterialF0D", (PyObject *)&MaterialF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DMaterial___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`FrsMaterial` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DMaterial___init__(BPy_UnaryFunction0DMaterial* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_material = new UnaryFunction0D<FrsMaterial>();
+ self->uf0D_material->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DMaterial___dealloc__(BPy_UnaryFunction0DMaterial* self)
+{
+ if (self->uf0D_material)
+ delete self->uf0D_material;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+
+static PyObject * UnaryFunction0DMaterial___repr__(BPy_UnaryFunction0DMaterial* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_material->getName().c_str(), self->uf0D_material );
+}
+
+static char UnaryFunction0DMaterial_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DMaterial_getName( BPy_UnaryFunction0DMaterial *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_material->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DMaterial___call__( BPy_UnaryFunction0DMaterial *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_material)) == typeid(UnaryFunction0D<FrsMaterial>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_material->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_material->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_FrsMaterial_from_FrsMaterial( self->uf0D_material->result );
+
+}
+
+/*----------------------UnaryFunction0DMaterial instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DMaterial_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DMaterial_getName, METH_NOARGS, UnaryFunction0DMaterial_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DMaterial type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DMaterial_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DMaterial", /* tp_name */
+ sizeof(BPy_UnaryFunction0DMaterial), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DMaterial___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DMaterial___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DMaterial___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DMaterial___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DMaterial_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DMaterial___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h
new file mode 100644
index 00000000000..02fb2b99ccd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../scene_graph/FrsMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DMaterial_Type;
+
+#define BPy_UnaryFunction0DMaterial_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DMaterial_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DMaterial structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<FrsMaterial> *uf0D_material;
+} BPy_UnaryFunction0DMaterial;
+
+/*---------------------------Python BPy_UnaryFunction0DMaterial visible prototypes-----------*/
+int UnaryFunction0DMaterial_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DMATERIAL_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
new file mode 100644
index 00000000000..ddf42e7851d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp
@@ -0,0 +1,157 @@
+#include "BPy_UnaryFunction0DUnsigned.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DUnsigned_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DUnsigned_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DUnsigned_Type );
+ PyModule_AddObject(module, "UnaryFunction0DUnsigned", (PyObject *)&UnaryFunction0DUnsigned_Type);
+
+ if( PyType_Ready( &QuantitativeInvisibilityF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &QuantitativeInvisibilityF0D_Type );
+ PyModule_AddObject(module, "QuantitativeInvisibilityF0D", (PyObject *)&QuantitativeInvisibilityF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DUnsigned___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return an int value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+ " Default constructor.\n";
+
+static int UnaryFunction0DUnsigned___init__(BPy_UnaryFunction0DUnsigned* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_unsigned = new UnaryFunction0D<unsigned int>();
+ self->uf0D_unsigned->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DUnsigned___dealloc__(BPy_UnaryFunction0DUnsigned* self)
+{
+ if (self->uf0D_unsigned)
+ delete self->uf0D_unsigned;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DUnsigned___repr__(BPy_UnaryFunction0DUnsigned* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_unsigned->getName().c_str(), self->uf0D_unsigned );
+}
+
+static char UnaryFunction0DUnsigned_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DUnsigned_getName( BPy_UnaryFunction0DUnsigned *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_unsigned->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DUnsigned___call__( BPy_UnaryFunction0DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_unsigned)) == typeid(UnaryFunction0D<unsigned int>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_unsigned->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_unsigned->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyLong_FromLong( self->uf0D_unsigned->result );
+
+}
+
+/*----------------------UnaryFunction0DUnsigned instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DUnsigned_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DUnsigned_getName, METH_NOARGS, UnaryFunction0DUnsigned_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DUnsigned type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DUnsigned_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DUnsigned", /* tp_name */
+ sizeof(BPy_UnaryFunction0DUnsigned), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DUnsigned___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DUnsigned___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DUnsigned___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DUnsigned___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DUnsigned_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DUnsigned___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h
new file mode 100644
index 00000000000..4776ce30918
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DUnsigned_Type;
+
+#define BPy_UnaryFunction0DUnsigned_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DUnsigned_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DUnsigned structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<unsigned int> *uf0D_unsigned;
+} BPy_UnaryFunction0DUnsigned;
+
+/*---------------------------Python BPy_UnaryFunction0DUnsigned visible prototypes-----------*/
+int UnaryFunction0DUnsigned_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DUNSIGNED_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
new file mode 100644
index 00000000000..faca476f319
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp
@@ -0,0 +1,163 @@
+#include "BPy_UnaryFunction0DVec2f.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h"
+#include "UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVec2f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DVec2f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DVec2f_Type );
+ PyModule_AddObject(module, "UnaryFunction0DVec2f", (PyObject *)&UnaryFunction0DVec2f_Type);
+
+ if( PyType_Ready( &Normal2DF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Normal2DF0D_Type );
+ PyModule_AddObject(module, "Normal2DF0D", (PyObject *)&Normal2DF0D_Type);
+
+ if( PyType_Ready( &VertexOrientation2DF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &VertexOrientation2DF0D_Type );
+ PyModule_AddObject(module, "VertexOrientation2DF0D", (PyObject *)&VertexOrientation2DF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVec2f___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a 2D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVec2f___init__(BPy_UnaryFunction0DVec2f* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_vec2f = new UnaryFunction0D<Vec2f>();
+ self->uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVec2f___dealloc__(BPy_UnaryFunction0DVec2f* self)
+{
+ if (self->uf0D_vec2f)
+ delete self->uf0D_vec2f;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DVec2f___repr__(BPy_UnaryFunction0DVec2f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vec2f->getName().c_str(), self->uf0D_vec2f );
+}
+
+static char UnaryFunction0DVec2f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DVec2f_getName( BPy_UnaryFunction0DVec2f *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_vec2f->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DVec2f___call__( BPy_UnaryFunction0DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_vec2f)) == typeid(UnaryFunction0D<Vec2f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vec2f->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_vec2f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec2f( self->uf0D_vec2f->result );
+
+}
+
+/*----------------------UnaryFunction0DVec2f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DVec2f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DVec2f_getName, METH_NOARGS, UnaryFunction0DVec2f_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DVec2f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVec2f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVec2f", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVec2f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVec2f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVec2f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVec2f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVec2f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DVec2f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVec2f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h
new file mode 100644
index 00000000000..6628d629a41
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVec2f_Type;
+
+#define BPy_UnaryFunction0DVec2f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVec2f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DVec2f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Vec2f> *uf0D_vec2f;
+} BPy_UnaryFunction0DVec2f;
+
+/*---------------------------Python BPy_UnaryFunction0DVec2f visible prototypes-----------*/
+int UnaryFunction0DVec2f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVEC2F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
new file mode 100644
index 00000000000..f329007fd70
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp
@@ -0,0 +1,157 @@
+#include "BPy_UnaryFunction0DVec3f.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVec3f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DVec3f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DVec3f_Type );
+ PyModule_AddObject(module, "UnaryFunction0DVec3f", (PyObject *)&UnaryFunction0DVec3f_Type);
+
+ if( PyType_Ready( &VertexOrientation3DF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &VertexOrientation3DF0D_Type );
+ PyModule_AddObject(module, "VertexOrientation3DF0D", (PyObject *)&VertexOrientation3DF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVec3f___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a 3D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVec3f___init__(BPy_UnaryFunction0DVec3f* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_vec3f = new UnaryFunction0D<Vec3f>();
+ self->uf0D_vec3f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVec3f___dealloc__(BPy_UnaryFunction0DVec3f* self)
+{
+ if (self->uf0D_vec3f)
+ delete self->uf0D_vec3f;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DVec3f___repr__(BPy_UnaryFunction0DVec3f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vec3f->getName().c_str(), self->uf0D_vec3f );
+}
+
+static char UnaryFunction0DVec3f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DVec3f_getName( BPy_UnaryFunction0DVec3f *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_vec3f->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DVec3f___call__( BPy_UnaryFunction0DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_vec3f)) == typeid(UnaryFunction0D<Vec3f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vec3f->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_vec3f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec3f( self->uf0D_vec3f->result );
+
+}
+
+/*----------------------UnaryFunction0DVec3f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DVec3f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DVec3f_getName, METH_NOARGS, UnaryFunction0DVec3f_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DVec3f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVec3f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVec3f", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVec3f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVec3f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVec3f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVec3f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVec3f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DVec3f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVec3f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h
new file mode 100644
index 00000000000..47ec89fb179
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVec3f_Type;
+
+#define BPy_UnaryFunction0DVec3f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVec3f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DVec3f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<Vec3f> *uf0D_vec3f;
+} BPy_UnaryFunction0DVec3f;
+
+/*---------------------------Python BPy_UnaryFunction0DVec3f visible prototypes-----------*/
+int UnaryFunction0DVec3f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVEC3F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
new file mode 100644
index 00000000000..351935141c5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp
@@ -0,0 +1,162 @@
+#include "BPy_UnaryFunction0DVectorViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DVectorViewShape_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DVectorViewShape_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DVectorViewShape_Type );
+ PyModule_AddObject(module, "UnaryFunction0DVectorViewShape", (PyObject *)&UnaryFunction0DVectorViewShape_Type);
+
+ if( PyType_Ready( &GetOccludersF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludersF0D_Type );
+ PyModule_AddObject(module, "GetOccludersF0D", (PyObject *)&GetOccludersF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DVectorViewShape___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a list of :class:`ViewShape`\n"
+"objects.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DVectorViewShape___init__(BPy_UnaryFunction0DVectorViewShape* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_vectorviewshape = new UnaryFunction0D< std::vector<ViewShape*> >();
+ self->uf0D_vectorviewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DVectorViewShape___dealloc__(BPy_UnaryFunction0DVectorViewShape* self)
+{
+ if (self->uf0D_vectorviewshape)
+ delete self->uf0D_vectorviewshape;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DVectorViewShape___repr__(BPy_UnaryFunction0DVectorViewShape* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_vectorviewshape->getName().c_str(), self->uf0D_vectorviewshape );
+}
+
+static char UnaryFunction0DVectorViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DVectorViewShape_getName( BPy_UnaryFunction0DVectorViewShape *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_vectorviewshape->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DVectorViewShape___call__( BPy_UnaryFunction0DVectorViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_vectorviewshape)) == typeid(UnaryFunction0D< std::vector<ViewShape*> >) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_vectorviewshape->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_vectorviewshape->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ PyObject *list = PyList_New(0);
+
+ for( unsigned int i = 0; i < self->uf0D_vectorviewshape->result.size(); i++)
+ PyList_Append(list, BPy_ViewShape_from_ViewShape(*( self->uf0D_vectorviewshape->result[i] )) );
+
+ return list;
+}
+
+/*----------------------UnaryFunction0DVectorViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DVectorViewShape_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DVectorViewShape_getName, METH_NOARGS, UnaryFunction0DVectorViewShape_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DVectorViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DVectorViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DVectorViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction0DVectorViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DVectorViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DVectorViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DVectorViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DVectorViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DVectorViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DVectorViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h
new file mode 100644
index 00000000000..77f96e96f20
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include <vector>
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DVectorViewShape_Type;
+
+#define BPy_UnaryFunction0DVectorViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DVectorViewShape_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DVectorViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D< std::vector<ViewShape*> > *uf0D_vectorviewshape;
+} BPy_UnaryFunction0DVectorViewShape;
+
+/*---------------------------Python BPy_UnaryFunction0DVectorViewShape visible prototypes-----------*/
+int UnaryFunction0DVectorViewShape_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVECTORVIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
new file mode 100644
index 00000000000..e3e8538009d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp
@@ -0,0 +1,163 @@
+#include "BPy_UnaryFunction0DViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../Iterator/BPy_Interface0DIterator.h"
+
+#include "UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h"
+#include "UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction0DViewShape_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction0DViewShape_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction0DViewShape_Type );
+ PyModule_AddObject(module, "UnaryFunction0DViewShape", (PyObject *)&UnaryFunction0DViewShape_Type);
+
+ if( PyType_Ready( &GetOccludeeF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludeeF0D_Type );
+ PyModule_AddObject(module, "GetOccludeeF0D", (PyObject *)&GetOccludeeF0D_Type);
+
+ if( PyType_Ready( &GetShapeF0D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetShapeF0D_Type );
+ PyModule_AddObject(module, "GetShapeF0D", (PyObject *)&GetShapeF0D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction0DViewShape___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface0DIterator` and return a :class:`ViewShape` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n";
+
+static int UnaryFunction0DViewShape___init__(BPy_UnaryFunction0DViewShape* self, PyObject *args, PyObject *kwds)
+{
+ if ( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->uf0D_viewshape = new UnaryFunction0D<ViewShape*>();
+ self->uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+static void UnaryFunction0DViewShape___dealloc__(BPy_UnaryFunction0DViewShape* self)
+{
+ if (self->uf0D_viewshape)
+ delete self->uf0D_viewshape;
+ UnaryFunction0D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction0DViewShape___repr__(BPy_UnaryFunction0DViewShape* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf0D_viewshape->getName().c_str(), self->uf0D_viewshape );
+}
+
+static char UnaryFunction0DViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 0D predicate.\n"
+"\n"
+" :return: The name of the unary 0D predicate.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction0DViewShape_getName( BPy_UnaryFunction0DViewShape *self )
+{
+ return PyUnicode_FromFormat( self->uf0D_viewshape->getName().c_str() );
+}
+
+static PyObject * UnaryFunction0DViewShape___call__( BPy_UnaryFunction0DViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if(!PyArg_ParseTuple(args, "O!", &Interface0DIterator_Type, &obj))
+ return NULL;
+
+ if( typeid(*(self->uf0D_viewshape)) == typeid(UnaryFunction0D<ViewShape*>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf0D_viewshape->operator()(*( ((BPy_Interface0DIterator *) obj)->if0D_it )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf0D_viewshape->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_ViewShape_from_ViewShape( *(self->uf0D_viewshape->result) );
+
+}
+
+/*----------------------UnaryFunction0DViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction0DViewShape_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction0DViewShape_getName, METH_NOARGS, UnaryFunction0DViewShape_getName___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction0DViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction0DViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction0DViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction0DViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction0DViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction0DViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction0DViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction0DViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction0DViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction0DViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h
new file mode 100644
index 00000000000..68c888eb36b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H
+
+#include "../BPy_UnaryFunction0D.h"
+
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction0DViewShape_Type;
+
+#define BPy_UnaryFunction0DViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction0DViewShape_Type) )
+
+/*---------------------------Python BPy_UnaryFunction0DViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0D py_uf0D;
+ UnaryFunction0D<ViewShape*> *uf0D_viewshape;
+} BPy_UnaryFunction0DViewShape;
+
+/*---------------------------Python BPy_UnaryFunction0DViewShape visible prototypes-----------*/
+int UnaryFunction0DViewShape_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION0DVIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
new file mode 100644
index 00000000000..8acb96f8d0f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp
@@ -0,0 +1,90 @@
+#include "BPy_ShapeIdF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ShapeIdF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a ShapeIdF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`Id` of the Shape the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator belongs to. This evaluation can\n"
+" be ambiguous (in the case of a :class:`TVertex` for example). This\n"
+" functor tries to remove this ambiguity using the context offered by\n"
+" the 1D element to which the Interface0DIterator belongs to.\n"
+" However, there still can be problematic cases, and the user willing\n"
+" to deal with this cases in a specific way should implement its own\n"
+" getShapeIdF0D functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Id of the Shape the pointed Interface0D belongs to.\n"
+" :rtype: :class:`Id`\n";
+
+static int ShapeIdF0D___init__( BPy_ShapeIdF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_id.uf0D_id = new Functions0D::ShapeIdF0D();
+ self->py_uf0D_id.uf0D_id->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ShapeIdF0D type definition ------------------------------*/
+
+PyTypeObject ShapeIdF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ShapeIdF0D", /* tp_name */
+ sizeof(BPy_ShapeIdF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ShapeIdF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DId_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ShapeIdF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
new file mode 100644
index 00000000000..11995bb4e88
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_SHAPEIDF0D_H
+#define FREESTYLE_PYTHON_SHAPEIDF0D_H
+
+#include "../BPy_UnaryFunction0DId.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ShapeIdF0D_Type;
+
+#define BPy_ShapeIdF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ShapeIdF0D_Type) )
+
+/*---------------------------Python BPy_ShapeIdF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DId py_uf0D_id;
+} BPy_ShapeIdF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SHAPEIDF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
new file mode 100644
index 00000000000..1f709947d0e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_MaterialF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char MaterialF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a MaterialF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the material of the object evaluated at the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator. This\n"
+" evaluation can be ambiguous (in the case of a :class:`TVertex` for\n"
+" example. This functor tries to remove this ambiguity using the\n"
+" context offered by the 1D element to which the Interface0DIterator\n"
+" belongs to and by arbitrary chosing the material of the face that\n"
+" lies on its left when following the 1D element if there are two\n"
+" different materials on each side of the point. However, there\n"
+" still can be problematic cases, and the user willing to deal with\n"
+" this cases in a specific way should implement its own getMaterial\n"
+" functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The material of the object evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: :class:`Material`\n";
+
+static int MaterialF0D___init__( BPy_MaterialF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_material.uf0D_material = new Functions0D::MaterialF0D();
+ self->py_uf0D_material.uf0D_material->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_MaterialF0D type definition ------------------------------*/
+
+PyTypeObject MaterialF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "MaterialF0D", /* tp_name */
+ sizeof(BPy_MaterialF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ MaterialF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DMaterial_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)MaterialF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
new file mode 100644
index 00000000000..1ae30484ba5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_MATERIALF0D_H
+#define FREESTYLE_PYTHON_MATERIALF0D_H
+
+#include "../BPy_UnaryFunction0DMaterial.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject MaterialF0D_Type;
+
+#define BPy_MaterialF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &MaterialF0D_Type) )
+
+/*---------------------------Python BPy_MaterialF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DMaterial py_uf0D_material;
+} BPy_MaterialF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_MATERIALF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
new file mode 100644
index 00000000000..0216d01baba
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp
@@ -0,0 +1,85 @@
+#include "BPy_CurveNatureF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurveNatureF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a CurveNatureF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`Nature` of the 1D element the Interface0D pointed\n"
+" by the Interface0DIterator belongs to.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The nature of the 1D element to which the pointed Interface0D\n"
+" belongs.\n"
+" :rtype: :class:`Nature`\n";
+
+static int CurveNatureF0D___init__( BPy_CurveNatureF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_edgenature.uf0D_edgenature = new Functions0D::CurveNatureF0D();
+ self->py_uf0D_edgenature.uf0D_edgenature->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_CurveNatureF0D type definition ------------------------------*/
+
+PyTypeObject CurveNatureF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurveNatureF0D", /* tp_name */
+ sizeof(BPy_CurveNatureF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurveNatureF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DEdgeNature_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurveNatureF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
new file mode 100644
index 00000000000..63b3050c474
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVENATUREF0D_H
+#define FREESTYLE_PYTHON_CURVENATUREF0D_H
+
+#include "../BPy_UnaryFunction0DEdgeNature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurveNatureF0D_Type;
+
+#define BPy_CurveNatureF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurveNatureF0D_Type) )
+
+/*---------------------------Python BPy_CurveNatureF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DEdgeNature py_uf0D_edgenature;
+} BPy_CurveNatureF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVENATUREF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
new file mode 100644
index 00000000000..e1b5e14c9bd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_Normal2DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Normal2DF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a Normal2DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a two-dimensional vector giving the normalized 2D normal to\n"
+" the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The normal is evaluated at the pointed\n"
+" Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D normal of the 1D element evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Normal2DF0D___init__( BPy_Normal2DF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::Normal2DF0D();
+ self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_Normal2DF0D type definition ------------------------------*/
+
+PyTypeObject Normal2DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Normal2DF0D", /* tp_name */
+ sizeof(BPy_Normal2DF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Normal2DF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Normal2DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
new file mode 100644
index 00000000000..0b3be2df428
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_NORMAL2DF0D_H
+#define FREESTYLE_PYTHON_NORMAL2DF0D_H
+
+#include "../BPy_UnaryFunction0DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Normal2DF0D_Type;
+
+#define BPy_Normal2DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Normal2DF0D_Type) )
+
+/*---------------------------Python BPy_Normal2DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec2f py_uf0D_vec2f;
+} BPy_Normal2DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NORMAL2DF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
new file mode 100644
index 00000000000..e1663468307
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_VertexOrientation2DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char VertexOrientation2DF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a VertexOrientation2DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a two-dimensional vector giving the 2D oriented tangent to\n"
+" the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 2D oriented tangent is evaluated\n"
+" at the pointed Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D oriented tangent to the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int VertexOrientation2DF0D___init__( BPy_VertexOrientation2DF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vec2f.uf0D_vec2f = new Functions0D::VertexOrientation2DF0D();
+ self->py_uf0D_vec2f.uf0D_vec2f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_VertexOrientation2DF0D type definition ------------------------------*/
+
+PyTypeObject VertexOrientation2DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "VertexOrientation2DF0D", /* tp_name */
+ sizeof(BPy_VertexOrientation2DF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ VertexOrientation2DF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)VertexOrientation2DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
new file mode 100644
index 00000000000..1cce9b592ba
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H
+#define FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H
+
+#include "../BPy_UnaryFunction0DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject VertexOrientation2DF0D_Type;
+
+#define BPy_VertexOrientation2DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &VertexOrientation2DF0D_Type) )
+
+/*---------------------------Python BPy_VertexOrientation2DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec2f py_uf0D_vec2f;
+} BPy_VertexOrientation2DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VERTEXORIENTATION2DF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
new file mode 100644
index 00000000000..0455eeac20e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_VertexOrientation3DF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char VertexOrientation3DF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a VertexOrientation3DF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a three-dimensional vector giving the 3D oriented tangent\n"
+" to the 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 3D oriented tangent is evaluated\n"
+" at the pointed Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 3D oriented tangent to the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int VertexOrientation3DF0D___init__( BPy_VertexOrientation3DF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vec3f.uf0D_vec3f = new Functions0D::VertexOrientation3DF0D();
+ self->py_uf0D_vec3f.uf0D_vec3f->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_VertexOrientation3DF0D type definition ------------------------------*/
+
+PyTypeObject VertexOrientation3DF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "VertexOrientation3DF0D", /* tp_name */
+ sizeof(BPy_VertexOrientation3DF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ VertexOrientation3DF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVec3f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)VertexOrientation3DF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
new file mode 100644
index 00000000000..80cac529f0b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H
+#define FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H
+
+#include "../BPy_UnaryFunction0DVec3f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject VertexOrientation3DF0D_Type;
+
+#define BPy_VertexOrientation3DF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &VertexOrientation3DF0D_Type) )
+
+/*---------------------------Python BPy_VertexOrientation3DF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVec3f py_uf0D_vec3f;
+} BPy_VertexOrientation3DF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_VERTEXORIENTATION3DF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp
new file mode 100644
index 00000000000..d4af0b2f95d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetOccludeeF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludeeF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludeeF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`ViewShape` that the Interface0D pointed by the\n"
+" Interface0DIterator occludes.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The ViewShape occluded by the pointed Interface0D.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static int GetOccludeeF0D___init__( BPy_GetOccludeeF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetOccludeeF0D();
+ self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludeeF0D type definition ------------------------------*/
+
+PyTypeObject GetOccludeeF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludeeF0D", /* tp_name */
+ sizeof(BPy_GetOccludeeF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludeeF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludeeF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
new file mode 100644
index 00000000000..fd4f7d92bbb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDEEF0D_H
+#define FREESTYLE_PYTHON_GETOCCLUDEEF0D_H
+
+#include "../BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludeeF0D_Type;
+
+#define BPy_GetOccludeeF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludeeF0D_Type) )
+
+/*---------------------------Python BPy_GetOccludeeF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DViewShape py_uf0D_viewshape;
+} BPy_GetOccludeeF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDEEF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp
new file mode 100644
index 00000000000..331ee590b91
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetShapeF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetShapeF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetShapeF0D.cpp object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the :class:`ViewShape` containing the Interface0D pointed\n"
+" by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The ViewShape containing the pointed Interface0D.\n"
+" :rtype: :class:`ViewShape`\n";
+
+static int GetShapeF0D___init__( BPy_GetShapeF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_viewshape.uf0D_viewshape = new Functions0D::GetShapeF0D();
+ self->py_uf0D_viewshape.uf0D_viewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetShapeF0D type definition ------------------------------*/
+
+PyTypeObject GetShapeF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetShapeF0D", /* tp_name */
+ sizeof(BPy_GetShapeF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetShapeF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetShapeF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
new file mode 100644
index 00000000000..040c753968d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETSHAPEF0D_H
+#define FREESTYLE_PYTHON_GETSHAPEF0D_H
+
+#include "../BPy_UnaryFunction0DViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetShapeF0D_Type;
+
+#define BPy_GetShapeF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetShapeF0D_Type) )
+
+/*---------------------------Python BPy_GetShapeF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DViewShape py_uf0D_viewshape;
+} BPy_GetShapeF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETSHAPEF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
new file mode 100644
index 00000000000..9223c7d0088
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_Curvature2DAngleF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Curvature2DAngleF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a Curvature2DAngleF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a real value giving the 2D curvature (as an angle) of the\n"
+" 1D element to which the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator belongs. The 2D curvature is evaluated at the\n"
+" Interface0D.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The 2D curvature of the 1D element evaluated at the\n"
+" pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int Curvature2DAngleF0D___init__( BPy_Curvature2DAngleF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::Curvature2DAngleF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_Curvature2DAngleF0D type definition ------------------------------*/
+
+PyTypeObject Curvature2DAngleF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curvature2DAngleF0D", /* tp_name */
+ sizeof(BPy_Curvature2DAngleF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Curvature2DAngleF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Curvature2DAngleF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
new file mode 100644
index 00000000000..810ba04db8a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H
+#define FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Curvature2DAngleF0D_Type;
+
+#define BPy_Curvature2DAngleF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Curvature2DAngleF0D_Type) )
+
+/*---------------------------Python BPy_Curvature2DAngleF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_Curvature2DAngleF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVATURE2DANGLEF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
new file mode 100644
index 00000000000..4b2f56104a2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_DensityF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityF0D___doc__[] =
+".. method:: __init__(sigma=2.0)\n"
+"\n"
+" Builds a DensityF0D object.\n"
+"\n"
+" :arg sigma: The gaussian sigma value ndicating the X value for\n"
+" which the gaussian function is 0.5. It leads to the window size\n"
+" value (the larger, the smoother).\n"
+" :type sigma: float\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the density of the (result) image evaluated at the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator. This\n"
+" density is evaluated using a pixels square window around the\n"
+" evaluation point and integrating these values using a gaussian.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The density of the image evaluated at the pointed\n"
+" Interface0D.\n"
+" :rtype: float\n";
+
+static int DensityF0D___init__( BPy_DensityF0D* self, PyObject *args)
+{
+ double d = 2;
+
+ if( !PyArg_ParseTuple(args, "|d", &d) )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::DensityF0D(d);
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_DensityF0D type definition ------------------------------*/
+
+PyTypeObject DensityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityF0D", /* tp_name */
+ sizeof(BPy_DensityF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DensityF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
new file mode 100644
index 00000000000..17ea95a771c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_DENSITYF0D_H
+#define FREESTYLE_PYTHON_DENSITYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityF0D_Type;
+
+#define BPy_DensityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityF0D_Type) )
+
+/*---------------------------Python BPy_DensityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_DensityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_DENSITYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp
new file mode 100644
index 00000000000..f11555a1e3c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetProjectedXF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedXF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedXF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the X 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The X 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedXF0D___init__( BPy_GetProjectedXF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedXF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedXF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedXF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedXF0D", /* tp_name */
+ sizeof(BPy_GetProjectedXF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedXF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedXF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
new file mode 100644
index 00000000000..da73623cbf0
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDXF0D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDXF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedXF0D_Type;
+
+#define BPy_GetProjectedXF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedXF0D_Type) )
+
+/*---------------------------Python BPy_GetProjectedXF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedXF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDXF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp
new file mode 100644
index 00000000000..fa00514869a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetProjectedYF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedYF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedYF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Y 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Y 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedYF0D___init__( BPy_GetProjectedYF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedYF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedYF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedYF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedYF0D", /* tp_name */
+ sizeof(BPy_GetProjectedYF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedYF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedYF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
new file mode 100644
index 00000000000..3a26e093747
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDYF0D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedYF0D_Type;
+
+#define BPy_GetProjectedYF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedYF0D_Type) )
+
+/*---------------------------Python BPy_GetProjectedYF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedYF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp
new file mode 100644
index 00000000000..19f61fc8203
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetProjectedZF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedZF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetProjectedZF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Z 3D projected coordinate of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Z 3D projected coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetProjectedZF0D___init__( BPy_GetProjectedZF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetProjectedZF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedZF0D type definition ------------------------------*/
+
+PyTypeObject GetProjectedZF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedZF0D", /* tp_name */
+ sizeof(BPy_GetProjectedZF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedZF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedZF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
new file mode 100644
index 00000000000..aa41b70c660
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDZF0D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDZF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedZF0D_Type;
+
+#define BPy_GetProjectedZF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedZF0D_Type) )
+
+/*---------------------------Python BPy_GetProjectedZF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetProjectedZF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDZF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp
new file mode 100644
index 00000000000..0dde08e6f35
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetXF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetXF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetXF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the X 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The X 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetXF0D___init__( BPy_GetXF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetXF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetXF0D type definition ------------------------------*/
+
+PyTypeObject GetXF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetXF0D", /* tp_name */
+ sizeof(BPy_GetXF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetXF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetXF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
new file mode 100644
index 00000000000..69e9a892f4a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETXF0D_H
+#define FREESTYLE_PYTHON_GETXF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetXF0D_Type;
+
+#define BPy_GetXF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetXF0D_Type) )
+
+/*---------------------------Python BPy_GetXF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetXF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETXF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp
new file mode 100644
index 00000000000..4775c65c199
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetYF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetYF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetYF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Y 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Y 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetYF0D___init__( BPy_GetYF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetYF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetYF0D type definition ------------------------------*/
+
+PyTypeObject GetYF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetYF0D", /* tp_name */
+ sizeof(BPy_GetYF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetYF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetYF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
new file mode 100644
index 00000000000..0601f38585f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETYF0D_H
+#define FREESTYLE_PYTHON_GETYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetYF0D_Type;
+
+#define BPy_GetYF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetYF0D_Type) )
+
+/*---------------------------Python BPy_GetYF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetYF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp
new file mode 100644
index 00000000000..7a5fdfadf92
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetZF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetZF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetZF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the Z 3D coordinate of the :class:`Interface0D` pointed by\n"
+" the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The Z 3D coordinate of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetZF0D___init__( BPy_GetZF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::GetZF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetZF0D type definition ------------------------------*/
+
+PyTypeObject GetZF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetZF0D", /* tp_name */
+ sizeof(BPy_GetZF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetZF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetZF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
new file mode 100644
index 00000000000..eac52426600
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETZF0D_H
+#define FREESTYLE_PYTHON_GETZF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetZF0D_Type;
+
+#define BPy_GetZF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetZF0D_Type) )
+
+/*---------------------------Python BPy_GetZF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_GetZF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETZF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
new file mode 100644
index 00000000000..5c07913100e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp
@@ -0,0 +1,90 @@
+#include "BPy_LocalAverageDepthF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char LocalAverageDepthF0D___doc__[] =
+".. method:: __init__(maskSize=5.0)\n"
+"\n"
+" Builds a LocalAverageDepthF0D object.\n"
+"\n"
+" :arg maskSize: The size of the mask.\n"
+" :type maskSize: float\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the average depth around the :class:`Interface0D` pointed\n"
+" by the Interface0DIterator. The result is obtained by querying the\n"
+" depth buffer on a window around that point.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The average depth around the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int LocalAverageDepthF0D___init__( BPy_LocalAverageDepthF0D* self, PyObject *args)
+{
+ double d = 5.0;
+
+ if( !PyArg_ParseTuple(args, "|d", &d) )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::LocalAverageDepthF0D(d);
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_LocalAverageDepthF0D type definition ------------------------------*/
+
+PyTypeObject LocalAverageDepthF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "LocalAverageDepthF0D", /* tp_name */
+ sizeof(BPy_LocalAverageDepthF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ LocalAverageDepthF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)LocalAverageDepthF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
new file mode 100644
index 00000000000..7385e1d24c1
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H
+#define FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject LocalAverageDepthF0D_Type;
+
+#define BPy_LocalAverageDepthF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &LocalAverageDepthF0D_Type) )
+
+/*---------------------------Python BPy_LocalAverageDepthF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_LocalAverageDepthF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
new file mode 100644
index 00000000000..f9bcbb6ee21
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_ZDiscontinuityF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ZDiscontinuityF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a ZDiscontinuityF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a real value giving the distance between the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator and the\n"
+" shape that lies behind (occludee). This distance is evaluated in\n"
+" the camera space and normalized between 0 and 1. Therefore, if no\n"
+" oject is occluded by the shape to which the Interface0D belongs to,\n"
+" 1 is returned.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The normalized distance between the pointed Interface0D\n"
+" and the occludee.\n"
+" :rtype: float\n";
+
+static int ZDiscontinuityF0D___init__( BPy_ZDiscontinuityF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_double.uf0D_double = new Functions0D::ZDiscontinuityF0D();
+ self->py_uf0D_double.uf0D_double->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ZDiscontinuityF0D type definition ------------------------------*/
+
+PyTypeObject ZDiscontinuityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ZDiscontinuityF0D", /* tp_name */
+ sizeof(BPy_ZDiscontinuityF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ZDiscontinuityF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ZDiscontinuityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
new file mode 100644
index 00000000000..a26ba4fdbd6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H
+#define FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H
+
+#include "../BPy_UnaryFunction0DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ZDiscontinuityF0D_Type;
+
+#define BPy_ZDiscontinuityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ZDiscontinuityF0D_Type) )
+
+/*---------------------------Python BPy_ZDiscontinuityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DDouble py_uf0D_double;
+} BPy_ZDiscontinuityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ZDISCONTINUITYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
new file mode 100644
index 00000000000..9dfcf776103
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp
@@ -0,0 +1,85 @@
+#include "BPy_GetCurvilinearAbscissaF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetCurvilinearAbscissaF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetCurvilinearAbscissaF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the curvilinear abscissa of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator in the context of its 1D\n"
+" element.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The curvilinear abscissa of the pointed Interface0D.\n"
+" :rtype: float\n";
+
+static int GetCurvilinearAbscissaF0D___init__( BPy_GetCurvilinearAbscissaF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetCurvilinearAbscissaF0D();
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetCurvilinearAbscissaF0D type definition ------------------------------*/
+
+PyTypeObject GetCurvilinearAbscissaF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetCurvilinearAbscissaF0D", /* tp_name */
+ sizeof(BPy_GetCurvilinearAbscissaF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetCurvilinearAbscissaF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetCurvilinearAbscissaF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
new file mode 100644
index 00000000000..0cb56fcec70
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H
+#define FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetCurvilinearAbscissaF0D_Type;
+
+#define BPy_GetCurvilinearAbscissaF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetCurvilinearAbscissaF0D_Type) )
+
+/*---------------------------Python BPy_GetCurvilinearAbscissaF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetCurvilinearAbscissaF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETCURVILINEARABSCISSAF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp
new file mode 100644
index 00000000000..d8861ac2f77
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetParameterF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetParameterF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetParameterF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the parameter of the :class:`Interface0D` pointed by the\n"
+" Interface0DIterator in the context of its 1D element.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The parameter of an Interface0D.\n"
+" :rtype: float\n";
+
+static int GetParameterF0D___init__( BPy_GetParameterF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetParameterF0D();
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetParameterF0D type definition ------------------------------*/
+
+PyTypeObject GetParameterF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetParameterF0D", /* tp_name */
+ sizeof(BPy_GetParameterF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetParameterF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetParameterF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
new file mode 100644
index 00000000000..4817e5cec86
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPARAMETERF0D_H
+#define FREESTYLE_PYTHON_GETPARAMETERF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetParameterF0D_Type;
+
+#define BPy_GetParameterF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetParameterF0D_Type) )
+
+/*---------------------------Python BPy_GetParameterF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetParameterF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPARAMETERF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
new file mode 100644
index 00000000000..b753727fbf5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp
@@ -0,0 +1,91 @@
+#include "BPy_GetViewMapGradientNormF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetViewMapGradientNormF0D___doc__[] =
+".. method:: __init__(level)\n"
+"\n"
+" Builds a GetViewMapGradientNormF0D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the norm of the gradient of the global viewmap density\n"
+" image.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The norm of the gradient of the global viewmap density\n"
+" image.\n"
+" :rtype: float\n";
+
+static int GetViewMapGradientNormF0D___init__( BPy_GetViewMapGradientNormF0D* self, PyObject *args)
+{
+ int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::GetViewMapGradientNormF0D(i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetViewMapGradientNormF0D type definition ------------------------------*/
+
+PyTypeObject GetViewMapGradientNormF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetViewMapGradientNormF0D", /* tp_name */
+ sizeof(BPy_GetViewMapGradientNormF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetViewMapGradientNormF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetViewMapGradientNormF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
new file mode 100644
index 00000000000..c072ba7f408
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H
+#define FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetViewMapGradientNormF0D_Type;
+
+#define BPy_GetViewMapGradientNormF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetViewMapGradientNormF0D_Type) )
+
+/*---------------------------Python BPy_GetViewMapGradientNormF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_GetViewMapGradientNormF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
new file mode 100644
index 00000000000..660f2b9f0c5
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp
@@ -0,0 +1,89 @@
+#include "BPy_ReadCompleteViewMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadCompleteViewMapPixelF0D___doc__[] =
+".. method:: __init__(level)\n"
+"\n"
+" Builds a ReadCompleteViewMapPixelF0D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in one of the level of the complete viewmap.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in one of the level of the complete viewmap.\n"
+" :rtype: float\n";
+
+static int ReadCompleteViewMapPixelF0D___init__( BPy_ReadCompleteViewMapPixelF0D* self, PyObject *args)
+{
+ int i;
+
+ if( !PyArg_ParseTuple(args, "i", &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadCompleteViewMapPixelF0D(i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadCompleteViewMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadCompleteViewMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadCompleteViewMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadCompleteViewMapPixelF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ReadCompleteViewMapPixelF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadCompleteViewMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
new file mode 100644
index 00000000000..6a10e6c06a4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H
+#define FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadCompleteViewMapPixelF0D_Type;
+
+#define BPy_ReadCompleteViewMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadCompleteViewMapPixelF0D_Type) )
+
+/*---------------------------Python BPy_ReadCompleteViewMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadCompleteViewMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_READCOMPLETEVIEWMAPPIXELF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
new file mode 100644
index 00000000000..6826bda4c09
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_ReadMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadMapPixelF0D___doc__[] =
+".. method:: __init__(iMapName, level)\n"
+"\n"
+" Builds a ReadMapPixelF0D object.\n"
+"\n"
+" :arg iMapName: The name of the map to be read.\n"
+" :type iMapName: string\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in a map.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in a map.\n"
+" :rtype: float\n";
+
+static int ReadMapPixelF0D___init__( BPy_ReadMapPixelF0D* self, PyObject *args)
+{
+ const char *s;
+ int i;
+
+ if( !PyArg_ParseTuple(args, "si", &s, &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadMapPixelF0D(s,i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadMapPixelF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ReadMapPixelF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
new file mode 100644
index 00000000000..9aed0cd82bf
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_READMAPPIXELF0D_H
+#define FREESTYLE_PYTHON_READMAPPIXELF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadMapPixelF0D_Type;
+
+#define BPy_ReadMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadMapPixelF0D_Type) )
+
+/*---------------------------Python BPy_ReadMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_READMAPPIXELF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
new file mode 100644
index 00000000000..5d551d9b910
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp
@@ -0,0 +1,93 @@
+#include "BPy_ReadSteerableViewMapPixelF0D.h"
+
+#include "../../../stroke/AdvancedFunctions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ReadSteerableViewMapPixelF0D___doc__[] =
+".. method:: __init__(nOrientation, level)\n"
+"\n"
+" Builds a ReadSteerableViewMapPixelF0D object.\n"
+"\n"
+" :arg nOrientation: The integer belonging to [0, 4] indicating the\n"
+" orientation (E, NE, N, NW) we are interested in.\n"
+" :type nOrientation: int\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Reads a pixel in one of the level of one of the steerable viewmaps.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A pixel in one of the level of one of the steerable viewmaps.\n"
+" :rtype: float\n";
+
+static int ReadSteerableViewMapPixelF0D___init__( BPy_ReadSteerableViewMapPixelF0D* self, PyObject *args)
+{
+ unsigned int u;
+ int i;
+
+ if( !PyArg_ParseTuple(args, "Ii", &u, &i) )
+ return -1;
+ self->py_uf0D_float.uf0D_float = new Functions0D::ReadSteerableViewMapPixelF0D(u,i);
+ self->py_uf0D_float.uf0D_float->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_ReadSteerableViewMapPixelF0D type definition ------------------------------*/
+
+PyTypeObject ReadSteerableViewMapPixelF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ReadSteerableViewMapPixelF0D", /* tp_name */
+ sizeof(BPy_ReadSteerableViewMapPixelF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ReadSteerableViewMapPixelF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DFloat_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ReadSteerableViewMapPixelF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
new file mode 100644
index 00000000000..a881a10f72d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H
+#define FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H
+
+#include "../BPy_UnaryFunction0DFloat.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ReadSteerableViewMapPixelF0D_Type;
+
+#define BPy_ReadSteerableViewMapPixelF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ReadSteerableViewMapPixelF0D_Type) )
+
+/*---------------------------Python BPy_ReadSteerableViewMapPixelF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DFloat py_uf0D_float;
+} BPy_ReadSteerableViewMapPixelF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_READSTEERABLEVIEWMAPPIXELF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
new file mode 100644
index 00000000000..91093e482ff
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp
@@ -0,0 +1,90 @@
+#include "BPy_QuantitativeInvisibilityF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a QuantitativeInvisibilityF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns the quantitative invisibility of the :class:`Interface0D`\n"
+" pointed by the Interface0DIterator. This evaluation can be\n"
+" ambiguous (in the case of a :class:`TVertex` for example). This\n"
+" functor tries to remove this ambiguity using the context offered by\n"
+" the 1D element to which the Interface0D belongs to. However, there\n"
+" still can be problematic cases, and the user willing to deal with\n"
+" this cases in a specific way should implement its own getQIF0D\n"
+" functor.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: The quantitative invisibility of the pointed Interface0D.\n"
+" :rtype: int\n";
+
+static int QuantitativeInvisibilityF0D___init__( BPy_QuantitativeInvisibilityF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_unsigned.uf0D_unsigned = new Functions0D::QuantitativeInvisibilityF0D();
+ self->py_uf0D_unsigned.uf0D_unsigned->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityF0D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityF0D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ QuantitativeInvisibilityF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DUnsigned_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
new file mode 100644
index 00000000000..39b73343608
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H
+#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H
+
+#include "../BPy_UnaryFunction0DUnsigned.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityF0D_Type;
+
+#define BPy_QuantitativeInvisibilityF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityF0D_Type) )
+
+/*---------------------------Python BPy_QuantitativeInvisibilityF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DUnsigned py_uf0D_unsigned;
+} BPy_QuantitativeInvisibilityF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
new file mode 100644
index 00000000000..943d1950016
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp
@@ -0,0 +1,85 @@
+#include "BPy_GetOccludersF0D.h"
+
+#include "../../../view_map/Functions0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludersF0D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludersF0D object.\n"
+"\n"
+".. method:: __call__(it)\n"
+"\n"
+" Returns a list of :class:`ViewShape` objects occluding the\n"
+" :class:`Interface0D` pointed by the Interface0DIterator.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: A list of ViewShape objects occluding the pointed\n"
+" Interface0D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludersF0D___init__( BPy_GetOccludersF0D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf0D_vectorviewshape.uf0D_vectorviewshape = new Functions0D::GetOccludersF0D();
+ self->py_uf0D_vectorviewshape.uf0D_vectorviewshape->py_uf0D = (PyObject *)self;
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludersF0D type definition ------------------------------*/
+
+PyTypeObject GetOccludersF0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludersF0D", /* tp_name */
+ sizeof(BPy_GetOccludersF0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludersF0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction0DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludersF0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
new file mode 100644
index 00000000000..0e92158a2e7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDERSF0D_H
+#define FREESTYLE_PYTHON_GETOCCLUDERSF0D_H
+
+#include "../BPy_UnaryFunction0DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludersF0D_Type;
+
+#define BPy_GetOccludersF0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludersF0D_Type) )
+
+/*---------------------------Python BPy_GetOccludersF0D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction0DVectorViewShape py_uf0D_vectorviewshape;
+} BPy_GetOccludersF0D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDERSF0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
new file mode 100644
index 00000000000..7721b35b2a8
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp
@@ -0,0 +1,287 @@
+#include "BPy_UnaryFunction1DDouble.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h"
+#include "UnaryFunction1D_double/BPy_DensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedXF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedYF1D.h"
+#include "UnaryFunction1D_double/BPy_GetProjectedZF1D.h"
+#include "UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h"
+#include "UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h"
+#include "UnaryFunction1D_double/BPy_GetXF1D.h"
+#include "UnaryFunction1D_double/BPy_GetYF1D.h"
+#include "UnaryFunction1D_double/BPy_GetZF1D.h"
+#include "UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h"
+#include "UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DDouble_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DDouble_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DDouble_Type );
+ PyModule_AddObject(module, "UnaryFunction1DDouble", (PyObject *)&UnaryFunction1DDouble_Type);
+
+ if( PyType_Ready( &DensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &DensityF1D_Type );
+ PyModule_AddObject(module, "DensityF1D", (PyObject *)&DensityF1D_Type);
+
+ if( PyType_Ready( &Curvature2DAngleF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Curvature2DAngleF1D_Type );
+ PyModule_AddObject(module, "Curvature2DAngleF1D", (PyObject *)&Curvature2DAngleF1D_Type);
+
+ if( PyType_Ready( &GetCompleteViewMapDensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetCompleteViewMapDensityF1D_Type );
+ PyModule_AddObject(module, "GetCompleteViewMapDensityF1D", (PyObject *)&GetCompleteViewMapDensityF1D_Type);
+
+ if( PyType_Ready( &GetDirectionalViewMapDensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetDirectionalViewMapDensityF1D_Type );
+ PyModule_AddObject(module, "GetDirectionalViewMapDensityF1D", (PyObject *)&GetDirectionalViewMapDensityF1D_Type);
+
+ if( PyType_Ready( &GetProjectedXF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedXF1D_Type );
+ PyModule_AddObject(module, "GetProjectedXF1D", (PyObject *)&GetProjectedXF1D_Type);
+
+ if( PyType_Ready( &GetProjectedYF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedYF1D_Type );
+ PyModule_AddObject(module, "GetProjectedYF1D", (PyObject *)&GetProjectedYF1D_Type);
+
+ if( PyType_Ready( &GetProjectedZF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetProjectedZF1D_Type );
+ PyModule_AddObject(module, "GetProjectedZF1D", (PyObject *)&GetProjectedZF1D_Type);
+
+ if( PyType_Ready( &GetSteerableViewMapDensityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetSteerableViewMapDensityF1D_Type );
+ PyModule_AddObject(module, "GetSteerableViewMapDensityF1D", (PyObject *)&GetSteerableViewMapDensityF1D_Type);
+
+ if( PyType_Ready( &GetViewMapGradientNormF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetViewMapGradientNormF1D_Type );
+ PyModule_AddObject(module, "GetViewMapGradientNormF1D", (PyObject *)&GetViewMapGradientNormF1D_Type);
+
+ if( PyType_Ready( &GetXF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetXF1D_Type );
+ PyModule_AddObject(module, "GetXF1D", (PyObject *)&GetXF1D_Type);
+
+ if( PyType_Ready( &GetYF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetYF1D_Type );
+ PyModule_AddObject(module, "GetYF1D", (PyObject *)&GetYF1D_Type);
+
+ if( PyType_Ready( &GetZF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetZF1D_Type );
+ PyModule_AddObject(module, "GetZF1D", (PyObject *)&GetZF1D_Type);
+
+ if( PyType_Ready( &LocalAverageDepthF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &LocalAverageDepthF1D_Type );
+ PyModule_AddObject(module, "LocalAverageDepthF1D", (PyObject *)&LocalAverageDepthF1D_Type);
+
+ if( PyType_Ready( &ZDiscontinuityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ZDiscontinuityF1D_Type );
+ PyModule_AddObject(module, "ZDiscontinuityF1D", (PyObject *)&ZDiscontinuityF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DDouble___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DDouble___init__(BPy_UnaryFunction1DDouble* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_double = new UnaryFunction1D<double>();
+ else {
+ self->uf1D_double = new UnaryFunction1D<double>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_double->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DDouble___dealloc__(BPy_UnaryFunction1DDouble* self)
+{
+ if (self->uf1D_double)
+ delete self->uf1D_double;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DDouble___repr__(BPy_UnaryFunction1DDouble* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_double->getName().c_str(), self->uf1D_double );
+}
+
+static char UnaryFunction1DDouble_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DDouble_getName( BPy_UnaryFunction1DDouble *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_double->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DDouble___call__( BPy_UnaryFunction1DDouble *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_double)) == typeid(UnaryFunction1D<double>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_double->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_double->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf1D_double->result );
+
+}
+
+static char UnaryFunction1DDouble_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DDouble_setIntegrationType(BPy_UnaryFunction1DDouble* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_double->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DDouble_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DDouble_getIntegrationType(BPy_UnaryFunction1DDouble* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_double->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DDouble instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DDouble_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DDouble_getName, METH_NOARGS, UnaryFunction1DDouble_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DDouble_setIntegrationType, METH_VARARGS, UnaryFunction1DDouble_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DDouble_getIntegrationType, METH_NOARGS, UnaryFunction1DDouble_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DDouble type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DDouble_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DDouble", /* tp_name */
+ sizeof(BPy_UnaryFunction1DDouble), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DDouble___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DDouble___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DDouble___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DDouble___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DDouble_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DDouble___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
new file mode 100644
index 00000000000..9a9170cfe17
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DDouble_Type;
+
+#define BPy_UnaryFunction1DDouble_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DDouble_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DDouble structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<double> *uf1D_double;
+} BPy_UnaryFunction1DDouble;
+
+/*---------------------------Python BPy_UnaryFunction1DDouble visible prototypes-----------*/
+int UnaryFunction1DDouble_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DDOUBLE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
new file mode 100644
index 00000000000..9cff857cdbe
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp
@@ -0,0 +1,208 @@
+#include "BPy_UnaryFunction1DEdgeNature.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DEdgeNature_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DEdgeNature_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DEdgeNature_Type );
+ PyModule_AddObject(module, "UnaryFunction1DEdgeNature", (PyObject *)&UnaryFunction1DEdgeNature_Type);
+
+ if( PyType_Ready( &CurveNatureF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &CurveNatureF1D_Type );
+ PyModule_AddObject(module, "CurveNatureF1D", (PyObject *)&CurveNatureF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DEdgeNature___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a :class:`Nature` object.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DEdgeNature___init__(BPy_UnaryFunction1DEdgeNature* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>();
+ else {
+ self->uf1D_edgenature = new UnaryFunction1D<Nature::EdgeNature>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_edgenature->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DEdgeNature___dealloc__(BPy_UnaryFunction1DEdgeNature* self)
+{
+ if (self->uf1D_edgenature)
+ delete self->uf1D_edgenature;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DEdgeNature___repr__(BPy_UnaryFunction1DEdgeNature* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_edgenature->getName().c_str(), self->uf1D_edgenature );
+}
+
+static char UnaryFunction1DEdgeNature_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DEdgeNature_getName( BPy_UnaryFunction1DEdgeNature *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_edgenature->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DEdgeNature___call__( BPy_UnaryFunction1DEdgeNature *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_edgenature)) == typeid(UnaryFunction1D<Nature::EdgeNature>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_edgenature->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_edgenature->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return BPy_Nature_from_Nature( self->uf1D_edgenature->result );
+
+}
+
+static char UnaryFunction1DEdgeNature_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DEdgeNature_setIntegrationType(BPy_UnaryFunction1DEdgeNature* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_edgenature->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DEdgeNature_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DEdgeNature_getIntegrationType(BPy_UnaryFunction1DEdgeNature* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_edgenature->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DEdgeNature instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DEdgeNature_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DEdgeNature_getName, METH_NOARGS, UnaryFunction1DEdgeNature_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DEdgeNature_setIntegrationType, METH_VARARGS, UnaryFunction1DEdgeNature_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DEdgeNature_getIntegrationType, METH_NOARGS, UnaryFunction1DEdgeNature_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DEdgeNature type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DEdgeNature_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DEdgeNature", /* tp_name */
+ sizeof(BPy_UnaryFunction1DEdgeNature), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DEdgeNature___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DEdgeNature___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DEdgeNature___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DEdgeNature___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DEdgeNature_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DEdgeNature___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h
new file mode 100644
index 00000000000..05e3e522c4b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h
@@ -0,0 +1,36 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../winged_edge/Nature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DEdgeNature_Type;
+
+#define BPy_UnaryFunction1DEdgeNature_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DEdgeNature_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DEdgeNature structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Nature::EdgeNature> *uf1D_edgenature;
+} BPy_UnaryFunction1DEdgeNature;
+
+/*---------------------------Python BPy_UnaryFunction1DEdgeNature visible prototypes-----------*/
+int UnaryFunction1DEdgeNature_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DEDGENATURE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
new file mode 100644
index 00000000000..ff20ee6d7c4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp
@@ -0,0 +1,201 @@
+#include "BPy_UnaryFunction1DFloat.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DFloat_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DFloat_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DFloat_Type );
+ PyModule_AddObject(module, "UnaryFunction1DFloat", (PyObject *)&UnaryFunction1DFloat_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DFloat___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a float value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DFloat___init__(BPy_UnaryFunction1DFloat* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_float = new UnaryFunction1D<float>();
+ else {
+ self->uf1D_float = new UnaryFunction1D<float>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_float->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DFloat___dealloc__(BPy_UnaryFunction1DFloat* self)
+{
+ if (self->uf1D_float)
+ delete self->uf1D_float;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DFloat___repr__(BPy_UnaryFunction1DFloat* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_float->getName().c_str(), self->uf1D_float );
+}
+
+static char UnaryFunction1DFloat_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DFloat_getName( BPy_UnaryFunction1DFloat *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_float->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DFloat___call__( BPy_UnaryFunction1DFloat *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_float)) == typeid(UnaryFunction1D<float>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_float->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_float->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyFloat_FromDouble( self->uf1D_float->result );
+
+}
+
+static char UnaryFunction1DFloat_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DFloat_setIntegrationType(BPy_UnaryFunction1DFloat* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_float->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DFloat_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DFloat_getIntegrationType(BPy_UnaryFunction1DFloat* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_float->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DFloat instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DFloat_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DFloat_getName, METH_NOARGS, UnaryFunction1DFloat_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DFloat_setIntegrationType, METH_VARARGS, UnaryFunction1DFloat_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DFloat_getIntegrationType, METH_NOARGS, UnaryFunction1DFloat_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DFloat type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DFloat_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DFloat", /* tp_name */
+ sizeof(BPy_UnaryFunction1DFloat), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DFloat___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DFloat___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DFloat___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DFloat___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DFloat_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DFloat___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
new file mode 100644
index 00000000000..529b382372e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DFloat_Type;
+
+#define BPy_UnaryFunction1DFloat_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DFloat_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DFloat structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<float> *uf1D_float;
+} BPy_UnaryFunction1DFloat;
+
+/*---------------------------Python BPy_UnaryFunction1DFloat visible prototypes-----------*/
+int UnaryFunction1DFloat_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DFLOAT_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
new file mode 100644
index 00000000000..bbdfd8dc4f2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp
@@ -0,0 +1,208 @@
+#include "BPy_UnaryFunction1DUnsigned.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DUnsigned_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DUnsigned_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DUnsigned_Type );
+ PyModule_AddObject(module, "UnaryFunction1DUnsigned", (PyObject *)&UnaryFunction1DUnsigned_Type);
+
+ if( PyType_Ready( &QuantitativeInvisibilityF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &QuantitativeInvisibilityF1D_Type );
+ PyModule_AddObject(module, "QuantitativeInvisibilityF1D", (PyObject *)&QuantitativeInvisibilityF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DUnsigned___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return an int value.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DUnsigned___init__(BPy_UnaryFunction1DUnsigned* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_unsigned = new UnaryFunction1D<unsigned int>();
+ else {
+ self->uf1D_unsigned = new UnaryFunction1D<unsigned int>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_unsigned->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DUnsigned___dealloc__(BPy_UnaryFunction1DUnsigned* self)
+{
+ if (self->uf1D_unsigned)
+ delete self->uf1D_unsigned;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DUnsigned___repr__(BPy_UnaryFunction1DUnsigned* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_unsigned->getName().c_str(), self->uf1D_unsigned );
+}
+
+static char UnaryFunction1DUnsigned_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DUnsigned_getName( BPy_UnaryFunction1DUnsigned *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_unsigned->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DUnsigned___call__( BPy_UnaryFunction1DUnsigned *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_unsigned)) == typeid(UnaryFunction1D<unsigned int>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_unsigned->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_unsigned->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return PyLong_FromLong( self->uf1D_unsigned->result );
+
+}
+
+static char UnaryFunction1DUnsigned_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DUnsigned_setIntegrationType(BPy_UnaryFunction1DUnsigned* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_unsigned->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DUnsigned_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DUnsigned_getIntegrationType(BPy_UnaryFunction1DUnsigned* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_unsigned->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DUnsigned instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DUnsigned_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DUnsigned_getName, METH_NOARGS, UnaryFunction1DUnsigned_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DUnsigned_setIntegrationType, METH_VARARGS, UnaryFunction1DUnsigned_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DUnsigned_getIntegrationType, METH_NOARGS, UnaryFunction1DUnsigned_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DUnsigned type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DUnsigned_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DUnsigned", /* tp_name */
+ sizeof(BPy_UnaryFunction1DUnsigned), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DUnsigned___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DUnsigned___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DUnsigned___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DUnsigned___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DUnsigned_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DUnsigned___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h
new file mode 100644
index 00000000000..c70cc6257a7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DUnsigned_Type;
+
+#define BPy_UnaryFunction1DUnsigned_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DUnsigned_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DUnsigned structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<unsigned int> *uf1D_unsigned;
+} BPy_UnaryFunction1DUnsigned;
+
+/*---------------------------Python BPy_UnaryFunction1DUnsigned visible prototypes-----------*/
+int UnaryFunction1DUnsigned_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DUNSIGNED_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
new file mode 100644
index 00000000000..1847c72bbeb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp
@@ -0,0 +1,214 @@
+#include "BPy_UnaryFunction1DVec2f.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h"
+#include "UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVec2f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVec2f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVec2f_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVec2f", (PyObject *)&UnaryFunction1DVec2f_Type);
+
+ if( PyType_Ready( &Normal2DF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Normal2DF1D_Type );
+ PyModule_AddObject(module, "Normal2DF1D", (PyObject *)&Normal2DF1D_Type);
+
+ if( PyType_Ready( &Orientation2DF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Orientation2DF1D_Type );
+ PyModule_AddObject(module, "Orientation2DF1D", (PyObject *)&Orientation2DF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVec2f___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a 2D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVec2f___init__(BPy_UnaryFunction1DVec2f* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_vec2f = new UnaryFunction1D<Vec2f>();
+ else {
+ self->uf1D_vec2f = new UnaryFunction1D<Vec2f>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_vec2f->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVec2f___dealloc__(BPy_UnaryFunction1DVec2f* self)
+{
+ if (self->uf1D_vec2f)
+ delete self->uf1D_vec2f;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DVec2f___repr__(BPy_UnaryFunction1DVec2f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vec2f->getName().c_str(), self->uf1D_vec2f );
+}
+
+static char UnaryFunction1DVec2f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DVec2f_getName( BPy_UnaryFunction1DVec2f *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_vec2f->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DVec2f___call__( BPy_UnaryFunction1DVec2f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_vec2f)) == typeid(UnaryFunction1D<Vec2f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vec2f->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_vec2f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec2f( self->uf1D_vec2f->result );
+
+}
+
+static char UnaryFunction1DVec2f_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVec2f_setIntegrationType(BPy_UnaryFunction1DVec2f* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_vec2f->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVec2f_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVec2f_getIntegrationType(BPy_UnaryFunction1DVec2f* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_vec2f->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVec2f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVec2f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVec2f_getName, METH_NOARGS, UnaryFunction1DVec2f_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVec2f_setIntegrationType, METH_VARARGS, UnaryFunction1DVec2f_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVec2f_getIntegrationType, METH_NOARGS, UnaryFunction1DVec2f_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVec2f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVec2f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVec2f", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVec2f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVec2f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVec2f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVec2f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVec2f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVec2f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVec2f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h
new file mode 100644
index 00000000000..64a616e211a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVec2f_Type;
+
+#define BPy_UnaryFunction1DVec2f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVec2f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVec2f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Vec2f> *uf1D_vec2f;
+} BPy_UnaryFunction1DVec2f;
+
+/*---------------------------Python BPy_UnaryFunction1DVec2f visible prototypes-----------*/
+int UnaryFunction1DVec2f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVEC2F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
new file mode 100644
index 00000000000..ae31fd5c9fd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp
@@ -0,0 +1,208 @@
+#include "BPy_UnaryFunction1DVec3f.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVec3f_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVec3f_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVec3f_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVec3f", (PyObject *)&UnaryFunction1DVec3f_Type);
+
+ if( PyType_Ready( &Orientation3DF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &Orientation3DF1D_Type );
+ PyModule_AddObject(module, "Orientation3DF1D", (PyObject *)&Orientation3DF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVec3f___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a 3D vector.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+int UnaryFunction1DVec3f___init__(BPy_UnaryFunction1DVec3f* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_vec3f = new UnaryFunction1D<Vec3f>();
+ else {
+ self->uf1D_vec3f = new UnaryFunction1D<Vec3f>( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_vec3f->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+void UnaryFunction1DVec3f___dealloc__(BPy_UnaryFunction1DVec3f* self)
+{
+ if (self->uf1D_vec3f)
+ delete self->uf1D_vec3f;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+
+PyObject * UnaryFunction1DVec3f___repr__(BPy_UnaryFunction1DVec3f* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vec3f->getName().c_str(), self->uf1D_vec3f );
+}
+
+static char UnaryFunction1DVec3f_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+PyObject * UnaryFunction1DVec3f_getName( BPy_UnaryFunction1DVec3f *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_vec3f->getName().c_str() );
+}
+
+PyObject * UnaryFunction1DVec3f___call__( BPy_UnaryFunction1DVec3f *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_vec3f)) == typeid(UnaryFunction1D<Vec3f>) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vec3f->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_vec3f->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ return Vector_from_Vec3f( self->uf1D_vec3f->result );
+
+}
+
+static char UnaryFunction1DVec3f_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+PyObject * UnaryFunction1DVec3f_setIntegrationType(BPy_UnaryFunction1DVec3f* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_vec3f->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVec3f_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+PyObject * UnaryFunction1DVec3f_getIntegrationType(BPy_UnaryFunction1DVec3f* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_vec3f->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVec3f instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVec3f_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVec3f_getName, METH_NOARGS, UnaryFunction1DVec3f_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVec3f_setIntegrationType, METH_VARARGS, UnaryFunction1DVec3f_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVec3f_getIntegrationType, METH_NOARGS, UnaryFunction1DVec3f_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVec3f type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVec3f_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVec3f", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVec3f), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVec3f___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVec3f___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVec3f___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVec3f___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVec3f_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVec3f___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h
new file mode 100644
index 00000000000..7730271fc09
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include "../../geometry/Geom.h"
+using namespace Geometry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVec3f_Type;
+
+#define BPy_UnaryFunction1DVec3f_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVec3f_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVec3f structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D<Vec3f> *uf1D_vec3f;
+} BPy_UnaryFunction1DVec3f;
+
+/*---------------------------Python BPy_UnaryFunction1DVec3f visible prototypes-----------*/
+int UnaryFunction1DVec3f_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVEC3F_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
new file mode 100644
index 00000000000..4a0787e24cc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp
@@ -0,0 +1,225 @@
+#include "BPy_UnaryFunction1DVectorViewShape.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h"
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h"
+#include "UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVectorViewShape_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVectorViewShape_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVectorViewShape_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVectorViewShape", (PyObject *)&UnaryFunction1DVectorViewShape_Type);
+
+ if( PyType_Ready( &GetOccludeeF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludeeF1D_Type );
+ PyModule_AddObject(module, "GetOccludeeF1D", (PyObject *)&GetOccludeeF1D_Type);
+
+ if( PyType_Ready( &GetOccludersF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetOccludersF1D_Type );
+ PyModule_AddObject(module, "GetOccludersF1D", (PyObject *)&GetOccludersF1D_Type);
+
+ if( PyType_Ready( &GetShapeF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &GetShapeF1D_Type );
+ PyModule_AddObject(module, "GetShapeF1D", (PyObject *)&GetShapeF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVectorViewShape___doc__[] =
+"Base class for unary functions (functors) that work on\n"
+":class:`Interface1D` and return a list of :class:`ViewShape`\n"
+"objects.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVectorViewShape___init__(BPy_UnaryFunction1DVectorViewShape* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >();
+ else {
+ self->uf1D_vectorviewshape = new UnaryFunction1D< std::vector<ViewShape*> >( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_vectorviewshape->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVectorViewShape___dealloc__(BPy_UnaryFunction1DVectorViewShape* self)
+{
+ if (self->uf1D_vectorviewshape)
+ delete self->uf1D_vectorviewshape;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DVectorViewShape___repr__(BPy_UnaryFunction1DVectorViewShape* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_vectorviewshape->getName().c_str(), self->uf1D_vectorviewshape );
+}
+
+static char UnaryFunction1DVectorViewShape_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DVectorViewShape_getName( BPy_UnaryFunction1DVectorViewShape *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_vectorviewshape->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DVectorViewShape___call__( BPy_UnaryFunction1DVectorViewShape *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_vectorviewshape)) == typeid(UnaryFunction1D< std::vector<ViewShape*> >) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_vectorviewshape->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_vectorviewshape->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ PyObject *list = PyList_New(0);
+
+ for( unsigned int i = 0; i < self->uf1D_vectorviewshape->result.size(); i++)
+ PyList_Append(list, BPy_ViewShape_from_ViewShape(*( self->uf1D_vectorviewshape->result[i] )) );
+
+ return list;
+}
+
+static char UnaryFunction1DVectorViewShape_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVectorViewShape_setIntegrationType(BPy_UnaryFunction1DVectorViewShape* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_vectorviewshape->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVectorViewShape_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVectorViewShape_getIntegrationType(BPy_UnaryFunction1DVectorViewShape* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_vectorviewshape->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVectorViewShape instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVectorViewShape_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVectorViewShape_getName, METH_NOARGS, UnaryFunction1DVectorViewShape_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVectorViewShape_setIntegrationType, METH_VARARGS, UnaryFunction1DVectorViewShape_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVectorViewShape_getIntegrationType, METH_NOARGS, UnaryFunction1DVectorViewShape_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVectorViewShape type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVectorViewShape_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVectorViewShape", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVectorViewShape), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVectorViewShape___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVectorViewShape___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVectorViewShape___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVectorViewShape___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVectorViewShape_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVectorViewShape___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h
new file mode 100644
index 00000000000..e2321a6107f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h
@@ -0,0 +1,37 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#include <vector>
+#include "../../view_map/ViewMap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVectorViewShape_Type;
+
+#define BPy_UnaryFunction1DVectorViewShape_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVectorViewShape_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVectorViewShape structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D< std::vector<ViewShape*> > *uf1D_vectorviewshape;
+} BPy_UnaryFunction1DVectorViewShape;
+
+/*---------------------------Python BPy_UnaryFunction1DVectorViewShape visible prototypes-----------*/
+int UnaryFunction1DVectorViewShape_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVECTORVIEWSHAPE_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
new file mode 100644
index 00000000000..ddc75d34462
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp
@@ -0,0 +1,220 @@
+#include "BPy_UnaryFunction1DVoid.h"
+
+#include "../BPy_Convert.h"
+#include "../BPy_Interface1D.h"
+#include "../BPy_IntegrationType.h"
+
+#include "UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h"
+#include "UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h"
+#include "UnaryFunction1D_void/BPy_TimeStampF1D.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//-------------------MODULE INITIALIZATION--------------------------------
+
+int UnaryFunction1DVoid_Init( PyObject *module ) {
+
+ if( module == NULL )
+ return -1;
+
+ if( PyType_Ready( &UnaryFunction1DVoid_Type ) < 0 )
+ return -1;
+ Py_INCREF( &UnaryFunction1DVoid_Type );
+ PyModule_AddObject(module, "UnaryFunction1DVoid", (PyObject *)&UnaryFunction1DVoid_Type);
+
+ if( PyType_Ready( &ChainingTimeStampF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &ChainingTimeStampF1D_Type );
+ PyModule_AddObject(module, "ChainingTimeStampF1D", (PyObject *)&ChainingTimeStampF1D_Type);
+
+ if( PyType_Ready( &IncrementChainingTimeStampF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &IncrementChainingTimeStampF1D_Type );
+ PyModule_AddObject(module, "IncrementChainingTimeStampF1D", (PyObject *)&IncrementChainingTimeStampF1D_Type);
+
+ if( PyType_Ready( &TimeStampF1D_Type ) < 0 )
+ return -1;
+ Py_INCREF( &TimeStampF1D_Type );
+ PyModule_AddObject(module, "TimeStampF1D", (PyObject *)&TimeStampF1D_Type);
+
+ return 0;
+}
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char UnaryFunction1DVoid___doc__[] =
+"Base class for unary functions (functors) working on\n"
+":class:`Interface1D`.\n"
+"\n"
+".. method:: __init__()\n"
+"\n"
+" Default constructor.\n"
+"\n"
+".. method:: __init__(integration)\n"
+"\n"
+" Builds a unary 1D function using the integration method given as\n"
+" argument.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static int UnaryFunction1DVoid___init__(BPy_UnaryFunction1DVoid* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ if( !obj )
+ self->uf1D_void = new UnaryFunction1D_void();
+ else {
+ self->uf1D_void = new UnaryFunction1D_void( IntegrationType_from_BPy_IntegrationType(obj) );
+ }
+
+ self->uf1D_void->py_uf1D = (PyObject *)self;
+
+ return 0;
+}
+
+static void UnaryFunction1DVoid___dealloc__(BPy_UnaryFunction1DVoid* self)
+{
+ if (self->uf1D_void)
+ delete self->uf1D_void;
+ UnaryFunction1D_Type.tp_dealloc((PyObject*)self);
+}
+
+static PyObject * UnaryFunction1DVoid___repr__(BPy_UnaryFunction1DVoid* self)
+{
+ return PyUnicode_FromFormat("type: %s - address: %p", self->uf1D_void->getName().c_str(), self->uf1D_void );
+}
+
+static char UnaryFunction1DVoid_getName___doc__[] =
+".. method:: getName()\n"
+"\n"
+" Returns the name of the unary 1D function.\n"
+"\n"
+" :return: The name of the unary 1D function.\n"
+" :rtype: string\n";
+
+static PyObject * UnaryFunction1DVoid_getName( BPy_UnaryFunction1DVoid *self )
+{
+ return PyUnicode_FromFormat( self->uf1D_void->getName().c_str() );
+}
+
+static PyObject * UnaryFunction1DVoid___call__( BPy_UnaryFunction1DVoid *self, PyObject *args, PyObject *kwds)
+{
+ PyObject *obj;
+
+ if( kwds != NULL ) {
+ PyErr_SetString(PyExc_TypeError, "keyword argument(s) not supported");
+ return NULL;
+ }
+ if( !PyArg_ParseTuple(args, "O!", &Interface1D_Type, &obj) )
+ return NULL;
+
+ if( typeid(*(self->uf1D_void)) == typeid(UnaryFunction1D_void) ) {
+ PyErr_SetString(PyExc_TypeError, "__call__ method not properly overridden");
+ return NULL;
+ }
+ if (self->uf1D_void->operator()(*( ((BPy_Interface1D *) obj)->if1D )) < 0) {
+ if (!PyErr_Occurred()) {
+ string msg(self->uf1D_void->getName() + " __call__ method failed");
+ PyErr_SetString(PyExc_RuntimeError, msg.c_str());
+ }
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVoid_setIntegrationType___doc__[] =
+".. method:: setIntegrationType(integration)\n"
+"\n"
+" Sets the integration method.\n"
+"\n"
+" :arg integration: An integration method.\n"
+" :type integration: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVoid_setIntegrationType(BPy_UnaryFunction1DVoid* self, PyObject *args)
+{
+ PyObject *obj;
+
+ if( !PyArg_ParseTuple(args, "O!", &IntegrationType_Type, &obj) )
+ return NULL;
+
+ self->uf1D_void->setIntegrationType( IntegrationType_from_BPy_IntegrationType(obj) );
+ Py_RETURN_NONE;
+}
+
+static char UnaryFunction1DVoid_getIntegrationType___doc__[] =
+".. method:: getIntegrationType(integration)\n"
+"\n"
+" Returns the integration method.\n"
+"\n"
+" :return: The integration method.\n"
+" :rtype: :class:`IntegrationType`\n";
+
+static PyObject * UnaryFunction1DVoid_getIntegrationType(BPy_UnaryFunction1DVoid* self) {
+ return BPy_IntegrationType_from_IntegrationType( self->uf1D_void->getIntegrationType() );
+}
+
+/*----------------------UnaryFunction1DVoid instance definitions ----------------------------*/
+static PyMethodDef BPy_UnaryFunction1DVoid_methods[] = {
+ {"getName", ( PyCFunction ) UnaryFunction1DVoid_getName, METH_NOARGS, UnaryFunction1DVoid_getName___doc__},
+ {"setIntegrationType", ( PyCFunction ) UnaryFunction1DVoid_setIntegrationType, METH_VARARGS, UnaryFunction1DVoid_setIntegrationType___doc__},
+ {"getIntegrationType", ( PyCFunction ) UnaryFunction1DVoid_getIntegrationType, METH_NOARGS, UnaryFunction1DVoid_getIntegrationType___doc__},
+ {NULL, NULL, 0, NULL}
+};
+
+/*-----------------------BPy_UnaryFunction1DVoid type definition ------------------------------*/
+
+PyTypeObject UnaryFunction1DVoid_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "UnaryFunction1DVoid", /* tp_name */
+ sizeof(BPy_UnaryFunction1DVoid), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)UnaryFunction1DVoid___dealloc__, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ (reprfunc)UnaryFunction1DVoid___repr__, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ (ternaryfunc)UnaryFunction1DVoid___call__, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ UnaryFunction1DVoid___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ BPy_UnaryFunction1DVoid_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)UnaryFunction1DVoid___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
new file mode 100644
index 00000000000..af907aeec84
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h
@@ -0,0 +1,34 @@
+#ifndef FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H
+#define FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H
+
+#include "../BPy_UnaryFunction1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject UnaryFunction1DVoid_Type;
+
+#define BPy_UnaryFunction1DVoid_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &UnaryFunction1DVoid_Type) )
+
+/*---------------------------Python BPy_UnaryFunction1DVoid structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1D py_uf1D;
+ UnaryFunction1D_void *uf1D_void;
+} BPy_UnaryFunction1DVoid;
+
+/*---------------------------Python BPy_UnaryFunction1DVoid visible prototypes-----------*/
+int UnaryFunction1DVoid_Init( PyObject *module );
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_UNARYFUNCTION1DVOID_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
new file mode 100644
index 00000000000..3ee5daec439
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp
@@ -0,0 +1,97 @@
+#include "BPy_CurveNatureF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char CurveNatureF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a CurveNatureF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the nature of the Interface1D (silhouette, ridge, crease,\n"
+" and so on). Except if the Interface1D is a :class:`ViewEdge`, this\n"
+" result might be ambiguous. Indeed, the Interface1D might result\n"
+" from the gathering of several 1D elements, each one being of a\n"
+" different nature. An integration method, such as the MEAN, might\n"
+" give, in this case, irrelevant results.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The nature of the Interface1D.\n"
+" :rtype: :class:`Nature`\n";
+
+static int CurveNatureF1D___init__( BPy_CurveNatureF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_edgenature.uf1D_edgenature = new Functions1D::CurveNatureF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_CurveNatureF1D type definition ------------------------------*/
+
+PyTypeObject CurveNatureF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "CurveNatureF1D", /* tp_name */
+ sizeof(BPy_CurveNatureF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ CurveNatureF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DEdgeNature_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)CurveNatureF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
new file mode 100644
index 00000000000..852f8937954
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVENATUREF1D_H
+#define FREESTYLE_PYTHON_CURVENATUREF1D_H
+
+#include "../BPy_UnaryFunction1DEdgeNature.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject CurveNatureF1D_Type;
+
+#define BPy_CurveNatureF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &CurveNatureF1D_Type) )
+
+/*---------------------------Python BPy_CurveNatureF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DEdgeNature py_uf1D_edgenature;
+} BPy_CurveNatureF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVENATUREF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
new file mode 100644
index 00000000000..f5ae4e885de
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_Normal2DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Normal2DF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a Normal2DF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D normal for the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D normal for the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Normal2DF1D___init__( BPy_Normal2DF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Normal2DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Normal2DF1D type definition ------------------------------*/
+
+PyTypeObject Normal2DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Normal2DF1D", /* tp_name */
+ sizeof(BPy_Normal2DF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Normal2DF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Normal2DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
new file mode 100644
index 00000000000..32078558d0c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_NORMAL2DF1D_H
+#define FREESTYLE_PYTHON_NORMAL2DF1D_H
+
+#include "../BPy_UnaryFunction1DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Normal2DF1D_Type;
+
+#define BPy_Normal2DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Normal2DF1D_Type) )
+
+/*---------------------------Python BPy_Normal2DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec2f py_uf1D_vec2f;
+} BPy_Normal2DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_NORMAL2DF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
new file mode 100644
index 00000000000..c83ea650cb2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp
@@ -0,0 +1,94 @@
+#include "BPy_Orientation2DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Orientation2DF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds an Orientation2DF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D orientation of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D orientation of the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Orientation2DF1D___init__( BPy_Orientation2DF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec2f.uf1D_vec2f = new Functions1D::Orientation2DF1D(t);
+ return 0;
+
+}
+
+
+/*-----------------------BPy_Orientation2DF1D type definition ------------------------------*/
+
+PyTypeObject Orientation2DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Orientation2DF1D", /* tp_name */
+ sizeof(BPy_Orientation2DF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Orientation2DF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVec2f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Orientation2DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
new file mode 100644
index 00000000000..189ab04db4f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ORIENTATION2DF1D_H
+#define FREESTYLE_PYTHON_ORIENTATION2DF1D_H
+
+#include "../BPy_UnaryFunction1DVec2f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Orientation2DF1D_Type;
+
+#define BPy_Orientation2DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Orientation2DF1D_Type) )
+
+/*---------------------------Python BPy_Orientation2DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec2f py_uf1D_vec2f;
+} BPy_Orientation2DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ORIENTATION2DF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
new file mode 100644
index 00000000000..41339111906
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_Orientation3DF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Orientation3DF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds an Orientation3DF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 3D orientation of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 3D orientation of the Interface1D.\n"
+" :rtype: :class:`mathutils.Vector`\n";
+
+static int Orientation3DF1D___init__( BPy_Orientation3DF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_vec3f.uf1D_vec3f = new Functions1D::Orientation3DF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_Orientation3DF1D type definition ------------------------------*/
+
+PyTypeObject Orientation3DF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Orientation3DF1D", /* tp_name */
+ sizeof(BPy_Orientation3DF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Orientation3DF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVec3f_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Orientation3DF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
new file mode 100644
index 00000000000..b69baf106f4
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ORIENTATION3DF1D_H
+#define FREESTYLE_PYTHON_ORIENTATION3DF1D_H
+
+#include "../BPy_UnaryFunction1DVec3f.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Orientation3DF1D_Type;
+
+#define BPy_Orientation3DF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Orientation3DF1D_Type) )
+
+/*---------------------------Python BPy_Orientation3DF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVec3f py_uf1D_vec3f;
+} BPy_Orientation3DF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ORIENTATION3DF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
new file mode 100644
index 00000000000..da80aaa0b6e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_Curvature2DAngleF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char Curvature2DAngleF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a Curvature2DAngleF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the 2D curvature as an angle for an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The 2D curvature as an angle.\n"
+" :rtype: float\n";
+
+static int Curvature2DAngleF1D___init__( BPy_Curvature2DAngleF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::Curvature2DAngleF1D(t);
+ return 0;
+
+}
+/*-----------------------BPy_Curvature2DAngleF1D type definition ------------------------------*/
+
+PyTypeObject Curvature2DAngleF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "Curvature2DAngleF1D", /* tp_name */
+ sizeof(BPy_Curvature2DAngleF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ Curvature2DAngleF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)Curvature2DAngleF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
new file mode 100644
index 00000000000..1603a7dc4ea
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H
+#define FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject Curvature2DAngleF1D_Type;
+
+#define BPy_Curvature2DAngleF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &Curvature2DAngleF1D_Type) )
+
+/*---------------------------Python BPy_Curvature2DAngleF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_Curvature2DAngleF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CURVATURE2DANGLEF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
new file mode 100644
index 00000000000..7035375a3f6
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp
@@ -0,0 +1,107 @@
+#include "BPy_DensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityF1D___doc__[] =
+".. method:: __init__(sigma=2.0, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a DensityF1D object.\n"
+"\n"
+" :arg sigma: The sigma used in DensityF0D and determining the window size\n"
+" used in each density query.\n"
+" :type sigma: float\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D. The density is\n"
+" evaluated for a set of points along the Interface1D (using the\n"
+" :class:`DensityF0D` functor) with a user-defined sampling and then\n"
+" integrated into a single value using a user-defined integration\n"
+" method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density evaluated for an Interface1D.\n"
+" :rtype: float\n";
+
+static int DensityF1D___init__( BPy_DensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ double d = 2.0;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "|dO!f", &d, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::DensityF1D(d,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_DensityF1D type definition ------------------------------*/
+
+PyTypeObject DensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityF1D", /* tp_name */
+ sizeof(BPy_DensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
new file mode 100644
index 00000000000..36426536b36
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_DENSITYF1D_H
+#define FREESTYLE_PYTHON_DENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityF1D_Type;
+
+#define BPy_DensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityF1D_Type) )
+
+/*---------------------------Python BPy_DensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_DensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_DENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..5343d9e3236
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp
@@ -0,0 +1,108 @@
+#include "BPy_GetCompleteViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetCompleteViewMapDensityF1D___doc__[] =
+".. method:: __init__(level, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetCompleteViewMapDensityF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D in the complete\n"
+" viewmap image. The density is evaluated for a set of points along\n"
+" the Interface1D (using the :class:`ReadCompleteViewMapPixelF0D`\n"
+" functor) and then integrated into a single value using a\n"
+" user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density evaluated for the Interface1D in the complete\n"
+" viewmap image.\n"
+" :rtype: float\n";
+
+static int GetCompleteViewMapDensityF1D___init__( BPy_GetCompleteViewMapDensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ unsigned i;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetCompleteViewMapDensityF1D(i,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetCompleteViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetCompleteViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetCompleteViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetCompleteViewMapDensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetCompleteViewMapDensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetCompleteViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
new file mode 100644
index 00000000000..5963b820348
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H
+#define FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetCompleteViewMapDensityF1D_Type;
+
+#define BPy_GetCompleteViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetCompleteViewMapDensityF1D_Type) )
+
+/*---------------------------Python BPy_GetCompleteViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetCompleteViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETCOMPLETEVIEWMAPDENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..5f543c30027
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp
@@ -0,0 +1,112 @@
+#include "BPy_GetDirectionalViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetDirectionalViewMapDensityF1D___doc__[] =
+".. method:: __init__(iOrientation, level, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetDirectionalViewMapDensityF1D object.\n"
+"\n"
+" :arg iOrientation: The number of the directional map we must work\n"
+" with.\n"
+" :type iOrientation: int\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density evaluated for an Interface1D in of the\n"
+" steerable viewmaps image. The direction telling which Directional\n"
+" map to choose is explicitely specified by the user. The density is\n"
+" evaluated for a set of points along the Interface1D (using the\n"
+" :class:`ReadSteerableViewMapPixelF0D` functor) and then integrated\n"
+" into a single value using a user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: the density evaluated for an Interface1D in of the\n"
+" steerable viewmaps image.\n"
+" :rtype: float\n";
+
+static int GetDirectionalViewMapDensityF1D___init__( BPy_GetDirectionalViewMapDensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ unsigned int u1, u2;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "II|O!f", &u1, &u2, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetDirectionalViewMapDensityF1D(u1, u2, t, f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetDirectionalViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetDirectionalViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetDirectionalViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetDirectionalViewMapDensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetDirectionalViewMapDensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetDirectionalViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
new file mode 100644
index 00000000000..0e2d7ec2718
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H
+#define FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetDirectionalViewMapDensityF1D_Type;
+
+#define BPy_GetDirectionalViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetDirectionalViewMapDensityF1D_Type) )
+
+/*---------------------------Python BPy_GetDirectionalViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetDirectionalViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETDIRECTIONALVIEWMAPDENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
new file mode 100644
index 00000000000..3c8fa2f1f0f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp
@@ -0,0 +1,93 @@
+#include "BPy_GetProjectedXF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedXF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedXF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected X 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected X 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedXF1D___init__( BPy_GetProjectedXF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedXF1D(t);
+ return 0;
+}
+
+
+/*-----------------------BPy_GetProjectedXF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedXF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedXF1D", /* tp_name */
+ sizeof(BPy_GetProjectedXF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedXF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedXF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
new file mode 100644
index 00000000000..d799fb7b334
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDXF1D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDXF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedXF1D_Type;
+
+#define BPy_GetProjectedXF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedXF1D_Type) )
+
+/*---------------------------Python BPy_GetProjectedXF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedXF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDXF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
new file mode 100644
index 00000000000..ce655172778
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_GetProjectedYF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedYF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedYF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected Y 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected Y 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedYF1D___init__( BPy_GetProjectedYF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedYF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedYF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedYF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedYF1D", /* tp_name */
+ sizeof(BPy_GetProjectedYF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedYF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedYF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
new file mode 100644
index 00000000000..1b7fe6c6b5f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDYF1D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedYF1D_Type;
+
+#define BPy_GetProjectedYF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedYF1D_Type) )
+
+/*---------------------------Python BPy_GetProjectedYF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedYF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
new file mode 100644
index 00000000000..df1cefeab4c
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_GetProjectedZF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetProjectedZF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a GetProjectedZF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values. \n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the projected Z 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The projected Z 3D coordinate of an Interface1D.\n"
+" :rtype: float\n";
+
+static int GetProjectedZF1D___init__( BPy_GetProjectedZF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetProjectedZF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetProjectedZF1D type definition ------------------------------*/
+
+PyTypeObject GetProjectedZF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetProjectedZF1D", /* tp_name */
+ sizeof(BPy_GetProjectedZF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetProjectedZF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetProjectedZF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
new file mode 100644
index 00000000000..a87ac6f8c5e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETPROJECTEDZF1D_H
+#define FREESTYLE_PYTHON_GETPROJECTEDZF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetProjectedZF1D_Type;
+
+#define BPy_GetProjectedZF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetProjectedZF1D_Type) )
+
+/*---------------------------Python BPy_GetProjectedZF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetProjectedZF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETPROJECTEDZF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
new file mode 100644
index 00000000000..7cd08a2da0b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp
@@ -0,0 +1,105 @@
+#include "BPy_GetSteerableViewMapDensityF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetSteerableViewMapDensityF1D___doc__[] =
+".. method:: __init__(level, iType=IntegrationType.MEAN, sampling=2.0)\n"
+"\n"
+" Builds a GetSteerableViewMapDensityF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density of the ViewMap for a given Interface1D. The\n"
+" density of each :class:`FEdge` is evaluated in the proper steerable\n"
+" :class:`ViewMap` depending on its orientation.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density of the ViewMap for a given Interface1D.\n"
+" :rtype: float\n";
+
+static int GetSteerableViewMapDensityF1D___init__( BPy_GetSteerableViewMapDensityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetSteerableViewMapDensityF1D(i,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetSteerableViewMapDensityF1D type definition ------------------------------*/
+
+PyTypeObject GetSteerableViewMapDensityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetSteerableViewMapDensityF1D", /* tp_name */
+ sizeof(BPy_GetSteerableViewMapDensityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetSteerableViewMapDensityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetSteerableViewMapDensityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
new file mode 100644
index 00000000000..29880c7e9a7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H
+#define FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetSteerableViewMapDensityF1D_Type;
+
+#define BPy_GetSteerableViewMapDensityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetSteerableViewMapDensityF1D_Type) )
+/*---------------------------Python BPy_GetSteerableViewMapDensityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetSteerableViewMapDensityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETSTEERABLEVIEWMAPDENSITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
new file mode 100644
index 00000000000..b34d56b37d3
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp
@@ -0,0 +1,105 @@
+#include "BPy_GetViewMapGradientNormF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetViewMapGradientNormF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetViewMapGradientNormF1D object.\n"
+"\n"
+" :arg level: The level of the pyramid from which the pixel must be\n"
+" read.\n"
+" :type level: int\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+" :arg sampling: The resolution used to sample the chain: the\n"
+" corresponding 0D function is evaluated at each sample point and\n"
+" the result is obtained by combining the resulting values into a\n"
+" single one, following the method specified by iType.\n"
+" :type sampling: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the density of the ViewMap for a given Interface1D. The\n"
+" density of each :class:`FEdge` is evaluated in the proper steerable\n"
+" :class:`ViewMap` depending on its orientation.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The density of the ViewMap for a given Interface1D.\n"
+" :rtype: float\n";
+
+static int GetViewMapGradientNormF1D___init__( BPy_GetViewMapGradientNormF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ int i;
+ float f = 2.0;
+
+ if( !PyArg_ParseTuple(args, "i|O!f", &i, &IntegrationType_Type, &obj, &f) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetViewMapGradientNormF1D(i,t,f);
+ return 0;
+
+}
+
+/*-----------------------BPy_GetViewMapGradientNormF1D type definition ------------------------------*/
+
+PyTypeObject GetViewMapGradientNormF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetViewMapGradientNormF1D", /* tp_name */
+ sizeof(BPy_GetViewMapGradientNormF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetViewMapGradientNormF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetViewMapGradientNormF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
new file mode 100644
index 00000000000..4f07629870f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H
+#define FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetViewMapGradientNormF1D_Type;
+
+#define BPy_GetViewMapGradientNormF1D_Check(v) ( ((PyObject *) v)->ob_type == PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetViewMapGradientNormF1D_Type) )
+
+/*---------------------------Python BPy_GetViewMapGradientNormF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetViewMapGradientNormF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETVIEWMAPGRADIENTNORMF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
new file mode 100644
index 00000000000..6bbf15c0af2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp
@@ -0,0 +1,93 @@
+#include "BPy_GetXF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetXF1D___doc__[] =
+".. method:: __init__(iType)\n"
+"\n"
+" Builds a GetXF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the X 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The X 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetXF1D___init__( BPy_GetXF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetXF1D(t);
+ return 0;
+}
+
+
+/*-----------------------BPy_GetXF1D type definition ------------------------------*/
+
+PyTypeObject GetXF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetXF1D", /* tp_name */
+ sizeof(BPy_GetXF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetXF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetXF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
new file mode 100644
index 00000000000..5eae107daae
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETXF1D_H
+#define FREESTYLE_PYTHON_GETXF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetXF1D_Type;
+
+#define BPy_GetXF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetXF1D_Type) )
+
+/*---------------------------Python BPy_GetXF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetXF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETXF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
new file mode 100644
index 00000000000..7275ea3dcf2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp
@@ -0,0 +1,91 @@
+#include "BPy_GetYF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetYF1D___doc__[] =
+".. method:: __init__(iType)\n"
+"\n"
+" Builds a GetYF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Y 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Y 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetYF1D___init__( BPy_GetYF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetYF1D(t);
+ return 0;
+}
+/*-----------------------BPy_GetYF1D type definition ------------------------------*/
+
+PyTypeObject GetYF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetYF1D", /* tp_name */
+ sizeof(BPy_GetYF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetYF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetYF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
new file mode 100644
index 00000000000..5864c245776
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETYF1D_H
+#define FREESTYLE_PYTHON_GETYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetYF1D_Type;
+
+#define BPy_GetYF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetYF1D_Type) )
+
+/*---------------------------Python BPy_GetYF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetYF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
new file mode 100644
index 00000000000..68f4f5e4300
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp
@@ -0,0 +1,92 @@
+#include "BPy_GetZF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetZF1D___doc__[] =
+".. method:: __init__(iType)\n"
+"\n"
+" Builds a GetZF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Z 3D coordinate of an Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Z 3D coordinate of the Interface1D.\n"
+" :rtype: float\n";
+
+static int GetZF1D___init__( BPy_GetZF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::GetZF1D(t);
+ return 0;
+}
+
+/*-----------------------BPy_GetZF1D type definition ------------------------------*/
+
+PyTypeObject GetZF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetZF1D", /* tp_name */
+ sizeof(BPy_GetZF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetZF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetZF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
new file mode 100644
index 00000000000..4b91a567eef
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETZF1D_H
+#define FREESTYLE_PYTHON_GETZF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetZF1D_Type;
+
+#define BPy_GetZF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetZF1D_Type) )
+
+/*---------------------------Python BPy_GetZF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_GetZF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETZF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
new file mode 100644
index 00000000000..be262632466
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp
@@ -0,0 +1,99 @@
+#include "BPy_LocalAverageDepthF1D.h"
+
+#include "../../../stroke/AdvancedFunctions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char LocalAverageDepthF1D___doc__[] =
+".. method:: __init__(sigma, iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a LocalAverageDepthF1D object.\n"
+"\n"
+" :arg sigma: The sigma used in DensityF0D and determining the window\n"
+" size used in each density query.\n"
+" :type sigma: float\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the average depth evaluated for an Interface1D. The\n"
+" average depth is evaluated for a set of points along the\n"
+" Interface1D (using the :class:`LocalAverageDepthF0D` functor) with\n"
+" a user-defined sampling and then integrated into a single value\n"
+" using a user-defined integration method.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The average depth evaluated for the Interface1D.\n"
+" :rtype: float\n";
+
+static int LocalAverageDepthF1D___init__( BPy_LocalAverageDepthF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+ double d;
+
+ if( !PyArg_ParseTuple(args, "d|O!", &d, &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::LocalAverageDepthF1D(d,t);
+ return 0;
+}
+/*-----------------------BPy_LocalAverageDepthF1D type definition ------------------------------*/
+
+PyTypeObject LocalAverageDepthF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "LocalAverageDepthF1D", /* tp_name */
+ sizeof(BPy_LocalAverageDepthF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ LocalAverageDepthF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)LocalAverageDepthF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
new file mode 100644
index 00000000000..627d10b6414
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H
+#define FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject LocalAverageDepthF1D_Type;
+
+#define BPy_LocalAverageDepthF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &LocalAverageDepthF1D_Type) )
+
+/*---------------------------Python BPy_LocalAverageDepthF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_LocalAverageDepthF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_LOCALAVERAGEDEPTHF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
new file mode 100644
index 00000000000..0640644ea1e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp
@@ -0,0 +1,97 @@
+#include "BPy_ZDiscontinuityF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ZDiscontinuityF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a ZDiscontinuityF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a real value giving the distance between an Interface1D\n"
+" and the shape that lies behind (occludee). This distance is\n"
+" evaluated in the camera space and normalized between 0 and 1.\n"
+" Therefore, if no oject is occluded by the shape to which the\n"
+" Interface1D belongs to, 1 is returned.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The normalized distance between the Interface1D and the occludee.\n"
+" :rtype: float\n";
+
+static int ZDiscontinuityF1D___init__( BPy_ZDiscontinuityF1D* self, PyObject *args )
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_double.uf1D_double = new Functions1D::ZDiscontinuityF1D(t);
+ return 0;
+}
+
+
+/*-----------------------BPy_ZDiscontinuityF1D type definition ------------------------------*/
+
+PyTypeObject ZDiscontinuityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ZDiscontinuityF1D", /* tp_name */
+ sizeof(BPy_ZDiscontinuityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ZDiscontinuityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DDouble_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ZDiscontinuityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
new file mode 100644
index 00000000000..e6b4be556d7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H
+#define FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H
+
+#include "../BPy_UnaryFunction1DDouble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ZDiscontinuityF1D_Type;
+
+#define BPy_ZDiscontinuityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ZDiscontinuityF1D_Type) )
+
+/*---------------------------Python BPy_ZDiscontinuityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DDouble py_uf1D_double;
+} BPy_ZDiscontinuityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_ZDISCONTINUITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
new file mode 100644
index 00000000000..4ffa3437c69
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp
@@ -0,0 +1,97 @@
+#include "BPy_QuantitativeInvisibilityF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityF1D___doc__[] =
+".. method:: __init__(iType=IntegrationType.MEAN)\n"
+"\n"
+" Builds a QuantitativeInvisibilityF1D object.\n"
+"\n"
+" :arg iType: The integration method used to compute a single value\n"
+" from a set of values.\n"
+" :type iType: :class:`IntegrationType`\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the Quantitative Invisibility of an Interface1D element.\n"
+" If the Interface1D is a :class:`ViewEdge`, then there is no\n"
+" ambiguity concerning the result. But, if the Interface1D results\n"
+" of a chaining (chain, stroke), then it might be made of several 1D\n"
+" elements of different Quantitative Invisibilities.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: The Quantitative Invisibility of the Interface1D.\n"
+" :rtype: int\n";
+
+static int QuantitativeInvisibilityF1D___init__( BPy_QuantitativeInvisibilityF1D* self, PyObject *args)
+{
+ PyObject *obj = 0;
+
+ if( !PyArg_ParseTuple(args, "|O!", &IntegrationType_Type, &obj) )
+ return -1;
+
+ IntegrationType t = ( obj ) ? IntegrationType_from_BPy_IntegrationType(obj) : MEAN;
+ self->py_uf1D_unsigned.uf1D_unsigned = new Functions1D::QuantitativeInvisibilityF1D(t);
+ return 0;
+
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityF1D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityF1D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ QuantitativeInvisibilityF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DUnsigned_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
new file mode 100644
index 00000000000..5bcf5fcc0a2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H
+#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H
+
+#include "../BPy_UnaryFunction1DUnsigned.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityF1D_Type;
+
+#define BPy_QuantitativeInvisibilityF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityF1D_Type) )
+
+/*---------------------------Python BPy_QuantitativeInvisibilityF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DUnsigned py_uf1D_unsigned;
+} BPy_QuantitativeInvisibilityF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp
new file mode 100644
index 00000000000..a4f49922e01
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetOccludeeF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludeeF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludeeF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of occluded shapes covered by this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of occluded shapes covered by the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludeeF1D___init__( BPy_GetOccludeeF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludeeF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludeeF1D type definition ------------------------------*/
+
+PyTypeObject GetOccludeeF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludeeF1D", /* tp_name */
+ sizeof(BPy_GetOccludeeF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludeeF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludeeF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
new file mode 100644
index 00000000000..c8d5e99a6a7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDEEF1D_H
+#define FREESTYLE_PYTHON_GETOCCLUDEEF1D_H
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludeeF1D_Type;
+
+#define BPy_GetOccludeeF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludeeF1D_Type) )
+
+/*---------------------------Python BPy_GetOccludeeF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetOccludeeF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDEEF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp
new file mode 100644
index 00000000000..f4030b5b25e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetOccludersF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetOccludersF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetOccludersF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of occluding shapes that cover this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of occluding shapes that cover the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetOccludersF1D___init__( BPy_GetOccludersF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetOccludersF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetOccludersF1D type definition ------------------------------*/
+
+PyTypeObject GetOccludersF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetOccludersF1D", /* tp_name */
+ sizeof(BPy_GetOccludersF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetOccludersF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetOccludersF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
new file mode 100644
index 00000000000..ad39ad25c3d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETOCCLUDERSF1D_H
+#define FREESTYLE_PYTHON_GETOCCLUDERSF1D_H
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetOccludersF1D_Type;
+
+#define BPy_GetOccludersF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetOccludersF1D_Type) )
+
+/*---------------------------Python BPy_GetOccludersF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetOccludersF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETOCCLUDERSF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp
new file mode 100644
index 00000000000..017dbc3436d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp
@@ -0,0 +1,84 @@
+#include "BPy_GetShapeF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char GetShapeF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a GetShapeF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns a list of shapes covered by this Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: A list of shapes covered by the Interface1D.\n"
+" :rtype: list of :class:`ViewShape` objects\n";
+
+static int GetShapeF1D___init__( BPy_GetShapeF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_vectorviewshape.uf1D_vectorviewshape = new Functions1D::GetShapeF1D();
+ return 0;
+}
+
+/*-----------------------BPy_GetShapeF1D type definition ------------------------------*/
+
+PyTypeObject GetShapeF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "GetShapeF1D", /* tp_name */
+ sizeof(BPy_GetShapeF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ GetShapeF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVectorViewShape_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)GetShapeF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
new file mode 100644
index 00000000000..39d1268c03f
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_GETSHAPEF1D_H
+#define FREESTYLE_PYTHON_GETSHAPEF1D_H
+
+#include "../BPy_UnaryFunction1DVectorViewShape.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject GetShapeF1D_Type;
+
+#define BPy_GetShapeF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &GetShapeF1D_Type) )
+
+/*---------------------------Python BPy_GetShapeF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVectorViewShape py_uf1D_vectorviewshape;
+} BPy_GetShapeF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_GETSHAPEF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
new file mode 100644
index 00000000000..848e0c92843
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp
@@ -0,0 +1,82 @@
+#include "BPy_ChainingTimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ChainingTimeStampF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a ChainingTimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Sets the chaining time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int ChainingTimeStampF1D___init__( BPy_ChainingTimeStampF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::ChainingTimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_ChainingTimeStampF1D type definition ------------------------------*/
+
+PyTypeObject ChainingTimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ChainingTimeStampF1D", /* tp_name */
+ sizeof(BPy_ChainingTimeStampF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ChainingTimeStampF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ChainingTimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
new file mode 100644
index 00000000000..6855ddaf14b
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H
+#define FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ChainingTimeStampF1D_Type;
+
+#define BPy_ChainingTimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ChainingTimeStampF1D_Type) )
+
+/*---------------------------Python BPy_ChainingTimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_ChainingTimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
new file mode 100644
index 00000000000..c1bcaacffb7
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp
@@ -0,0 +1,82 @@
+#include "BPy_IncrementChainingTimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char IncrementChainingTimeStampF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds an IncrementChainingTimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Increments the chaining time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int IncrementChainingTimeStampF1D___init__( BPy_IncrementChainingTimeStampF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::IncrementChainingTimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_IncrementChainingTimeStampF1D type definition ------------------------------*/
+
+PyTypeObject IncrementChainingTimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "IncrementChainingTimeStampF1D", /* tp_name */
+ sizeof(BPy_IncrementChainingTimeStampF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ IncrementChainingTimeStampF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)IncrementChainingTimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
new file mode 100644
index 00000000000..a1d5714ab63
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H
+#define FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject IncrementChainingTimeStampF1D_Type;
+
+#define BPy_IncrementChainingTimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &IncrementChainingTimeStampF1D_Type) )
+
+/*---------------------------Python BPy_IncrementChainingTimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_IncrementChainingTimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_INCREMENTCHAININGTIMESTAMPF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
new file mode 100644
index 00000000000..e9a7f2095bb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp
@@ -0,0 +1,82 @@
+#include "BPy_TimeStampF1D.h"
+
+#include "../../../view_map/Functions1D.h"
+#include "../../BPy_Convert.h"
+#include "../../BPy_IntegrationType.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TimeStampF1D___doc__[] =
+".. method:: __init__()\n"
+"\n"
+" Builds a TimeStampF1D object.\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns the time stamp of the Interface1D.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n";
+
+static int TimeStampF1D___init__( BPy_TimeStampF1D* self, PyObject *args )
+{
+ if( !PyArg_ParseTuple(args, "") )
+ return -1;
+ self->py_uf1D_void.uf1D_void = new Functions1D::TimeStampF1D();
+ return 0;
+}
+
+/*-----------------------BPy_TimeStampF1D type definition ------------------------------*/
+
+PyTypeObject TimeStampF1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TimeStampF1D", /* tp_name */
+ sizeof(BPy_TimeStampF1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TimeStampF1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryFunction1DVoid_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TimeStampF1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
new file mode 100644
index 00000000000..d9bee247c09
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.h
@@ -0,0 +1,30 @@
+#ifndef FREESTYLE_PYTHON_TIMESTAMPF1D_H
+#define FREESTYLE_PYTHON_TIMESTAMPF1D_H
+
+#include "../BPy_UnaryFunction1DVoid.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TimeStampF1D_Type;
+
+#define BPy_TimeStampF1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TimeStampF1D_Type) )
+
+/*---------------------------Python BPy_TimeStampF1D structure definition----------*/
+typedef struct {
+ BPy_UnaryFunction1DVoid py_uf1D_void;
+} BPy_TimeStampF1D;
+
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CHAININGTIMESTAMPF1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
new file mode 100644
index 00000000000..c2c956e3eab
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp
@@ -0,0 +1,76 @@
+#include "BPy_FalseUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseUP0D___doc__[] =
+".. method:: __call__(it)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseUP0D___init__( BPy_FalseUP0D* self, PyObject *args)
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up0D.up0D = new Predicates0D::FalseUP0D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseUP0D type definition ------------------------------*/
+
+PyTypeObject FalseUP0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseUP0D", /* tp_name */
+ sizeof(BPy_FalseUP0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FalseUP0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseUP0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
new file mode 100644
index 00000000000..399941d442d
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_FALSEUP0D_H
+#define FREESTYLE_PYTHON_FALSEUP0D_H
+
+#include "../BPy_UnaryPredicate0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseUP0D_Type;
+
+#define BPy_FalseUP0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseUP0D_Type) )
+
+/*---------------------------Python BPy_FalseUP0D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate0D py_up0D;
+} BPy_FalseUP0D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FALSEUP0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
new file mode 100644
index 00000000000..9097f4e38bc
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp
@@ -0,0 +1,76 @@
+#include "BPy_TrueUP0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueUP0D___doc__[] =
+".. method:: __call__(it)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg it: An Interface0DIterator object.\n"
+" :type it: :class:`Interface0DIterator`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueUP0D___init__( BPy_TrueUP0D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up0D.up0D = new Predicates0D::TrueUP0D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP0D type definition ------------------------------*/
+
+PyTypeObject TrueUP0D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueUP0D", /* tp_name */
+ sizeof(BPy_TrueUP0D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TrueUP0D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate0D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueUP0D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
new file mode 100644
index 00000000000..24976aaa5c9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_TRUEUP0D_H
+#define FREESTYLE_PYTHON_TRUEUP0D_H
+
+#include "../BPy_UnaryPredicate0D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueUP0D_Type;
+
+#define BPy_TrueUP0D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueUP0D_Type) )
+
+/*---------------------------Python BPy_TrueUP0D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate0D py_up0D;
+} BPy_TrueUP0D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TRUEUP0D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
new file mode 100644
index 00000000000..b5a16c3c238
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp
@@ -0,0 +1,77 @@
+#include "BPy_ContourUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ContourUP1D___doc__[] =
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D is a contour. An Interface1D is a\n"
+" contour if it is borded by a different shape on each of its sides.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the Interface1D is a contour, false otherwise.\n"
+" :rtype: bool\n";
+
+static int ContourUP1D___init__( BPy_ContourUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ContourUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_ContourUP1D type definition ------------------------------*/
+
+PyTypeObject ContourUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ContourUP1D", /* tp_name */
+ sizeof(BPy_ContourUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ContourUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ContourUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
new file mode 100644
index 00000000000..a24261a60de
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_CONTOURUP1D_H
+#define FREESTYLE_PYTHON_CONTOURUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ContourUP1D_Type;
+
+#define BPy_ContourUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ContourUP1D_Type) )
+
+/*---------------------------Python BPy_ContourUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ContourUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_CONTOURUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
new file mode 100644
index 00000000000..97bd6409bf2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp
@@ -0,0 +1,93 @@
+#include "BPy_DensityLowerThanUP1D.h"
+
+#include "../../stroke/AdvancedPredicates1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char DensityLowerThanUP1D___doc__[] =
+".. method:: __init__(threshold, sigma=2.0)\n"
+"\n"
+" Builds a DensityLowerThanUP1D object.\n"
+"\n"
+" :arg threshold: The value of the threshold density. Any Interface1D\n"
+" having a density lower than this threshold will match.\n"
+" :type threshold: float\n"
+" :arg sigma: The sigma value defining the density evaluation window\n"
+" size used in the :class:`DensityF0D` functor.\n"
+" :type sigma: float\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the density evaluated for the Interface1D is less\n"
+" than a user-defined density value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the density is lower than a threshold.\n"
+" :rtype: bool\n";
+
+static int DensityLowerThanUP1D___init__( BPy_DensityLowerThanUP1D* self, PyObject *args )
+{
+ double d1, d2 = 2.0;
+
+ if( !PyArg_ParseTuple(args, "d|d", &d1, &d2) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::DensityLowerThanUP1D(d1,d2);
+ return 0;
+}
+
+/*-----------------------BPy_DensityLowerThanUP1D type definition ------------------------------*/
+
+PyTypeObject DensityLowerThanUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "DensityLowerThanUP1D", /* tp_name */
+ sizeof(BPy_DensityLowerThanUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ DensityLowerThanUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)DensityLowerThanUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
new file mode 100644
index 00000000000..2862b060a0a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H
+#define FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject DensityLowerThanUP1D_Type;
+
+#define BPy_DensityLowerThanUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &DensityLowerThanUP1D_Type) )
+
+/*---------------------------Python BPy_DensityLowerThanUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_DensityLowerThanUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_DENSITYLOWERTHANUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
new file mode 100644
index 00000000000..3a5c66aef59
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_EqualToChainingTimeStampUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char EqualToChainingTimeStampUP1D___doc__[] =
+".. method:: __init__(ts)\n"
+"\n"
+" Builds a EqualToChainingTimeStampUP1D object.\n"
+"\n"
+" :arg ts: A time stamp value.\n"
+" :type ts: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D's time stamp is equal to a certain\n"
+" user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the time stamp is equal to a user-defined value.\n"
+" :rtype: bool\n";
+
+static int EqualToChainingTimeStampUP1D___init__( BPy_EqualToChainingTimeStampUP1D* self, PyObject *args )
+{
+ unsigned u;
+
+ if( !PyArg_ParseTuple(args, "I", &u) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::EqualToChainingTimeStampUP1D(u);
+ return 0;
+}
+
+/*-----------------------BPy_EqualToChainingTimeStampUP1D type definition ------------------------------*/
+
+PyTypeObject EqualToChainingTimeStampUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "EqualToChainingTimeStampUP1D", /* tp_name */
+ sizeof(BPy_EqualToChainingTimeStampUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ EqualToChainingTimeStampUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)EqualToChainingTimeStampUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
new file mode 100644
index 00000000000..39423423b8e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H
+#define FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject EqualToChainingTimeStampUP1D_Type;
+
+#define BPy_EqualToChainingTimeStampUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &EqualToChainingTimeStampUP1D_Type) )
+
+/*---------------------------Python BPy_EqualToChainingTimeStampUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_EqualToChainingTimeStampUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_EQUALTOCHAININGTIMESTAMPUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
new file mode 100644
index 00000000000..2427f6d0169
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp
@@ -0,0 +1,87 @@
+#include "BPy_EqualToTimeStampUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char EqualToTimeStampUP1D___doc__[] =
+".. method:: __init__(ts)\n"
+"\n"
+" Builds a EqualToTimeStampUP1D object.\n"
+"\n"
+" :arg ts: A time stamp value.\n"
+" :type ts: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D's time stamp is equal to a certain\n"
+" user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the time stamp is equal to a user-defined value.\n"
+" :rtype: bool\n";
+
+static int EqualToTimeStampUP1D___init__( BPy_EqualToTimeStampUP1D* self, PyObject *args )
+{
+ unsigned u;
+
+ if( !PyArg_ParseTuple(args, "I", &u) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::EqualToTimeStampUP1D(u);
+ return 0;
+}
+
+/*-----------------------BPy_EqualToTimeStampUP1D type definition ------------------------------*/
+
+PyTypeObject EqualToTimeStampUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "EqualToTimeStampUP1D", /* tp_name */
+ sizeof(BPy_EqualToTimeStampUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ EqualToTimeStampUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)EqualToTimeStampUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
new file mode 100644
index 00000000000..538dc400dc2
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H
+#define FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject EqualToTimeStampUP1D_Type;
+
+#define BPy_EqualToTimeStampUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &EqualToTimeStampUP1D_Type) )
+
+/*---------------------------Python BPy_EqualToTimeStampUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_EqualToTimeStampUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_EQUALTOTIMESTAMPUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
new file mode 100644
index 00000000000..f94b6653c7e
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp
@@ -0,0 +1,79 @@
+#include "BPy_ExternalContourUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ExternalContourUP1D___doc__[] =
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Interface1D is an external contour. An\n"
+" Interface1D is an external contour if it is borded by no shape on\n"
+" one of its sides.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if the Interface1D is an external contour, false\n"
+" otherwise.\n"
+" :rtype: bool\n";
+
+static int ExternalContourUP1D___init__( BPy_ExternalContourUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::ExternalContourUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_ExternalContourUP1D type definition ------------------------------*/
+
+PyTypeObject ExternalContourUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ExternalContourUP1D", /* tp_name */
+ sizeof(BPy_ExternalContourUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ExternalContourUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ExternalContourUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
new file mode 100644
index 00000000000..31300f04dfe
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H
+#define FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ExternalContourUP1D_Type;
+
+#define BPy_ExternalContourUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ExternalContourUP1D_Type) )
+
+/*---------------------------Python BPy_ExternalContourUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ExternalContourUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_EXTERNALCONTOURUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
new file mode 100644
index 00000000000..fa8b145f83a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp
@@ -0,0 +1,76 @@
+#include "BPy_FalseUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char FalseUP1D___doc__[] =
+".. method:: __call__(inter)\n"
+"\n"
+" Always returns false.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: False.\n"
+" :rtype: bool\n";
+
+static int FalseUP1D___init__( BPy_FalseUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::FalseUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_FalseUP1D type definition ------------------------------*/
+
+PyTypeObject FalseUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "FalseUP1D", /* tp_name */
+ sizeof(BPy_FalseUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ FalseUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)FalseUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
new file mode 100644
index 00000000000..273e4962db9
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_FALSEUP1D_H
+#define FREESTYLE_PYTHON_FALSEUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject FalseUP1D_Type;
+
+#define BPy_FalseUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &FalseUP1D_Type) )
+
+/*---------------------------Python BPy_FalseUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_FalseUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_FALSEUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
new file mode 100644
index 00000000000..ebc27787776
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp
@@ -0,0 +1,90 @@
+#include "BPy_QuantitativeInvisibilityUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char QuantitativeInvisibilityUP1D___doc__[] =
+".. method:: __init__(qi=0)\n"
+"\n"
+" Builds a QuantitativeInvisibilityUP1D object.\n"
+"\n"
+" :arg qi: The Quantitative Invisibility you want the Interface1D to\n"
+" have.\n"
+" :type qi: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the Quantitative Invisibility evaluated at an\n"
+" Interface1D, using the :class:`QuantitativeInvisibilityF1D`\n"
+" functor, equals a certain user-defined value.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if Quantitative Invisibility equals a user-defined\n"
+" value.\n"
+" :rtype: bool\n";
+
+static int QuantitativeInvisibilityUP1D___init__( BPy_QuantitativeInvisibilityUP1D* self, PyObject *args )
+{
+ int i = 0;
+
+ if( !PyArg_ParseTuple(args, "|i", &i) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::QuantitativeInvisibilityUP1D(i);
+ return 0;
+}
+
+/*-----------------------BPy_QuantitativeInvisibilityUP1D type definition ------------------------------*/
+
+PyTypeObject QuantitativeInvisibilityUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "QuantitativeInvisibilityUP1D", /* tp_name */
+ sizeof(BPy_QuantitativeInvisibilityUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ QuantitativeInvisibilityUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)QuantitativeInvisibilityUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
new file mode 100644
index 00000000000..f120ecb9778
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H
+#define FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject QuantitativeInvisibilityUP1D_Type;
+
+#define BPy_QuantitativeInvisibilityUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &QuantitativeInvisibilityUP1D_Type) )
+
+/*---------------------------Python BPy_QuantitativeInvisibilityUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_QuantitativeInvisibilityUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_QUANTITATIVEINVISIBILITYUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
new file mode 100644
index 00000000000..50a1de751fb
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp
@@ -0,0 +1,90 @@
+#include "BPy_ShapeUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char ShapeUP1D___doc__[] =
+".. method:: __init__(idFirst, idSecond=0)\n"
+"\n"
+" Builds a ShapeUP1D object.\n"
+"\n"
+" :arg idFirst: The first Id component.\n"
+" :type idFirst: int\n"
+" :arg idSecond: The second Id component.\n"
+" :type idSecond: int\n"
+"\n"
+".. method:: __call__(inter)\n"
+"\n"
+" Returns true if the shape to which the Interface1D belongs to has\n"
+" the same :class:`Id` as the one specified by the user.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True if Interface1D belongs to the shape of the\n"
+" user-specified Id.\n"
+" :rtype: bool\n";
+
+static int ShapeUP1D___init__( BPy_ShapeUP1D* self, PyObject *args )
+{
+ unsigned u1, u2 = 0;
+
+ if( !PyArg_ParseTuple(args, "I|I", &u1, &u2) )
+ return -1;
+
+ self->py_up1D.up1D = new Predicates1D::ShapeUP1D(u1,u2);
+ return 0;
+}
+
+/*-----------------------BPy_ShapeUP1D type definition ------------------------------*/
+
+PyTypeObject ShapeUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "ShapeUP1D", /* tp_name */
+ sizeof(BPy_ShapeUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ShapeUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)ShapeUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
new file mode 100644
index 00000000000..ce6d0276edd
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_SHAPEUP1D_H
+#define FREESTYLE_PYTHON_SHAPEUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject ShapeUP1D_Type;
+
+#define BPy_ShapeUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &ShapeUP1D_Type) )
+
+/*---------------------------Python BPy_ShapeUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_ShapeUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_SHAPEUP1D_H */
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
new file mode 100644
index 00000000000..320b1eb1c31
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp
@@ -0,0 +1,76 @@
+#include "BPy_TrueUP1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+//------------------------INSTANCE METHODS ----------------------------------
+
+static char TrueUP1D___doc__[] =
+".. method:: __call__(inter)\n"
+"\n"
+" Always returns true.\n"
+"\n"
+" :arg inter: An Interface1D object.\n"
+" :type inter: :class:`Interface1D`\n"
+" :return: True.\n"
+" :rtype: bool\n";
+
+static int TrueUP1D___init__( BPy_TrueUP1D* self, PyObject *args )
+{
+ if(!( PyArg_ParseTuple(args, "") ))
+ return -1;
+ self->py_up1D.up1D = new Predicates1D::TrueUP1D();
+ return 0;
+}
+
+/*-----------------------BPy_TrueUP1D type definition ------------------------------*/
+
+PyTypeObject TrueUP1D_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "TrueUP1D", /* tp_name */
+ sizeof(BPy_TrueUP1D), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ TrueUP1D___doc__, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &UnaryPredicate1D_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc)TrueUP1D___init__, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
new file mode 100644
index 00000000000..5a01ad42d2a
--- /dev/null
+++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.h
@@ -0,0 +1,29 @@
+#ifndef FREESTYLE_PYTHON_TRUEUP1D_H
+#define FREESTYLE_PYTHON_TRUEUP1D_H
+
+#include "../BPy_UnaryPredicate1D.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Python.h>
+
+extern PyTypeObject TrueUP1D_Type;
+
+#define BPy_TrueUP1D_Check(v) ( PyObject_IsInstance( (PyObject *) v, (PyObject *) &TrueUP1D_Type) )
+
+/*---------------------------Python BPy_TrueUP1D structure definition----------*/
+typedef struct {
+ BPy_UnaryPredicate1D py_up1D;
+} BPy_TrueUP1D;
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREESTYLE_PYTHON_TRUEUP1D_H */
diff --git a/source/blender/freestyle/intern/rendering/GLBBoxRenderer.cpp b/source/blender/freestyle/intern/rendering/GLBBoxRenderer.cpp
new file mode 100755
index 00000000000..464779d6a43
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLBBoxRenderer.cpp
@@ -0,0 +1,108 @@
+
+//
+// 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 "GLBBoxRenderer.h"
+#include "../scene_graph/IndexedFaceSet.h"
+#include "../scene_graph/NodeDrawingStyle.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/NodeLight.h"
+#include "../scene_graph/NodeTransform.h"
+
+#include "../scene_graph/Rep.h"
+#include "../scene_graph/Node.h"
+
+void GLBBoxRenderer::visitIndexedFaceSet(IndexedFaceSet& iFaceSet)
+{
+ RenderRep(iFaceSet);
+}
+
+void GLBBoxRenderer::visitNodeGroup(NodeGroup& iGroupNode)
+{
+ RenderNode(iGroupNode);
+}
+
+void GLBBoxRenderer::visitNodeTransform(NodeTransform& iTransformNode)
+{
+ RenderNode(iTransformNode);
+}
+
+void GLBBoxRenderer::visitDrawingStyle(DrawingStyle& iDrawingStyle)
+{
+ if(DrawingStyle::INVISIBLE == iDrawingStyle.style())
+ return ;
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ glPolygonMode(GL_FRONT, GL_LINE);
+ glLineWidth(1.f);
+
+ glDisable(GL_LIGHTING);
+}
+
+void GLBBoxRenderer::RenderRep(const Rep& iRep) const
+{
+ RenderBBox(iRep.bbox());
+}
+
+void GLBBoxRenderer::RenderNode(const Node& iNode) const
+{
+ RenderBBox(iNode.bbox());
+}
+
+void GLBBoxRenderer::RenderBBox(const BBox<Vec3r>& iBox) const
+{
+ if(iBox.empty())
+ return;
+
+ Vec3r m = iBox.getMin();
+ Vec3r M = iBox.getMax();
+
+ glColor3f(0.f, 0.f, 0.f);
+ glBegin(GL_LINE_LOOP);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], m[1], m[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], m[1], m[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], M[1], m[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], M[1], m[2]);
+ glEnd();
+
+ glBegin(GL_LINE_LOOP);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], m[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], m[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], M[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], M[1], M[2]);
+ glEnd();
+
+ glBegin(GL_LINE_LOOP);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], m[1], m[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], m[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], M[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(m[0], M[1], m[2]);
+ glEnd();
+
+ glBegin(GL_LINE_LOOP);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], m[1], m[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], m[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], M[1], M[2]);
+ ((GLBBoxRenderer*)(this))->glVertex3r(M[0], M[1], m[2]);
+ glEnd();
+
+}
diff --git a/source/blender/freestyle/intern/rendering/GLBBoxRenderer.h b/source/blender/freestyle/intern/rendering/GLBBoxRenderer.h
new file mode 100755
index 00000000000..4bb72ba80b0
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLBBoxRenderer.h
@@ -0,0 +1,59 @@
+//
+// Filename : GLBBoxRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to render BBoxes of a 3D scene thanks to OpenGL
+// Date of creation : 07/02/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 GLBBOXRENDERER_H
+# define GLBBOXRENDERER_H
+
+# include "../system/FreestyleConfig.h"
+# include "GLRenderer.h"
+# include "../geometry/BBox.h"
+
+class Rep;
+class Node;
+
+class LIB_RENDERING_EXPORT GLBBoxRenderer : public GLRenderer
+{
+public:
+
+ inline GLBBoxRenderer() : GLRenderer() {}
+ virtual ~GLBBoxRenderer() {}
+
+ VISIT_DECL(NodeGroup)
+ VISIT_DECL(NodeTransform)
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(DrawingStyle)
+
+ protected:
+
+ void RenderRep(const Rep& iRep) const ;
+ void RenderNode(const Node& iNode) const ;
+ void RenderBBox(const BBox<Vec3r>& iBox) const ;
+};
+
+#endif // GLBBOXRENDERER_H
diff --git a/source/blender/freestyle/intern/rendering/GLBlendEquation.cpp b/source/blender/freestyle/intern/rendering/GLBlendEquation.cpp
new file mode 100644
index 00000000000..2cbd003c58e
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLBlendEquation.cpp
@@ -0,0 +1,9 @@
+#include "GLBlendEquation.h"
+
+void FRS_glBlendEquation(GLenum mode) {
+ if( glBlendEquation ) {
+ glBlendEquation(mode);
+ } else if ( glBlendEquationEXT ) {
+ glBlendEquationEXT(mode);
+ }
+}
diff --git a/source/blender/freestyle/intern/rendering/GLBlendEquation.h b/source/blender/freestyle/intern/rendering/GLBlendEquation.h
new file mode 100644
index 00000000000..89a90837bea
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLBlendEquation.h
@@ -0,0 +1,16 @@
+#ifndef GLBLENDEQUATION_H
+#define GLBLENDEQUATION_H
+
+#include <GL/glew.h>
+#ifdef WIN32
+# include <windows.h>
+#endif
+#ifdef __MACH__
+# include <OpenGL/gl.h>
+#else
+# include <GL/gl.h>
+#endif
+
+void FRS_glBlendEquation(GLenum mode);
+
+#endif // GLBLENDEQUATION_H
diff --git a/source/blender/freestyle/intern/rendering/GLDebugRenderer.cpp b/source/blender/freestyle/intern/rendering/GLDebugRenderer.cpp
new file mode 100755
index 00000000000..12428ab633f
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLDebugRenderer.cpp
@@ -0,0 +1,201 @@
+
+//
+// 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 "GLDebugRenderer.h"
+
+#include <stdio.h>
+#include "../scene_graph/VertexRep.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/IndexedFaceSet.h"
+#include "../scene_graph/LineRep.h"
+#include "../geometry/Grid.h"
+
+#ifdef __MACH__
+#include <GLUT/glut.h>
+#else
+# ifdef WIN32
+# include <GL/glu.h>
+# else
+# include <GL/glut.h>
+# endif
+#endif
+
+void GLDebugRenderer::visitIndexedFaceSet(IndexedFaceSet& iFaceSet)
+{
+ unsigned int fIndex = 0;
+
+ const real * vertices = iFaceSet.vertices();
+ const real * normals = iFaceSet.normals();
+ const FrsMaterial *const* frs_materials = (const FrsMaterial**)iFaceSet.frs_materials();
+ const unsigned *vindices = iFaceSet.vindices();
+ const unsigned *nindices = iFaceSet.nindices();
+ const unsigned *mindices = iFaceSet.mindices();
+ const unsigned numfaces = iFaceSet.numFaces();
+ const unsigned *numVertexPerFace = iFaceSet.numVertexPerFaces();
+ const IndexedFaceSet::TRIANGLES_STYLE * faceStyle = iFaceSet.trianglesStyle();
+
+ const unsigned *pvi = vindices;
+ const unsigned *pni = nindices;
+ const unsigned* pmi = mindices;
+
+ for(fIndex=0; fIndex<numfaces; fIndex++)
+ {
+ switch(faceStyle[fIndex])
+ {
+ case IndexedFaceSet::TRIANGLE_STRIP:
+ RenderTriangleStrip(vertices, normals, frs_materials, pvi, pni, pmi, numVertexPerFace[fIndex]);
+ break;
+ case IndexedFaceSet::TRIANGLE_FAN:
+ RenderTriangleFan(vertices, normals, frs_materials, pvi, pni, pmi, numVertexPerFace[fIndex]);
+ break;
+ case IndexedFaceSet::TRIANGLES:
+ RenderTriangles(vertices, normals, frs_materials, pvi, pni, pmi, numVertexPerFace[fIndex]);
+ break;
+ }
+ pvi += numVertexPerFace[fIndex];
+ pni += numVertexPerFace[fIndex];
+ pmi += numVertexPerFace[fIndex];
+ }
+}
+
+void GLDebugRenderer::visitNodeShape(NodeShape& iShapeNode)
+{
+ // Gets the bbox size:
+ real minY = iShapeNode.bbox().getMin()[1];
+ real maxY = iShapeNode.bbox().getMax()[1];
+
+ // sets the text size:
+ _bboxSize = fabs((maxY-minY)); ///1000.f;
+}
+
+void GLDebugRenderer::visitLineRep(LineRep& iLine)
+{
+
+ glColor3f(0,0,0);
+
+ GLRenderer::visitLineRep(iLine);
+}
+
+void GLDebugRenderer::visitOrientedLineRep(OrientedLineRep& iLine)
+{
+ GLRenderer::visitOrientedLineRep(iLine);
+}
+
+void GLDebugRenderer::visitVertexRep(VertexRep& iVertex)
+{
+ glPointSize(3.0);
+
+ GLRenderer::visitVertexRep(iVertex);
+}
+
+
+void GLDebugRenderer::renderBitmapString(real x,
+ real y,
+ real z,
+ void *font,
+ char *string,
+ float size)
+{
+ char *c;
+
+ glPushMatrix();
+ glTranslater(x, y,z);
+ real textSize = min(_bboxSize/10.0, _minEdgeSize/2.0);
+ // adjust the text size so as it
+ // is acceptable giving the bbox size:
+ while(_bboxSize/textSize>1000)
+ textSize *= 10.0;
+
+ glScalef(size, size, size);
+ glScalef(textSize/200.0, textSize/200.0, textSize/200.0);
+ for (c=string; *c != '\0'; c++)
+ {
+ //soc glutStrokeCharacter(font, *c);
+ }
+ glPopMatrix();
+}
+
+void GLDebugRenderer::RenderTriangleStrip(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned iNVertices)
+{
+ // glBegin(GL_TRIANGLE_STRIP);
+ // for(unsigned int i=0; i<iNVertices; i++)
+ // {
+ // glNormal3r(iNormals[iNIndices[i]],
+ // iNormals[iNIndices[i]+1],
+ // iNormals[iNIndices[i]+2]);
+ //
+ // glVertex3r( iVertices[iVIndices[i]],
+ // iVertices[iVIndices[i]+1],
+ // iVertices[iVIndices[i]+2]);
+ // }
+ // glEnd();
+}
+
+void GLDebugRenderer::RenderTriangleFan(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned iNVertices)
+{
+ // glBegin(GL_TRIANGLE_FAN);
+ // for(unsigned int i=0; i<iNVertices; i++)
+ // {
+ // glNormal3r(iNormals[iNIndices[i]],
+ // iNormals[iNIndices[i]+1],
+ // iNormals[iNIndices[i]+2]);
+ //
+ // glVertex3r( iVertices[iVIndices[i]],
+ // iVertices[iVIndices[i]+1],
+ // iVertices[iVIndices[i]+2]);
+ // }
+ // glEnd();
+}
+
+void GLDebugRenderer::RenderTriangles(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned iNVertices)
+{
+ // // Renders the normals:
+ // glBegin(GL_LINES);
+ // for(unsigned int i=0; i<iNVertices; i++)
+ // {
+ // glVertex3r( iVertices[iVIndices[i]],
+ // iVertices[iVIndices[i]+1],
+ // iVertices[iVIndices[i]+2]);
+ //
+ // glVertex3r(iVertices[iVIndices[i]] + iNormals[iNIndices[i]]/10.f,
+ // iVertices[iVIndices[i]+1] + iNormals[iNIndices[i]+1]/10.f,
+ // iVertices[iVIndices[i]+2] + iNormals[iNIndices[i]+2]/10.f);
+ // }
+ // glEnd();
+}
diff --git a/source/blender/freestyle/intern/rendering/GLDebugRenderer.h b/source/blender/freestyle/intern/rendering/GLDebugRenderer.h
new file mode 100755
index 00000000000..45316b3abc6
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLDebugRenderer.h
@@ -0,0 +1,182 @@
+//
+// Filename : GLDebugRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to render the debug informations related to
+// a scene
+// Date of creation : 03/04/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 GLDEBUGRENDERER_H
+# define GLDEBUGRENDERER_H
+
+# include "../view_map/Silhouette.h"
+# include <float.h>
+# include "../system/FreestyleConfig.h"
+# include "GLRenderer.h"
+# include "../winged_edge/Curvature.h"
+
+class WSMeshShape;
+class WSExactShape;
+
+class LIB_RENDERING_EXPORT GLDebugRenderer : public GLRenderer
+{
+public:
+
+ inline GLDebugRenderer() : GLRenderer() {
+ _bboxSize = 2.0;
+ setMaxValue(&_minEdgeSize);
+ _SelectedFEdge = 0;
+ }
+
+ inline ~GLDebugRenderer() {}
+
+ VISIT_DECL(NodeShape)
+
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(LineRep)
+ VISIT_DECL(OrientedLineRep)
+ VISIT_DECL(VertexRep)
+
+ /*! Renders a bitmap string in world coordinates
+ * x, y, z
+ * The world coordinates of the sentence's starting point
+ * font
+ * The font used to display the text.
+ * Must be one of :
+ * - GLUT_STROKE_ROMAN
+ * - GLUT_STROKE_MONO_ROMAN
+ * string
+ * The text to display
+ * size
+ * The relative size of the text to display
+ */
+ void renderBitmapString(real x,
+ real y,
+ real z,
+ void *font,
+ char *string,
+ float size = 1.f) ;
+
+ /*! Reinitialize the Renderer so as the previous
+ * text size does not affect the current one.
+ * iBBoxSize
+ * The size of the scene bounding box.
+ */
+ inline void ReInit(real iBBoxSize) {_bboxSize = iBBoxSize; setMaxValue(&_minEdgeSize);}
+
+ inline void setSelectedFEdge(FEdge *iFEdge) {_SelectedFEdge = iFEdge;}
+ inline FEdge * selectedFEdge() {return _SelectedFEdge;}
+
+protected:
+
+ /*! Renders a face made of a triangles strip
+ * iVertices
+ * Array of float containing the face vertices. 3 floats per
+ * x, y, z vertex coordinates
+ * iNormals
+ * Array of float containing the face normals. 3 floats per
+ * x, y, z vertex normal coordinates
+ * iVIndices
+ * Array of the indices (to use with the iVertices array)
+ * describing the vertices parsing order
+ * iNIndices
+ * Array of normals indices (to use with iNormals array)
+ * describing the normals parsing order
+ * iNVertices
+ * The number of vertices in the face
+ */
+ virtual void RenderTriangleStrip(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned iNVertices);
+
+ /*! Renders a face made of a triangles fan
+ * iVertices
+ * Array of float containing the face vertices. 3 floats per
+ * x, y, z vertex coordinates
+ * iNormals
+ * Array of float containing the face normals. 3 floats per
+ * x, y, z vertex normal coordinates
+ * iVIndices
+ * Array of the indices (to use with the iVertices array)
+ * describing the vertices parsing order
+ * iNIndices
+ * Array of normals indices (to use with iNormals array)
+ * describing the normals parsing order
+ * iNVertices
+ * The number of vertices in the face
+ */
+ virtual void RenderTriangleFan(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const*iMaterials,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned iNVertices);
+
+ /*! Renders a face made of single triangles
+ * iVertices
+ * Array of float containing the face vertices. 3 floats per
+ * x, y, z vertex coordinates
+ * iNormals
+ * Array of float containing the face normals. 3 floats per
+ * x, y, z vertex normal coordinates
+ * iVIndices
+ * Array of the indices (to use with the iVertices array)
+ * describing the vertices parsing order
+ * iNIndices
+ * Array of normals indices (to use with iNormals array)
+ * describing the normals parsing order
+ * iNVertices
+ * The number of vertices in the face
+ */
+ virtual void RenderTriangles(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned iNVertices);
+
+ /*! glTranslatef or glTranslated */
+ inline void glTranslater(float x, float y, float z) {glTranslatef(x,y,z);}
+ inline void glTranslater(real x, real y, real z) {glTranslated(x,y,z);}
+
+
+private:
+
+ inline void setMaxValue(float *oValue) {*oValue = FLT_MAX;}
+ inline void setMaxValue(real *oValue) {*oValue = DBL_MAX;}
+
+ mutable real _bboxSize;
+ mutable real _minEdgeSize;
+
+ FEdge *_SelectedFEdge;
+};
+
+#endif // GLDEBUGRENDERER_H
diff --git a/source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.cpp b/source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.cpp
new file mode 100644
index 00000000000..b5a835f5104
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.cpp
@@ -0,0 +1,27 @@
+#include "GLFreeMemoryVisitor.h"
+#include "../scene_graph/IndexedFaceSet.h"
+
+# ifdef WIN32
+# include <windows.h>
+# endif
+# ifdef __MACH__
+# include <OpenGL/gl.h>
+# else
+# include <GL/gl.h>
+# endif
+
+GLFreeMemoryVisitor::GLFreeMemoryVisitor()
+:SceneVisitor(){
+}
+
+GLFreeMemoryVisitor::~GLFreeMemoryVisitor(){
+}
+
+void GLFreeMemoryVisitor::visitIndexedFaceSet(IndexedFaceSet& ifs){
+ GLuint dl = ifs.displayList();
+ if(dl != 0){
+ if(glIsList(dl)){
+ glDeleteLists(dl, 1);
+ }
+ }
+}
diff --git a/source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.h b/source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.h
new file mode 100644
index 00000000000..2b9314f3701
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLFreeMemoryVisitor.h
@@ -0,0 +1,23 @@
+#ifndef GL_FREE_MEMORY_VISITOR_H_
+#define GL_FREE_MEMORY_VISITOR_H_
+
+# include "../system/FreestyleConfig.h"
+# include "../scene_graph/SceneVisitor.h"
+
+/*! Mainly used to delete display lists */
+class LIB_RENDERING_EXPORT GLFreeMemoryVisitor : public SceneVisitor
+{
+public:
+
+ GLFreeMemoryVisitor() ;
+ virtual ~GLFreeMemoryVisitor() ;
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_DECL(IndexedFaceSet)
+};
+
+#endif // GL_FREE_MEMORY_H_
diff --git a/source/blender/freestyle/intern/rendering/GLMonoColorRenderer.cpp b/source/blender/freestyle/intern/rendering/GLMonoColorRenderer.cpp
new file mode 100755
index 00000000000..ff893484fb5
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLMonoColorRenderer.cpp
@@ -0,0 +1,43 @@
+
+//
+// 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 "GLMonoColorRenderer.h"
+
+void GLMonoColorRenderer::visitFrsMaterial(FrsMaterial&) {
+ glColor3f(_r, _g, _b);
+}
+
+void GLMonoColorRenderer::visitDrawingStyle(DrawingStyle&) {
+ glDisable(GL_LIGHTING);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ glLineWidth(3.0);
+ glPolygonMode(GL_BACK, GL_LINE);
+ //glPolygonMode(GL_BACK, GL_FILL);
+}
+
+void GLMonoColorRenderer::setColor(float r, float g, float b, float alpha) {
+ _r = r;
+ _g = g;
+ _b = b;
+ _alpha = alpha;
+}
diff --git a/source/blender/freestyle/intern/rendering/GLMonoColorRenderer.h b/source/blender/freestyle/intern/rendering/GLMonoColorRenderer.h
new file mode 100755
index 00000000000..9eb6c8134bb
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLMonoColorRenderer.h
@@ -0,0 +1,60 @@
+//
+// Filename : GLMonoColorRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to render 3D scene in 2 colors thanks to OpenGL
+// Date of creation : 07/02/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 GLMONOCOLORRENDERER_H
+# define GLMONOCOLORRENDERER_H
+
+# include "../system/FreestyleConfig.h"
+# include "GLRenderer.h"
+
+class LIB_RENDERING_EXPORT GLMonoColorRenderer : public GLRenderer
+{
+ public:
+
+ GLMonoColorRenderer() : GLRenderer() {
+ _r = _g = _b = 0.f;
+ _alpha = 1.f;
+ }
+
+ virtual ~GLMonoColorRenderer() {}
+
+ VISIT_DECL(DrawingStyle)
+ VISIT_DECL(FrsMaterial)
+
+ void setColor(float r, float g, float b, float alpha = 1.f);
+
+private:
+
+ float _r;
+ float _g;
+ float _b;
+ float _alpha;
+};
+
+#endif // GLMONOCOLORRENDERER_H
diff --git a/source/blender/freestyle/intern/rendering/GLRenderer.cpp b/source/blender/freestyle/intern/rendering/GLRenderer.cpp
new file mode 100755
index 00000000000..75901e09c2b
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLRenderer.cpp
@@ -0,0 +1,467 @@
+
+//
+// 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 "../stroke/Stroke.h"
+#include "../scene_graph/IndexedFaceSet.h"
+#include "../scene_graph/NodeDrawingStyle.h"
+#include "../scene_graph/NodeLight.h"
+#include "../scene_graph/NodeCamera.h"
+#include "../scene_graph/NodeTransform.h"
+#include "../scene_graph/NodeShape.h"
+#include "../scene_graph/OrientedLineRep.h"
+#include "../scene_graph/VertexRep.h"
+
+#include "../scene_graph/TriangleRep.h"
+
+#include "GLRenderer.h"
+
+static GLenum lights[8] = {GL_LIGHT0,
+ GL_LIGHT1,
+ GL_LIGHT2,
+ GL_LIGHT3,
+ GL_LIGHT4,
+ GL_LIGHT5,
+ GL_LIGHT6,
+ GL_LIGHT7};
+
+void GLRenderer::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ /*GLuint dl = ifs.displayList();
+ if(dl != 0){
+ glCallList(dl);
+ return;
+ }*/
+ unsigned int fIndex = 0;
+
+ const real * vertices = ifs.vertices();
+ const real * normals = ifs.normals();
+ const real * texCoords = ifs.texCoords();
+ const FrsMaterial *const* frs_materials = ifs.frs_materials();
+ const unsigned *vindices = ifs.vindices();
+ const unsigned *nindices = ifs.nindices();
+ const unsigned *mindices = ifs.mindices();
+ const unsigned *tindices = ifs.tindices();
+ const unsigned numfaces = ifs.numFaces();
+ const IndexedFaceSet::TRIANGLES_STYLE * faceStyle = ifs.trianglesStyle();
+ const unsigned *numVertexPerFace = ifs.numVertexPerFaces();
+
+
+ const unsigned* pvi = vindices;
+ const unsigned* pni = nindices;
+ const unsigned* pmi = mindices;
+ const unsigned* pti = tindices;
+
+ //dl = glGenLists(1);
+ //glNewList(dl, GL_COMPILE_AND_EXECUTE);
+ for(fIndex=0; fIndex<numfaces; fIndex++)
+ {
+ switch(faceStyle[fIndex])
+ {
+ case IndexedFaceSet::TRIANGLE_STRIP:
+ RenderTriangleStrip(vertices, normals, frs_materials, texCoords, pvi, pni, pmi, pti, numVertexPerFace[fIndex]);
+ break;
+ case IndexedFaceSet::TRIANGLE_FAN:
+ RenderTriangleFan(vertices, normals, frs_materials, texCoords, pvi, pni, pmi, pti, numVertexPerFace[fIndex]);
+ break;
+ case IndexedFaceSet::TRIANGLES:
+ RenderTriangles(vertices, normals, frs_materials, texCoords, pvi, pni, pmi, pti, numVertexPerFace[fIndex]);
+ break;
+ }
+ pvi += numVertexPerFace[fIndex];
+ pni += numVertexPerFace[fIndex];
+ if(pmi)
+ pmi += numVertexPerFace[fIndex];
+ if(pti)
+ pti += numVertexPerFace[fIndex];
+ }
+ //glEndList();
+ //ifs.setDisplayList(dl);
+}
+
+void GLRenderer::visitNodeTransform(NodeTransform& tn) {
+ if(tn.scaled())
+ glEnable(GL_NORMALIZE);
+}
+
+void GLRenderer::visitNodeTransformBefore(NodeTransform& tn) {
+ glPushMatrix();
+
+ // Now apply transform
+ applyTransform(tn.matrix());
+}
+
+void GLRenderer::visitNodeTransformAfter(NodeTransform& tn) {
+ glPopMatrix();
+}
+
+void GLRenderer::visitNodeLight(NodeLight& ln)
+{
+ if(true != ln.isOn())
+ return;
+
+ int number = ln.number();
+
+ glLightfv(lights[number], GL_AMBIENT, ln.ambient());
+ glLightfv(lights[number], GL_DIFFUSE, ln.diffuse());
+ glLightfv(lights[number], GL_SPECULAR, ln.specular());
+ glLightfv(lights[number], GL_POSITION, ln.position());
+
+ glEnable(lights[number]);
+}
+
+void GLRenderer::visitNodeCamera(NodeCamera& cn)
+{
+ const double * mvm = cn.modelViewMatrix();
+ const double * pm = cn.projectionMatrix();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMultMatrixd(pm);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glMultMatrixd(mvm);
+
+
+}
+
+void GLRenderer::visitNodeDrawingStyleBefore(NodeDrawingStyle& ds) {
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+}
+
+void GLRenderer::visitNodeDrawingStyleAfter(NodeDrawingStyle&) {
+ glPopAttrib();
+}
+
+void GLRenderer::RenderTriangleStrip( const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const real *iTexCoords,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned* iTIndices,
+ const unsigned iNVertices)
+{
+ unsigned index = -1;
+ glBegin(GL_TRIANGLE_STRIP);
+ for(unsigned int i=0; i<iNVertices; i++)
+ {
+ if(iMIndices){
+ if(iMIndices[i] != index){
+ visitFrsMaterial(*(iMaterials[iMIndices[i]]));
+ index = iMIndices[i];
+ }
+ }
+
+ if(iTIndices){
+ glTexCoord2f( iTexCoords[iTIndices[i]],
+ iTexCoords[iTIndices[i]+1]);
+ }
+
+ glNormal3r(iNormals[iNIndices[i]],
+ iNormals[iNIndices[i]+1],
+ iNormals[iNIndices[i]+2]);
+
+ glVertex3r( iVertices[iVIndices[i]],
+ iVertices[iVIndices[i]+1],
+ iVertices[iVIndices[i]+2]);
+ }
+ glEnd();
+}
+
+void GLRenderer::RenderTriangleFan( const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const real *iTexCoords,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned* iTIndices,
+ const unsigned iNVertices)
+{
+ unsigned index = -1;
+ glBegin(GL_TRIANGLE_FAN);
+ for(unsigned int i=0; i<iNVertices; i++)
+ {
+ if(iMIndices){
+ if(iMIndices[i] != index){
+ visitFrsMaterial(*(iMaterials[iMIndices[i]]));
+ index = iMIndices[i];
+ }
+ }
+ if(iTIndices){
+ glTexCoord2f( iTexCoords[iTIndices[i]],
+ iTexCoords[iTIndices[i]+1]);
+ }
+
+ glNormal3r(iNormals[iNIndices[i]],
+ iNormals[iNIndices[i]+1],
+ iNormals[iNIndices[i]+2]);
+
+ glVertex3r( iVertices[iVIndices[i]],
+ iVertices[iVIndices[i]+1],
+ iVertices[iVIndices[i]+2]);
+ }
+ glEnd();
+}
+
+void GLRenderer::RenderTriangles( const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const real *iTexCoords,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned* iTIndices,
+ const unsigned iNVertices)
+{
+ unsigned index = -1;
+ glBegin(GL_TRIANGLES);
+ for(unsigned int i=0; i<iNVertices; i++)
+ {
+ if(iMIndices){
+ if(iMIndices[i] != index){
+ visitFrsMaterial(*(iMaterials[iMIndices[i]]));
+ index = iMIndices[i];
+ }
+ }
+ if(iTIndices){
+ glTexCoord2f( iTexCoords[iTIndices[i]],
+ iTexCoords[iTIndices[i]+1]);
+ }
+
+ glNormal3r(iNormals[iNIndices[i]],
+ iNormals[iNIndices[i]+1],
+ iNormals[iNIndices[i]+2]);
+
+ glVertex3r( iVertices[iVIndices[i]],
+ iVertices[iVIndices[i]+1],
+ iVertices[iVIndices[i]+2]);
+ }
+ glEnd();
+}
+
+void GLRenderer::visitLineRep( LineRep& iLine)
+{
+ if(iLine.width() != 0)
+ glLineWidth(iLine.width());
+
+ switch(iLine.style())
+ {
+ case LineRep::LINES:
+ glBegin(GL_LINES);
+ break;
+ case LineRep::LINE_STRIP:
+ glBegin(GL_LINE_STRIP);
+ break;
+ case LineRep::LINE_LOOP:
+ glBegin(GL_LINE_LOOP);
+ break;
+ default:
+ return;
+ }
+
+ const vector<Vec3r>& vertices = iLine.vertices();
+ //soc unused float step=1.f/vertices.size();
+ vector<Vec3r>::const_iterator v;
+
+ for(v=vertices.begin(); v!=vertices.end(); v++)
+ glVertex3r((*v)[0], (*v)[1], (*v)[2]);
+
+ glEnd();
+}
+
+
+void GLRenderer::visitTriangleRep( TriangleRep& iTriangle)
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ switch(iTriangle.style())
+ {
+ case TriangleRep::FILL:
+ glPolygonMode(GL_FRONT, GL_FILL);
+ break;
+ case TriangleRep::LINES:
+ glPolygonMode(GL_FRONT, GL_LINES);
+ break;
+ default:
+ return;
+ }
+
+ glBegin(GL_TRIANGLES);
+ for(int i=0; i<3; ++i)
+ {
+ glColor3f(iTriangle.color(i)[0], iTriangle.color(i)[1], iTriangle.color(i)[2]);
+ glVertex3r(iTriangle.vertex(i)[0], iTriangle.vertex(i)[1], iTriangle.vertex(i)[2]);
+ }
+
+ glEnd();
+
+
+
+ glPopAttrib();
+
+}
+
+void GLRenderer::visitOrientedLineRep(OrientedLineRep& iLine)
+{
+ switch(iLine.style())
+ {
+ case LineRep::LINES:
+ glBegin(GL_LINES);
+ break;
+ case LineRep::LINE_STRIP:
+ glBegin(GL_LINE_STRIP);
+ break;
+ case LineRep::LINE_LOOP:
+ glBegin(GL_LINE_LOOP);
+ break;
+ default:
+ return;
+ }
+
+ int i=0;
+ int ncolor = iLine.getId().getFirst()%3;
+
+ const vector<Vec3r>& vertices = iLine.vertices();
+ float step=1.f/vertices.size();
+ vector<Vec3r>::const_iterator v;
+ for(v=vertices.begin(); v!=vertices.end(); v++)
+ {
+ switch(ncolor)
+ {
+ case 0:
+ glColor3f(i*step,0.f,0.f);
+ break;
+ case 1:
+ glColor3f(0.f, i*step, 0.f);
+ break;
+ case 2:
+ glColor3f(0.f, 0.f, i*step);
+ break;
+ default:
+ glColor3f(i*step, i*step,i*step);
+ break;
+ }
+ i++;
+ glVertex3r((*v)[0], (*v)[1], (*v)[2]);
+ }
+
+ glEnd();
+}
+
+void GLRenderer::visitVertexRep( VertexRep& iVertex)
+{
+ if(iVertex.pointSize() != 0.f)
+ glPointSize(iVertex.pointSize());
+
+ glBegin(GL_POINTS);
+ glVertex3r(iVertex.x(), iVertex.y(), iVertex.z());
+ glEnd();
+}
+
+void GLRenderer::visitDrawingStyle(DrawingStyle& iDrawingStyle)
+{
+
+ // Drawing Style management
+ switch(iDrawingStyle.style())
+ {
+ case DrawingStyle::FILLED:
+ glPolygonMode(GL_FRONT, GL_FILL);
+ glShadeModel(GL_SMOOTH);
+ break;
+
+ case DrawingStyle::LINES:
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_LINE_SMOOTH);
+ glPolygonMode(GL_FRONT, GL_LINE);
+ glLineWidth(iDrawingStyle.lineWidth());
+ break;
+
+ case DrawingStyle::POINTS:
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glEnable(GL_POINT_SMOOTH);
+ glPolygonMode(GL_FRONT, GL_POINT);
+ glPointSize(iDrawingStyle.pointSize());
+ break;
+
+ case DrawingStyle::INVISIBLE:
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glDepthMask(0);
+ break;
+
+ default:
+ break;
+ }
+
+ glLineWidth(iDrawingStyle.lineWidth());
+ glPointSize(iDrawingStyle.pointSize());
+
+ // FIXME
+ if(true == iDrawingStyle.lightingEnabled())
+ glEnable(GL_LIGHTING);
+ else
+ glDisable(GL_LIGHTING);
+}
+
+void GLRenderer::visitFrsMaterial(FrsMaterial& m) {
+ const float* diff = m.diffuse();
+ const float* amb = m.ambient();
+ const float* spec = m.specular();
+ const float* em = m.emission();
+
+ RenderColor(diff);
+ glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
+ glMaterialfv(GL_FRONT, GL_EMISSION, em);
+ glMaterialf(GL_FRONT, GL_SHININESS, m.shininess());
+}
+
+void GLRenderer::visitFrsMaterial(const FrsMaterial& m) {
+ const float* diff = m.diffuse();
+ const float* amb = m.ambient();
+ const float* spec = m.specular();
+ const float* em = m.emission();
+
+ RenderColor(diff);
+ glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
+ glMaterialfv(GL_FRONT, GL_EMISSION, em);
+ glMaterialf(GL_FRONT, GL_SHININESS, m.shininess());
+}
+void GLRenderer::applyTransform( const Matrix44r &iMatrix)
+{
+ real m[16];
+ for(int lign=0; lign<4; lign++)
+ for(int column=0; column<4; column++)
+ m[column*4+lign] = iMatrix(lign, column);
+
+ glMultMatrixr(m);
+}
+
+void GLRenderer::RenderColor( const float *rgba)
+{
+ glColor4fv(rgba);
+}
diff --git a/source/blender/freestyle/intern/rendering/GLRenderer.h b/source/blender/freestyle/intern/rendering/GLRenderer.h
new file mode 100755
index 00000000000..3769aefb92b
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLRenderer.h
@@ -0,0 +1,204 @@
+//
+// Filename : GLRenderer.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class to render a 3D scene thanks to OpenGL
+// Date of creation : 07/02/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 GLRENDERER_H
+# define GLRENDERER_H
+
+# ifdef WIN32
+# include <windows.h>
+# endif
+# ifdef __MACH__
+# include <OpenGL/gl.h>
+# else
+# include <GL/gl.h>
+# endif
+
+# include "../system/FreestyleConfig.h"
+# include "../system/Precision.h"
+# include "../scene_graph/SceneVisitor.h"
+# include "../geometry/Geom.h"
+using namespace Geometry;
+
+class LIB_RENDERING_EXPORT GLRenderer : public SceneVisitor
+{
+ public:
+
+ inline GLRenderer() : SceneVisitor() {}
+ virtual ~GLRenderer() {}
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_DECL(NodeLight)
+ VISIT_DECL(NodeCamera)
+ VISIT_DECL(NodeTransform)
+
+ VISIT_DECL(LineRep)
+ VISIT_DECL(OrientedLineRep)
+ VISIT_DECL(TriangleRep)
+ VISIT_DECL(VertexRep)
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(DrawingStyle)
+ VISIT_DECL(FrsMaterial)
+
+ virtual void visitFrsMaterial(const FrsMaterial&);
+ virtual void visitNodeTransformBefore(NodeTransform&);
+ virtual void visitNodeTransformAfter(NodeTransform&);
+ virtual void visitNodeDrawingStyleBefore(NodeDrawingStyle&);
+ virtual void visitNodeDrawingStyleAfter(NodeDrawingStyle&);
+
+ protected:
+
+ /*! Renders a face made of a triangles strip
+ * iVertices
+ * Array of float containing the face vertices. 3 floats per
+ * x, y, z vertex coordinates
+ * iNormals
+ * Array of float containing the face normals. 3 floats per
+ * x, y, z vertex normal coordinates
+ * iTexCoords
+ * Array of float containing the face uv coords. 2 floats per
+ * u,v vertex texture coordinates
+ * iVIndices
+ * Array of the indices (to use with the iVertices array)
+ * describing the vertices parsing order
+ * iNIndices
+ * Array of normals indices (to use with iNormals array)
+ * describing the normals parsing order
+ * iTIndices
+ * Array of texture coordinates indices (to use with iTexCoords array)
+ * describing the texture coordinates parsing order
+ * iNVertices
+ * The number of vertices in the face
+ */
+ virtual void RenderTriangleStrip(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const*iMaterials,
+ const real *iTexCoords,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned* iTIndices,
+ const unsigned iNVertices) ;
+
+ /*! Renders a face made of a triangles fan
+ * iVertices
+ * Array of float containing the face vertices. 3 floats per
+ * x, y, z vertex coordinates
+ * iNormals
+ * Array of float containing the face normals. 3 floats per
+ * x, y, z vertex normal coordinates
+ * iTexCoords
+ * Array of float containing the face uv coords. 2 floats per
+ * u,v vertex texture coordinates
+ * iVIndices
+ * Array of the indices (to use with the iVertices array)
+ * describing the vertices parsing order
+ * iNIndices
+ * Array of normals indices (to use with iNormals array)
+ * describing the normals parsing order
+ * iTIndices
+ * Array of texture coordinates indices (to use with iTexCoords array)
+ * describing the texture coordinates parsing order
+ * iNVertices
+ * The number of vertices in the face
+ */
+ virtual void RenderTriangleFan(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const real *iTexCoords,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned* iTIndices,
+ const unsigned iNVertices) ;
+
+ /*! Renders a face made of single triangles
+ * iVertices
+ * Array of float containing the face vertices. 3 floats per
+ * x, y, z vertex coordinates
+ * iNormals
+ * Array of float containing the face normals. 3 floats per
+ * x, y, z vertex normal coordinates
+ * iTexCoords
+ * Array of float containing the face uv coords. 2 floats per
+ * u,v vertex texture coordinates
+ * iVIndices
+ * Array of the indices (to use with the iVertices array)
+ * describing the vertices parsing order
+ * iNIndices
+ * Array of normals indices (to use with iNormals array)
+ * describing the normals parsing order
+ * iTIndices
+ * Array of texture coordinates indices (to use with iTexCoords array)
+ * describing the texture coordinates parsing order
+ * iNVertices
+ * The number of vertices in the face
+ */
+ virtual void RenderTriangles(const real *iVertices,
+ const real *iNormals,
+ const FrsMaterial *const* iMaterials,
+ const real *iTexCoords,
+ const unsigned* iVIndices,
+ const unsigned* iNIndices,
+ const unsigned* iMIndices,
+ const unsigned* iTIndices,
+ const unsigned iNVertices) ;
+
+ /*! Apply a transform matrix by multiplying
+ * the current OpenGL ModelView Matrix by
+ * iMatrix
+ */
+ virtual void applyTransform( const Matrix44r &iMatrix) ;
+
+ /*! Sets the current drawing color.
+ * Active only when light is disabled
+ * (simple call to glColor4fv)
+ * rgba
+ * array of 4 floats (r, g, b and alpha)
+ */
+ virtual void RenderColor( const float *rgba);
+
+ /*! glVertex3f or glVertex3d */
+ inline void glVertex3r(float x, float y, float z) {glVertex3f(x,y,z);}
+ inline void glVertex3r(real x, real y, real z) {glVertex3d(x,y,z);}
+
+ /*! glVertex3f or glNormal3d */
+ inline void glNormal3r(float x, float y, float z) {glNormal3f(x,y,z);}
+ inline void glNormal3r(real x, real y, real z) {glNormal3d(x,y,z);}
+
+ /*! glMultMatrixf or glMultMatrixd */
+ inline void glMultMatrixr(float *m) {glMultMatrixf(m);}
+ inline void glMultMatrixr(real *m) {glMultMatrixd(m);}
+
+};
+
+#endif // GLRENDERER_H
diff --git a/source/blender/freestyle/intern/rendering/GLSelectRenderer.cpp b/source/blender/freestyle/intern/rendering/GLSelectRenderer.cpp
new file mode 100755
index 00000000000..ca9199740f8
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLSelectRenderer.cpp
@@ -0,0 +1,159 @@
+
+//
+// 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 "../scene_graph/IndexedFaceSet.h"
+#include "../scene_graph/NodeShape.h"
+#include "GLSelectRenderer.h"
+
+static const float INACTIVE_COLOR_MIN = 0.2;
+static const float INACTIVE_COLOR_MAX = 0.8;
+static const float INACTIVE_COLOR_OFFSET = 0.2;
+
+static const float ACTIVE_COLOR[4] = {0.8,
+ 0.2,
+ 0.2,
+ 1};
+
+static float selection_color[4] = {INACTIVE_COLOR_MIN,
+ INACTIVE_COLOR_MIN,
+ INACTIVE_COLOR_MIN,
+ 1};
+
+
+void GLSelectRenderer::resetColor() {
+ for (unsigned i = 0; i < 3; ++i)
+ selection_color[i] = INACTIVE_COLOR_MIN;
+}
+
+void GLSelectRenderer::visitNodeShape(NodeShape& sn) {
+ if (_gl_select_rendering)
+ return;
+ for (unsigned i = 0; i < 3; ++i) {
+ selection_color[i] += INACTIVE_COLOR_OFFSET;
+ if (selection_color[i] > INACTIVE_COLOR_MAX)
+ selection_color[i] = INACTIVE_COLOR_MIN;
+ }
+ if (sn.shapes()[0]->getId() == _selected_shape) {
+ _current_shape_active = true;
+ return;
+ }
+ _current_shape_active = false;
+}
+
+void GLSelectRenderer::visitFrsMaterial(FrsMaterial& m) {
+ if (_gl_select_rendering)
+ return;
+
+ const float* amb = m.ambient();
+ const float* spec = m.specular();
+ const float* em = m.emission();
+
+ if (_current_shape_active) {
+ RenderColor(ACTIVE_COLOR);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, ACTIVE_COLOR);
+ } else {
+ RenderColor(selection_color);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, selection_color);
+ }
+ glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
+ glMaterialfv(GL_FRONT, GL_EMISSION, em);
+ glMaterialf(GL_FRONT, GL_SHININESS, m.shininess());
+}
+
+void GLSelectRenderer::visitFrsMaterial(const FrsMaterial& m) {
+ if (_gl_select_rendering)
+ return;
+
+ const float* amb = m.ambient();
+ const float* spec = m.specular();
+ const float* em = m.emission();
+
+ if (_current_shape_active) {
+ RenderColor(ACTIVE_COLOR);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, ACTIVE_COLOR);
+ } else {
+ RenderColor(selection_color);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, selection_color);
+ }
+ glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
+ glMaterialfv(GL_FRONT, GL_EMISSION, em);
+ glMaterialf(GL_FRONT, GL_SHININESS, m.shininess());
+}
+
+void GLSelectRenderer::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ unsigned int fIndex = 0;
+
+ const real * vertices = ifs.vertices();
+ const real * normals = ifs.normals();
+ const FrsMaterial *const* frs_materials = ifs.frs_materials();
+ const real * texCoords= ifs.texCoords();
+ const unsigned *vindices = ifs.vindices();
+ const unsigned *nindices = ifs.nindices();
+ const unsigned *mindices = ifs.mindices();
+ const unsigned *tindices = ifs.tindices();
+ const unsigned numfaces = ifs.numFaces();
+ const IndexedFaceSet::TRIANGLES_STYLE * faceStyle = ifs.trianglesStyle();
+ const unsigned *numVertexPerFace = ifs.numVertexPerFaces();
+
+
+ const unsigned* pvi = vindices;
+ const unsigned* pni = nindices;
+ const unsigned* pmi = mindices;
+ const unsigned* pti = tindices;
+
+ for(fIndex=0; fIndex<numfaces; fIndex++)
+ {
+ switch(faceStyle[fIndex])
+ {
+ case IndexedFaceSet::TRIANGLE_STRIP:
+ RenderTriangleStrip(vertices, normals, frs_materials, texCoords, pvi, pni, pmi, pti, numVertexPerFace[fIndex]);
+ break;
+ case IndexedFaceSet::TRIANGLE_FAN:
+ RenderTriangleFan(vertices, normals, frs_materials, texCoords, pvi, pni, pmi, pti, numVertexPerFace[fIndex]);
+ break;
+ case IndexedFaceSet::TRIANGLES:
+ RenderTriangles(vertices, normals, frs_materials, texCoords, pvi, pni, pmi, pti, numVertexPerFace[fIndex]);
+ break;
+ }
+ pvi += numVertexPerFace[fIndex];
+ pni += numVertexPerFace[fIndex];
+ pmi += numVertexPerFace[fIndex];
+ if(pti)
+ pti += numVertexPerFace[fIndex];
+ }
+}
+
+void GLSelectRenderer::visitNodeShapeBefore(NodeShape& sn) {
+ if (!_gl_select_rendering)
+ return;
+
+ glPushName(sn.shapes()[0]->getId().getFirst());
+}
+
+void GLSelectRenderer::visitNodeShapeAfter(NodeShape& sn) {
+ if (!_gl_select_rendering)
+ return;
+
+ glPopName();
+}
diff --git a/source/blender/freestyle/intern/rendering/GLSelectRenderer.h b/source/blender/freestyle/intern/rendering/GLSelectRenderer.h
new file mode 100755
index 00000000000..2ce8c3f62db
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLSelectRenderer.h
@@ -0,0 +1,85 @@
+//
+// Filename : GLSelectRenderer.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Class to highlight selected shapes
+// Date of creation : 09/01/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 GL_SELECT_RENDERER_H
+# define GL_SELECT_RENDERER_H
+
+# include "GLRenderer.h"
+
+class LIB_RENDERING_EXPORT GLSelectRenderer : public GLRenderer
+{
+ public:
+
+ inline GLSelectRenderer() : GLRenderer() {
+ _selected_shape = -1; // -1 means no selection
+ _current_shape_active = false;
+ _gl_select_rendering = false;
+ }
+ virtual ~GLSelectRenderer() {}
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_DECL(NodeShape)
+
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(FrsMaterial)
+
+ virtual void visitFrsMaterial(const FrsMaterial&);
+ virtual void visitNodeShapeBefore(NodeShape&);
+ virtual void visitNodeShapeAfter(NodeShape&);
+
+ void resetColor();
+
+ void setSelectedId(const int id) {
+ _selected_shape = id;
+ }
+
+ void setSelectRendering(bool b) {
+ _gl_select_rendering = b;
+ }
+
+ int getSelectedId() const {
+ return _selected_shape;
+ }
+
+ bool getSelectRendering() const {
+ return _gl_select_rendering;
+ }
+
+ private:
+
+ int _selected_shape;
+ bool _current_shape_active;
+ bool _gl_select_rendering;
+};
+
+#endif // GL_SELECT_RENDERER_H
diff --git a/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp b/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp
new file mode 100755
index 00000000000..e29dd5cad8f
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLStrokeRenderer.cpp
@@ -0,0 +1,474 @@
+
+//
+// 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 "GLStrokeRenderer.h"
+
+//soc
+// #include <qimage.h>
+// #include <qfileinfo.h>
+// #include <qgl.h>
+// #include <qfile.h>
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "MEM_guardedalloc.h"
+}
+
+#include "../system/StringUtils.h"
+
+GLStrokeRenderer::GLStrokeRenderer()
+:StrokeRenderer()
+{
+ _textureManager = new GLTextureManager;
+}
+
+GLStrokeRenderer::~GLStrokeRenderer()
+{
+ if(0 != _textureManager)
+ {
+ delete _textureManager;
+ _textureManager = 0;
+ }
+}
+
+float initialColor(float x, float avTex=0.5)
+{
+ float y=(1-x)/avTex;
+ return (y>1 ? 1 : y);
+}
+//float complementColor(float x, float avTex=0.5)
+//{
+// float y=(1-x)/avTex-1;
+// return (y<0 ? 0 : y);
+//}
+
+float complementColor(float x, float avTex=0.5)
+{
+ float y=(1-x);///avTex-1;
+ return (y<0 ? 0 : y);
+}
+
+void GLStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const
+{
+ glPushAttrib(GL_COLOR_BUFFER_BIT);
+ Stroke::MediumType strokeType = iStrokeRep->getMediumType();
+ // int averageTextureAlpha=0.5; //default value
+ // if (strokeType==OIL_STROKE)
+ // averageTextureAlpha=0.75;
+ // if (strokeType>=NO_BLEND_STROKE)
+ // averageTextureAlpha=1.0;
+ // if (strokeType<0)
+ // {
+ // renderNoTexture(iStrokeRep);
+ // return;
+ // }
+ //soc unused - int i;
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+
+ if(strokeType==Stroke::DRY_MEDIUM)
+ {
+ FRS_glBlendEquation(GL_MAX);
+ }
+ else if(strokeType==Stroke::OPAQUE_MEDIUM)
+ {
+ FRS_glBlendEquation(GL_ADD);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else
+ {
+ FRS_glBlendEquation(GL_ADD);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ }
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ //first texture, basically the only one for lighter strokes
+ glBindTexture(GL_TEXTURE_2D, iStrokeRep->getTextureId());
+
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
+ s!=send;
+ ++s){
+ Strip::vertex_container& vertices = (*s)->vertices();
+ glBegin(GL_TRIANGLE_STRIP);
+ for(Strip::vertex_container::iterator v=vertices.begin(), vend=vertices.end();
+ v!=vend;
+ ++v){
+
+ StrokeVertexRep * svRep = (*v);
+ Vec3r color = svRep->color();
+ real alpha = svRep->alpha();
+ glColor4f(complementColor(color[0]),
+ complementColor(color[1]),
+ complementColor(color[2]), alpha);
+ glTexCoord2f(svRep->texCoord()[0],svRep->texCoord()[1] );
+ glVertex2f(svRep->point2d()[0], svRep->point2d()[1]);
+ }
+ glEnd();
+ }
+// if (strokeType>=NO_BLEND_STROKE) return;
+ // //return;
+ //
+ // //second texture, the complement, for stronger strokes
+ // glBindTexture(GL_TEXTURE_2D, _textureManager.getTextureIndex(2*strokeType+1));
+ // glBegin(GL_TRIANGLE_STRIP);
+ // for(i=0; i<_sizeStrip; i++)
+ // {
+ // glColor4f(complementColor(_color[i][0]),
+ // complementColor(_color[i][1]),
+ // complementColor(_color[i][2]), _alpha[i]);
+ // glTexCoord2f(_texCoord[i][0],_texCoord[i][1] );
+ // glVertex2f(_vertex[i][0], _vertex[i][1]);
+ // }
+ // glEnd();
+
+ glPopAttrib();
+}
+
+void GLStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const
+{
+ glPushAttrib(GL_COLOR_BUFFER_BIT);
+ //soc unused - Stroke::MediumType strokeType = iStrokeRep->getMediumType();
+ //soc unused - int i;
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_LIGHTING);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+
+ glEnable(GL_BLEND);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_TEXTURE_2D);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+ //first texture, basically the only one for lighter strokes
+ glBindTexture(GL_TEXTURE_2D, iStrokeRep->getTextureId());
+
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
+ s!=send;
+ ++s){
+ Strip::vertex_container& vertices = (*s)->vertices();
+ glBegin(GL_TRIANGLE_STRIP);
+ for(Strip::vertex_container::iterator v=vertices.begin(), vend=vertices.end();
+ v!=vend;
+ ++v){
+ StrokeVertexRep * svRep = (*v);
+ Vec3r color = svRep->color();
+ real alpha = svRep->alpha();
+ glColor4f(color[0],
+ color[1],
+ color[2], alpha);
+ glTexCoord2f(svRep->texCoord()[0],svRep->texCoord()[1] );
+ glVertex2f(svRep->point2d()[0], svRep->point2d()[1]);
+ }
+ glEnd();
+ }
+ glPopAttrib();
+}
+
+//No Texture
+//void GLStrokeRenderer::renderNoTexture(StrokeRep *iStrokeRep) const
+//{
+// Stroke::MediumType strokeType = iStrokeRep->getMediumType();
+// int sizeStrip = iStrokeRep->sizeStrip();
+// const Vec3r *color = iStrokeRep->colors();
+// const Vec2r *vertex = iStrokeRep->vertices();
+// const float *alpha = iStrokeRep->alpha();
+//
+// glDisable(GL_LIGHTING);
+// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+// glShadeModel(GL_SMOOTH);
+// glDisable(GL_DEPTH_TEST);
+//
+// //if (strokeType==NO_TEXTURE_STROKE)
+// if(strokeType < 0)
+// {
+// glDisable(GL_BLEND);
+// glDisable(GL_TEXTURE_2D);
+// glBegin(GL_TRIANGLE_STRIP);
+// for(int i=0; i<sizeStrip; i++)
+// {
+// glColor4f(complementColor(color[i][0]),
+// complementColor(color[i][1]),
+// complementColor(color[i][2]), alpha[i]);
+// glVertex2f(vertex[i][0], vertex[i][1]);
+// }
+// glEnd();
+// }
+// else
+// {
+// //#ifdef WIN32
+// //glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+// glBlendEquation(GL_ADD);
+// //#endif
+// glEnable(GL_BLEND);
+// glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+// glDisable(GL_TEXTURE_2D);
+// glBegin(GL_TRIANGLE_STRIP);
+// for(int i=0; i<sizeStrip; i++)
+// {
+// glColor4f(complementColor(color[i][0]),
+// complementColor(color[i][1]),
+// complementColor(color[i][2]), alpha[i]);
+// glVertex2f(vertex[i][0], vertex[i][1]);
+// }
+// glEnd();
+// }
+// // cerr<<"color="<<_color[1][0]<<", "<<_color[1][1]<<", "<<_color[1][2]<<") "<<endl;
+//
+//
+//}
+
+
+/**********************************/
+/* */
+/* */
+/* GLTextureManager */
+/* */
+/* */
+/**********************************/
+
+//#define TEXTURES_DIR ROOT_DIR "/data/textures"
+
+GLTextureManager::GLTextureManager ()
+: TextureManager()
+{
+ //_brushes_path = Config::getInstance()...
+}
+
+GLTextureManager::~GLTextureManager ()
+{
+}
+
+void GLTextureManager::loadStandardBrushes()
+{
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ _defaultTextureId = getBrushTextureIndex("smoothAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+}
+
+
+unsigned
+GLTextureManager::loadBrush(string sname, Stroke::MediumType mediumType)
+{
+ GLuint texId;
+ glGenTextures(1, &texId);
+ bool found = false;
+ vector<string> pathnames;
+ string path; //soc
+ StringUtils::getPathName(TextureManager::Options::getBrushesPath(),
+ sname,
+ pathnames);
+ for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+ path = j->c_str();
+ //soc if(QFile::exists(path)){
+ if( BLI_exists( const_cast<char *>(path.c_str()) ) ) {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ return 0;
+ // Brush texture
+ cout << "Loading brush texture..." << endl;
+ switch(mediumType){
+ case Stroke::DRY_MEDIUM:
+ //soc prepareTextureLuminance((const char*)path.toAscii(), texId);
+ prepareTextureLuminance(StringUtils::toAscii(path), texId);
+ break;
+ case Stroke::HUMID_MEDIUM:
+ case Stroke::OPAQUE_MEDIUM:
+ default:
+ //soc prepareTextureAlpha((const char*)path.toAscii(), texId);
+ prepareTextureAlpha(StringUtils::toAscii(path), texId);
+ break;
+ }
+ cout << "Done." << endl << endl;
+
+ return texId;
+}
+
+bool
+GLTextureManager::prepareTextureAlpha (string sname, GLuint itexname)
+{
+ //soc const char * name = sname.c_str();
+ char * name = (char *) sname.c_str();
+
+ //soc
+ ImBuf *qim = IMB_loadiffname(name, 0);
+ char filename[FILE_MAXFILE];
+ char *p = BLI_strdup(name);
+ BLI_splitdirstring(p, filename);
+ MEM_freeN(p);
+
+//soc if (qim.isNull())
+ if (!qim) //soc
+ {
+ cerr << " Error: unable to read \"" << filename << "\"" << endl;
+ IMB_freeImBuf(qim);
+ return false;
+ }
+
+ if( qim->depth > 8) //soc
+ {
+ cerr<<" Error: \""<< filename <<"\" has "<< qim->depth <<" bits/pixel"<<endl; //soc
+ return false;
+ }
+ // qim=QGLWidget::convertToGLFormat( qimOri );
+
+ glBindTexture(GL_TEXTURE_2D, itexname);
+ //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ // GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim->x, qim->y, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, qim->rect); //soc
+
+ //soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
+ cout << " \"" << filename << "\" loaded with 32 bits per pixel" << endl;
+
+ return true;
+
+}
+
+bool
+GLTextureManager::prepareTextureLuminance (string sname, GLuint itexname)
+{
+ //soc const char * name = sname.c_str();
+ char * name = (char *) sname.c_str();
+
+ //soc
+ ImBuf *qim = IMB_loadiffname(name, 0);
+ char filename[FILE_MAXFILE];
+ char *p = BLI_strdup(name);
+ BLI_splitdirstring(p, filename);
+ MEM_freeN(p);
+
+ if (!qim) //soc
+ {
+ cerr << " Error: unable to read \"" << filename << "\"" << endl;
+ IMB_freeImBuf(qim);
+ return false;
+ }
+ if (qim->depth > 8) //soc
+ {
+ cerr<<" Error: \""<<filename<<"\" has "<<qim->depth <<" bits/pixel"<<endl;//soc
+ return false;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, itexname);
+ //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ // GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim->x, qim->y, 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, qim->rect); //soc
+
+ //soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
+ cout << " \"" << filename << "\" loaded with "<< qim->depth << " bits per pixel" << endl;
+
+ return true;
+
+}
+
+bool
+GLTextureManager::prepareTextureLuminanceAndAlpha (string sname, GLuint itexname)
+{
+ //soc const char * name = sname.c_str();
+ char * name = (char *) sname.c_str();
+
+ //soc
+ ImBuf *qim = IMB_loadiffname(name, 0);
+ char filename[FILE_MAXFILE];
+ char *p = BLI_strdup(name);
+ BLI_splitdirstring(p, filename);
+ MEM_freeN(p);
+
+ if (!qim) //soc
+ {
+ cerr << " Error: unable to read \"" << filename << "\"" << endl;
+ IMB_freeImBuf(qim);
+ return false;
+ }
+
+ if (qim->depth > 8) //soc
+ {
+ cerr<<" Error: \""<<filename<<"\" has "<< qim->depth <<" bits/pixel"<<endl; //soc
+ return false;
+ }
+
+ glBindTexture(GL_TEXTURE_2D, itexname);
+ //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ // GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, qim->x, qim->y, 0,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, qim->rect); //soc
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, qim->x, qim->y, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, qim->rect); //soc
+
+ //soc cout << " \"" << filename.toAscii().data() << "\" loaded with "<< qim.depth() << " bits per pixel" << endl;
+ cout << " \"" << filename << "\" loaded with "<< qim->depth << " bits per pixel" << endl;
+
+ return true;
+
+}
+
+
diff --git a/source/blender/freestyle/intern/rendering/GLStrokeRenderer.h b/source/blender/freestyle/intern/rendering/GLStrokeRenderer.h
new file mode 100755
index 00000000000..70289924002
--- /dev/null
+++ b/source/blender/freestyle/intern/rendering/GLStrokeRenderer.h
@@ -0,0 +1,88 @@
+//
+// Filename : GLStrokeRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the GL stroke renderer.
+// Date of creation : 05/03/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 GLSTROKERENDERER_H
+# define GLSTROKERENDERER_H
+
+# include "../stroke/StrokeRenderer.h"
+# include "../stroke/StrokeRep.h"
+# include "../system/FreestyleConfig.h"
+
+#include "GLBlendEquation.h"
+
+/**********************************/
+/* */
+/* */
+/* GLTextureManager */
+/* */
+/* */
+/**********************************/
+
+/*! Class to load textures
+ */
+class LIB_RENDERING_EXPORT GLTextureManager : public TextureManager
+{
+ public:
+ GLTextureManager ();
+ virtual ~GLTextureManager ();
+protected:
+ virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM);
+
+ protected:
+ virtual void loadStandardBrushes();
+ bool prepareTextureAlpha (string name, GLuint itexname);
+ bool prepareTextureLuminance (string name, GLuint itexname);
+ bool prepareTextureLuminanceAndAlpha (string name, GLuint itexname);
+};
+
+
+
+/**********************************/
+/* */
+/* */
+/* GLStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_RENDERING_EXPORT GLStrokeRenderer : public StrokeRenderer
+{
+public:
+ GLStrokeRenderer();
+ virtual ~GLStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+protected:
+ //void renderNoTexture(StrokeRep *iStrokeRep) const;
+};
+
+#endif // GLSTROKERENDERER_H
diff --git a/source/blender/freestyle/intern/scene_graph/DrawingStyle.h b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h
new file mode 100755
index 00000000000..58dcf4fede9
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/DrawingStyle.h
@@ -0,0 +1,82 @@
+//
+// Filename : DrawingStyle.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the drawing style of a node
+// Date of creation : 10/10/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 DRAWINGSTYLE_H
+# define DRAWINGSTYLE_H
+
+class DrawingStyle
+{
+public:
+ enum STYLE
+ {FILLED, LINES, POINTS, INVISIBLE};
+
+ inline DrawingStyle() {Style = FILLED; LineWidth = 2.f; PointSize = 2.f; LightingEnabled = true;}
+ inline explicit DrawingStyle(const DrawingStyle& iBrother);
+
+ virtual ~DrawingStyle() {}
+
+ /*! operators */
+ inline DrawingStyle& operator=(const DrawingStyle& ds);
+
+ inline void setStyle(const STYLE iStyle) {Style = iStyle;}
+ inline void setLineWidth(const float iLineWidth) {LineWidth = iLineWidth;}
+ inline void setPointSize(const float iPointSize) {PointSize = iPointSize;}
+ inline void setLightingEnabled(const bool on) {LightingEnabled = on;}
+
+ inline STYLE style() const {return Style;}
+ inline float lineWidth() const {return LineWidth;}
+ inline float pointSize() const {return PointSize;}
+ inline bool lightingEnabled() const {return LightingEnabled;}
+
+private:
+ STYLE Style;
+ float LineWidth;
+ float PointSize;
+ bool LightingEnabled;
+};
+
+DrawingStyle::DrawingStyle(const DrawingStyle& iBrother)
+{
+ Style = iBrother.Style;
+ LineWidth = iBrother.LineWidth;
+ PointSize = iBrother.PointSize;
+ LightingEnabled = iBrother.LightingEnabled;
+}
+
+DrawingStyle& DrawingStyle::operator=(const DrawingStyle& ds)
+{
+ Style = ds.Style;
+ LineWidth = ds.LineWidth;
+ PointSize = ds.PointSize;
+ LightingEnabled = ds.LightingEnabled;
+
+ return *this;
+}
+
+#endif // DRAWINGSTYLE_H
diff --git a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
new file mode 100755
index 00000000000..1cbadab2bd3
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
@@ -0,0 +1,304 @@
+//
+// Filename : FrsMaterial.h
+// Author(s) : Stephane Grabli
+// Purpose : Class used to handle materials.
+// Date of creation : 10/10/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 FRS_MATERIAL_H
+# define FRS_MATERIAL_H
+
+# include "../system/FreestyleConfig.h"
+
+/*! Class defining a material */
+class FrsMaterial
+{
+public:
+ /*! Default constructor */
+ inline FrsMaterial();
+ /*! Builds a Material from its diffuse, ambiant, specular, emissive
+ * colors and a shininess coefficient.
+ * \param iDiffuse
+ * A 4 element float-array containing the diffuse color.
+ * \param iAmbiant
+ * A 4 element float-array containing the ambiant color.
+ * \param iSpecular
+ * A 4 element float-array containing the specular color.
+ * \param iEmission
+ * A 4 element float-array containing the emissive color.
+ * \param iShininess
+ * The shininess coefficient.
+ */
+ inline FrsMaterial(const float *iDiffuse,
+ const float *iAmbiant,
+ const float *iSpecular,
+ const float *iEmission,
+ const float iShininess);
+
+ /*! Copy constructor */
+ inline FrsMaterial(const FrsMaterial& m);
+ /*! Destructor */
+ virtual ~FrsMaterial() {}
+
+
+ /*! Returns the diffuse color as a 4 float array */
+ inline const float * diffuse() const { return Diffuse; }
+ /*! Returns the red component of the diffuse color */
+ inline const float diffuseR() const { return Diffuse[0]; }
+ /*! Returns the green component of the diffuse color */
+ inline const float diffuseG() const { return Diffuse[1]; }
+ /*! Returns the blue component of the diffuse color */
+ inline const float diffuseB() const { return Diffuse[2]; }
+ /*! Returns the alpha component of the diffuse color */
+ inline const float diffuseA() const { return Diffuse[3]; }
+
+ /*! Returns the specular color as a 4 float array */
+ inline const float * specular() const { return Specular; }
+ /*! Returns the red component of the specular color */
+ inline const float specularR() const { return Specular[0]; }
+ /*! Returns the green component of the specular color */
+ inline const float specularG() const { return Specular[1]; }
+ /*! Returns the blue component of the specular color */
+ inline const float specularB() const { return Specular[2]; }
+ /*! Returns the alpha component of the specular color */
+ inline const float specularA() const { return Specular[3]; }
+
+ /*! Returns the ambiant color as a 4 float array */
+ inline const float * ambient() const { return Ambient; }
+ /*! Returns the red component of the ambiant color */
+ inline const float ambientR() const { return Ambient[0]; }
+ /*! Returns the green component of the ambiant color */
+ inline const float ambientG() const { return Ambient[1]; }
+ /*! Returns the blue component of the ambiant color */
+ inline const float ambientB() const { return Ambient[2]; }
+ /*! Returns the alpha component of the ambiant color */
+ inline const float ambientA() const { return Ambient[3]; }
+
+ /*! Returns the emissive color as a 4 float array */
+ inline const float * emission() const { return Emission; }
+ /*! Returns the red component of the emissive color */
+ inline const float emissionR() const { return Emission[0]; }
+ /*! Returns the green component of the emissive color */
+ inline const float emissionG() const { return Emission[1]; }
+ /*! Returns the blue component of the emissive color */
+ inline const float emissionB() const { return Emission[2]; }
+ /*! Returns the alpha component of the emissive color */
+ inline const float emissionA() const { return Emission[3]; }
+
+ /*! Returns the shininess coefficient */
+ inline const float shininess() const { return Shininess; }
+
+ /*! Sets the diffuse color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setDiffuse(const float r, const float g, const float b, const float a);
+ /*! Sets the specular color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setSpecular(const float r, const float g, const float b, const float a);
+ /*! Sets the ambiant color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setAmbient(const float r, const float g, const float b, const float a);
+
+ /*! Sets the emissive color.
+ * \param r
+ * Red component
+ * \param g
+ * Green component
+ * \param b
+ * Blue component
+ * \param a
+ * Alpha component
+ */
+ inline void setEmission(const float r, const float g, const float b, const float a);
+
+ /*! Sets the shininess.
+ * \param s
+ * Shininess
+ */
+ inline void setShininess(const float s);
+
+ /* operators */
+ inline FrsMaterial& operator=(const FrsMaterial& m);
+ inline bool operator!=(const FrsMaterial& m) const;
+ inline bool operator==(const FrsMaterial& m) const;
+
+private:
+
+ /*! Material properties */
+ float Diffuse[4];
+ float Specular[4];
+ float Ambient[4];
+ float Emission[4];
+ float Shininess;
+
+};
+
+FrsMaterial::FrsMaterial()
+{
+ Ambient[0] = Ambient[1] = Ambient[2] = 0.2f;
+ Ambient[3] = 1.f;
+
+ Diffuse[0] = Diffuse[1] = Diffuse[2] = 0.8f;
+ Diffuse[3] = 1.f;
+
+ Emission[0] = Emission[1] = Emission[2] = 0.f;
+ Emission[3] = 1.f;
+
+ Specular[0] = Specular[1] = Specular[2] = 0.f;
+ Specular[3] = 1.f;
+
+ Shininess = 0.f;
+}
+
+FrsMaterial::FrsMaterial(const float *iDiffuse,
+ const float *iAmbiant,
+ const float *iSpecular,
+ const float *iEmission,
+ const float iShininess)
+{
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = iDiffuse[i];
+ Specular[i] = iSpecular[i];
+ Ambient[i] = iAmbiant[i];
+ Emission[i] = iEmission[i];
+ }
+
+ Shininess = iShininess;
+}
+
+FrsMaterial::FrsMaterial(const FrsMaterial& m)
+{
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = m.diffuse()[i];
+ Specular[i] = m.specular()[i];
+ Ambient[i] = m.ambient()[i];
+ Emission[i] = m.emission()[i];
+ }
+
+ Shininess = m.shininess();
+}
+
+void FrsMaterial::setDiffuse(const float r, const float g, const float b, const float a)
+{
+ Diffuse[0] = r;
+ Diffuse[1] = g;
+ Diffuse[2] = b;
+ Diffuse[3] = a;
+}
+
+void FrsMaterial::setSpecular(const float r, const float g, const float b, const float a)
+{
+ Specular[0] = r;
+ Specular[1] = g;
+ Specular[2] = b;
+ Specular[3] = a;
+}
+
+void FrsMaterial::setAmbient(const float r, const float g, const float b, const float a)
+{
+ Ambient[0] = r;
+ Ambient[1] = g;
+ Ambient[2] = b;
+ Ambient[3] = a;
+}
+
+void FrsMaterial::setEmission(const float r, const float g, const float b, const float a)
+{
+ Emission[0] = r;
+ Emission[1] = g;
+ Emission[2] = b;
+ Emission[3] = a;
+}
+
+void FrsMaterial::setShininess(const float s)
+{
+ Shininess = s;
+}
+
+FrsMaterial& FrsMaterial::operator=(const FrsMaterial& m)
+{
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = m.diffuse()[i];
+ Specular[i] = m.specular()[i];
+ Ambient[i] = m.ambient()[i];
+ Emission[i] = m.emission()[i];
+ }
+
+ Shininess = m.shininess();
+
+ return *this;
+}
+
+bool FrsMaterial::operator!=(const FrsMaterial& m) const
+{
+ if(Shininess != m.shininess())
+ return true;
+ for(int i=0; i<4; i++)
+ {
+ if(Diffuse[i] != m.diffuse()[i])
+ return true;
+ if(Specular[i] != m.specular()[i])
+ return true;
+ if(Ambient[i] != m.ambient()[i])
+ return true;
+ if(Emission[i] != m.emission()[i])
+ return true;
+ }
+
+ return false;
+}
+
+bool FrsMaterial::operator==(const FrsMaterial& m) const
+{
+ return (!((*this)!=m));
+}
+
+#endif // FRS_MATERIAL_H
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
new file mode 100755
index 00000000000..98872c6c8ea
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -0,0 +1,321 @@
+
+//
+// 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 "IndexedFaceSet.h"
+
+IndexedFaceSet::IndexedFaceSet()
+: Rep()
+{
+ _Vertices = NULL;
+ _Normals = NULL;
+ _FrsMaterials = 0;
+ _TexCoords = 0;
+ _VSize = 0;
+ _NSize = 0;
+ _MSize = 0;
+ _TSize = 0;
+ _NumFaces = 0;
+ _NumVertexPerFace = NULL;
+ _FaceStyle = NULL;
+ _VIndices = NULL;
+ _VISize = 0;
+ _NIndices = NULL;
+ _NISize = 0;
+ _MIndices = NULL;
+ _MISize = 0;
+ _TIndices = NULL;
+ _TISize = 0;
+ _displayList = 0;
+}
+
+IndexedFaceSet::IndexedFaceSet( real *iVertices, unsigned iVSize,
+ real *iNormals, unsigned iNSize,
+ FrsMaterial **iMaterials, unsigned iMSize,
+ real *iTexCoords, unsigned iTSize,
+ unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle,
+ unsigned *iVIndices, unsigned iVISize,
+ unsigned *iNIndices, unsigned iNISize,
+ unsigned *iMIndices, unsigned iMISize,
+ unsigned *iTIndices, unsigned iTISize,
+ unsigned iCopy)
+ : Rep()
+{
+ if(1 == iCopy)
+ {
+ _VSize = iVSize;
+ _Vertices = new real[_VSize];
+ memcpy(_Vertices, iVertices, iVSize*sizeof(real));
+
+ _NSize = iNSize;
+ _Normals = new real[_NSize];
+ memcpy(_Normals, iNormals, iNSize*sizeof(real));
+
+ _MSize = iMSize;
+ _FrsMaterials = 0;
+ if(iMaterials){
+ _FrsMaterials = new FrsMaterial*[_MSize];
+ for(unsigned i=0; i<_MSize; ++i)
+ _FrsMaterials[i] = new FrsMaterial(*(iMaterials[i]));
+ }
+ _TSize = iTSize;
+ _TexCoords = 0;
+ if(_TSize){
+ _TexCoords = new real[_TSize];
+ memcpy(_TexCoords, iTexCoords, iTSize*sizeof(real));
+ }
+
+ _NumFaces = iNumFaces;
+ _NumVertexPerFace = new unsigned[_NumFaces];
+ memcpy(_NumVertexPerFace, iNumVertexPerFace, _NumFaces*sizeof(unsigned));
+
+ _FaceStyle = new TRIANGLES_STYLE[_NumFaces];
+ memcpy(_FaceStyle, iFaceStyle, _NumFaces*sizeof(TRIANGLES_STYLE));
+
+ _VISize = iVISize;
+ _VIndices = new unsigned[_VISize];
+ memcpy(_VIndices, iVIndices, _VISize*sizeof(unsigned));
+
+ _NISize = iNISize;
+ _NIndices = new unsigned[_NISize];
+ memcpy(_NIndices, iNIndices, _NISize*sizeof(unsigned));
+
+ _MISize = iMISize;
+ _MIndices = 0;
+ if(iMIndices){
+ _MIndices = new unsigned[_MISize];
+ memcpy(_MIndices, iMIndices, _MISize*sizeof(unsigned));
+ }
+ _TISize = iTISize;
+ _TIndices = 0;
+ if(_TISize){
+ _TIndices = new unsigned[_TISize];
+ memcpy(_TIndices, iTIndices, _TISize*sizeof(unsigned));
+ }
+ }
+ else
+ {
+ _VSize = iVSize;
+ _Vertices = iVertices;
+
+ _NSize = iNSize;
+ _Normals = iNormals;
+
+ _MSize = iMSize;
+ _FrsMaterials = 0;
+ if(iMaterials)
+ _FrsMaterials = iMaterials;
+
+ _TSize = iTSize;
+ _TexCoords = iTexCoords;
+
+ _NumFaces = iNumFaces;
+ _NumVertexPerFace = iNumVertexPerFace;
+ _FaceStyle = iFaceStyle;
+
+ _VISize = iVISize;
+ _VIndices = iVIndices;
+
+ _NISize = iNISize;
+ _NIndices = iNIndices;
+
+ _MISize = iMISize;
+ _MIndices = 0;
+ if(iMISize)
+ _MIndices = iMIndices;
+
+ _TISize = iTISize;
+ _TIndices = iTIndices;
+ }
+
+ _displayList = 0;
+}
+
+IndexedFaceSet::IndexedFaceSet( const IndexedFaceSet& iBrother)
+:Rep(iBrother)
+{
+ _VSize = iBrother.vsize();
+ _Vertices = new real[_VSize];
+ memcpy(_Vertices, iBrother.vertices(), _VSize*sizeof(real));
+
+ _NSize = iBrother.nsize();
+ _Normals = new real[_NSize];
+ memcpy(_Normals, iBrother.normals(), _NSize*sizeof(real));
+
+ _MSize = iBrother.msize();
+ if(_MSize){
+ _FrsMaterials = new FrsMaterial*[_MSize];
+ for(unsigned i=0; i<_MSize; ++i){
+ _FrsMaterials[i] = new FrsMaterial(*(iBrother._FrsMaterials[i]));
+ }
+ }else{
+ _FrsMaterials = 0;
+ }
+
+ _TSize = iBrother.tsize();
+ _TexCoords = 0;
+ if(_TSize){
+ _TexCoords = new real[_TSize];
+ memcpy(_TexCoords, iBrother.texCoords(), _TSize*sizeof(real));
+ }
+
+ _NumFaces = iBrother.numFaces();
+ _NumVertexPerFace = new unsigned[_NumFaces];
+ memcpy(_NumVertexPerFace, iBrother.numVertexPerFaces(), _NumFaces*sizeof(unsigned));
+
+ _FaceStyle = new TRIANGLES_STYLE[_NumFaces];
+ memcpy(_FaceStyle, iBrother.trianglesStyle(), _NumFaces*sizeof(TRIANGLES_STYLE));
+
+ _VISize = iBrother.visize();
+ _VIndices = new unsigned[_VISize];
+ memcpy(_VIndices, iBrother.vindices(), _VISize*sizeof(unsigned));
+
+ _NISize = iBrother.nisize();
+ _NIndices = new unsigned[_NISize];
+ memcpy(_NIndices, iBrother.nindices(), _NISize*sizeof(unsigned));
+
+ _MISize = iBrother.misize();
+ if(_MISize){
+ _MIndices = new unsigned[_MISize];
+ memcpy(_MIndices, iBrother.mindices(), _MISize*sizeof(unsigned));
+ }else{
+ _MIndices=0;
+ }
+
+ _TISize = iBrother.tisize();
+ _TIndices = 0;
+ if(_TISize){
+ _TIndices = new unsigned[_TISize];
+ memcpy(_TIndices, iBrother.tindices(), _TISize*sizeof(unsigned));
+ }
+
+ _displayList = 0;
+}
+
+IndexedFaceSet::~IndexedFaceSet()
+{
+ if(NULL != _Vertices)
+ {
+ delete [] _Vertices;
+ _Vertices = NULL;
+ }
+
+ if(NULL != _Normals)
+ {
+ delete [] _Normals;
+ _Normals = NULL;
+ }
+
+ if(NULL != _FrsMaterials)
+ {
+ for(unsigned i=0; i<_MSize; ++i)
+ delete _FrsMaterials[i];
+ delete [] _FrsMaterials;
+ _FrsMaterials = NULL;
+ }
+
+ if(NULL != _TexCoords)
+ {
+ delete [] _TexCoords;
+ _TexCoords = NULL;
+ }
+
+ if(NULL != _NumVertexPerFace)
+ {
+ delete [] _NumVertexPerFace;
+ _NumVertexPerFace = NULL;
+ }
+
+ if(NULL != _FaceStyle)
+ {
+ delete [] _FaceStyle;
+ _FaceStyle = NULL;
+ }
+
+ if(NULL != _VIndices)
+ {
+ delete [] _VIndices;
+ _VIndices = NULL;
+ }
+
+ if(NULL != _NIndices)
+ {
+ delete [] _NIndices;
+ _NIndices = NULL;
+ }
+
+ if(NULL != _MIndices)
+ {
+ delete [] _MIndices;
+ _MIndices = NULL;
+ }
+ if(NULL != _TIndices)
+ {
+ delete [] _TIndices;
+ _TIndices = NULL;
+ }
+ // should find a way to deallocates the displayList
+ // glDeleteLists(GLuint list, GLSizei range)
+ _displayList = 0;
+}
+
+void IndexedFaceSet::accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitIndexedFaceSet(*this);
+}
+
+void IndexedFaceSet::ComputeBBox()
+{
+ real XMax = _Vertices[0];
+ real YMax = _Vertices[1];
+ real ZMax = _Vertices[2];
+
+ real XMin = _Vertices[0];
+ real YMin = _Vertices[1];
+ real ZMin = _Vertices[2];
+
+ // parse all the coordinates to find
+ // the Xmax, YMax, ZMax
+ real *v = _Vertices;
+
+ for(unsigned i=0; i<_VSize/3; i++)
+ {
+ // X
+ if(*v > XMax)
+ XMax = *v;
+ if(*v < XMin)
+ XMin = *v;
+ v++;
+
+ if(*v > YMax)
+ YMax = *v;
+ if(*v < YMin)
+ YMin = *v;
+ v++;
+
+ if(*v > ZMax)
+ ZMax = *v;
+ if(*v < ZMin)
+ ZMin = *v;
+ v++;
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
new file mode 100755
index 00000000000..41db4db4c42
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -0,0 +1,222 @@
+//
+// Filename : IndexedFaceSet.h
+// Author(s) : Stephane Grabli
+// Purpose : A Set of indexed faces to represent a surfacic object
+// Date of creation : 22/01/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 INDEXEDFACESET_H
+# define INDEXEDFACESET_H
+
+# include <stdio.h>
+# include <memory.h>
+
+//! inherits from class Rep
+# include "Rep.h"
+
+# include "../system/FreestyleConfig.h"
+
+class LIB_SCENE_GRAPH_EXPORT IndexedFaceSet : public Rep
+ {
+public:
+
+ /*! Triangles description style:*/
+ enum TRIANGLES_STYLE{TRIANGLE_STRIP, TRIANGLE_FAN, TRIANGLES};
+
+ /*! Builds an empty indexed face set
+ */
+ IndexedFaceSet();
+ /*! Builds an indexed face set
+ iVertices
+ The array of object vertices 3D coordinates (for all faces).
+ If iCopy != 0, the array is copied; you must desallocate iVertices. Else you must not.
+ iVSize
+ The size of iVertices (must be a multiple of 3)
+ iNormals
+ The array of object normals 3D coordinates.
+ If iCopy != 0, the array is copied; you must desallocate iNormals. Else you must not.
+ iNSize
+ The size of iNormals
+ iMaterials
+ The array of materials
+ iMSize
+ The size of iMaterials
+ iTexCoords
+ The array of texture coordinates.
+ iTSize
+ The size of iTexCoords (must be multiple of 2)
+ iNumFaces
+ The number of faces
+ iNumVertexPerFace
+ Array containing the number of vertices per face.
+ iFaceStyle
+ Array containing the description style of each faces.
+ The style belongs to:
+ - TRIANGLE_STRIP: the face indices describe a triangle strip
+ - TRIANGLE_FAN : the face indices describe a triangle fan
+ - TRIANGLES : the face indices describe single triangles
+ If iCopy != 0, the array is copied; you must desallocate iFaceStyle. Else you must not.
+ iVIndices,
+ Array of vertices indices.
+ The integers contained in this array must be multiple of 3.
+ If iCopy != 0, the array is copied; you must desallocate iVIndices. Else you must not.
+ iVISize
+ The size of iVIndices.
+ iNIndices
+ Array of normals indices.
+ The integers contained in this array must be multiple of 3.
+ If iCopy != 0, the array is copied; you must desallocate iNIndices. Else you must not.
+ iNISize
+ The size of iNIndices
+ iMIndices
+ The Material indices (per vertex)
+ iMISize
+ The size of iMIndices
+ iTIndices
+ The Texture coordinates indices (per vertex). The integers contained in this array must be multiple of 2.
+ iTISize
+ The size of iMIndices
+ iCopy
+ 0 : the arrays are not copied. The pointers passed as arguments are used.
+ IndexedFaceSet takes these arrays desallocation in charge.
+ 1 : the arrays are copied. The caller is in charge of the arrays, passed
+ as arguments desallocation.
+ */
+ IndexedFaceSet( real *iVertices, unsigned iVSize,
+ real *iNormals, unsigned iNSize,
+ FrsMaterial **iMaterials, unsigned iMSize,
+ real *iTexCoords, unsigned iTSize,
+ unsigned iNumFaces, unsigned *iNumVertexPerFace, TRIANGLES_STYLE *iFaceStyle,
+ unsigned *iVIndices, unsigned iVISize,
+ unsigned *iNIndices, unsigned iNISize,
+ unsigned *iMIndices, unsigned iMISize,
+ unsigned *iTIndices, unsigned iTISize,
+ unsigned iCopy = 1
+ );
+
+ /*! Builds an indexed face set from an other indexed face set */
+ IndexedFaceSet(const IndexedFaceSet& iBrother);
+
+ void swap(IndexedFaceSet& ioOther){
+ std::swap(_Vertices, ioOther._Vertices);
+ std::swap(_Normals, ioOther._Normals);
+ std::swap(_FrsMaterials, ioOther._FrsMaterials);
+ std::swap(_TexCoords, ioOther._TexCoords);
+
+ std::swap(_VSize, ioOther._VSize);
+ std::swap(_NSize, ioOther._NSize);
+ std::swap(_MSize, ioOther._MSize);
+ std::swap(_TSize, ioOther._TSize);
+
+ std::swap(_NumFaces, ioOther._NumFaces);
+ std::swap(_NumVertexPerFace, ioOther._NumVertexPerFace);
+ std::swap(_FaceStyle, ioOther._FaceStyle);
+
+ std::swap(_VIndices, ioOther._VIndices);
+ std::swap(_NIndices, ioOther._NIndices);
+ std::swap(_MIndices, ioOther._MIndices); // Material Indices
+ std::swap(_TIndices, ioOther._TIndices);
+
+ std::swap(_VISize, ioOther._VISize);
+ std::swap(_NISize, ioOther._NISize);
+ std::swap(_MISize, ioOther._MISize);
+ std::swap(_TISize, ioOther._TISize);
+
+ std::swap(_displayList, ioOther._displayList);
+
+ Rep::swap(ioOther);
+ }
+
+ IndexedFaceSet& operator=(const IndexedFaceSet& iBrother){
+ IndexedFaceSet tmp(iBrother);
+ swap(tmp);
+ return *this;
+ }
+
+ /*! Desctructor
+ desallocates all the ressources */
+ virtual ~IndexedFaceSet();
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Compute the Bounding Box */
+ virtual void ComputeBBox();
+
+ /*! modifiers */
+ inline void setDisplayList(unsigned int index) {_displayList = index;}
+
+ /*! Accessors */
+ virtual const real * vertices() const {return _Vertices;}
+ virtual const real * normals() const {return _Normals;}
+ virtual const FrsMaterial*const* frs_materials() const {return _FrsMaterials;}
+ virtual const real* texCoords() const {return _TexCoords;}
+ virtual const unsigned vsize() const {return _VSize;}
+ virtual const unsigned nsize() const {return _NSize;}
+ virtual const unsigned msize() const {return _MSize;}
+ virtual const unsigned tsize() const {return _TSize;}
+ virtual const unsigned numFaces() const {return _NumFaces;}
+ virtual const unsigned * numVertexPerFaces() const {return _NumVertexPerFace;}
+ virtual const TRIANGLES_STYLE * trianglesStyle() const {return _FaceStyle;}
+ virtual const unsigned* vindices() const {return _VIndices;}
+ virtual const unsigned* nindices() const {return _NIndices;}
+ virtual const unsigned* mindices() const {return _MIndices;}
+ virtual const unsigned* tindices() const {return _TIndices;}
+ virtual const unsigned visize() const {return _VISize;}
+ virtual const unsigned nisize() const {return _NISize;}
+ virtual const unsigned misize() const {return _MISize;}
+ virtual const unsigned tisize() const {return _TISize;}
+ inline unsigned int displayList() const {return _displayList;}
+
+protected:
+ real *_Vertices;
+ real *_Normals;
+ FrsMaterial** _FrsMaterials;
+ real *_TexCoords;
+
+ unsigned _VSize;
+ unsigned _NSize;
+ unsigned _MSize;
+ unsigned _TSize;
+
+ unsigned _NumFaces;
+ unsigned *_NumVertexPerFace;
+ TRIANGLES_STYLE *_FaceStyle;
+
+ unsigned *_VIndices;
+ unsigned *_NIndices;
+ unsigned *_MIndices; // Material Indices
+ unsigned *_TIndices; // Texture coordinates Indices
+
+ unsigned _VISize;
+ unsigned _NISize;
+ unsigned _MISize;
+ unsigned _TISize;
+
+ unsigned int _displayList;
+
+};
+
+#endif // INDEXEDFACESET_H
diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.cpp b/source/blender/freestyle/intern/scene_graph/LineRep.cpp
new file mode 100755
index 00000000000..504db06acf4
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/LineRep.cpp
@@ -0,0 +1,58 @@
+
+//
+// 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 "LineRep.h"
+
+void LineRep::ComputeBBox()
+{
+ real XMax = _vertices.front()[0];
+ real YMax = _vertices.front()[1];
+ real ZMax = _vertices.front()[2];
+
+ real XMin = _vertices.front()[0];
+ real YMin = _vertices.front()[1];
+ real ZMin = _vertices.front()[2];
+
+ // parse all the coordinates to find
+ // the XMax, YMax, ZMax
+ vector<Vec3r>::iterator v;
+ for(v=_vertices.begin(); v!=_vertices.end(); v++) {
+ // X
+ if((*v)[0] > XMax)
+ XMax = (*v)[0];
+ if((*v)[0] < XMin)
+ XMin = (*v)[0];
+
+ // Y
+ if((*v)[1] > YMax)
+ YMax = (*v)[1];
+ if((*v)[1] < YMin)
+ YMin = (*v)[1];
+
+ // Z
+ if((*v)[2] > ZMax)
+ ZMax = (*v)[2];
+ if((*v)[2] < ZMin)
+ ZMin = (*v)[2];
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/LineRep.h b/source/blender/freestyle/intern/scene_graph/LineRep.h
new file mode 100755
index 00000000000..232557af857
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/LineRep.h
@@ -0,0 +1,130 @@
+//
+// Filename : LineRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the representation of 3D Line.
+// 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 LINEREP_H
+# define LINEREP_H
+
+# include <vector>
+# include <list>
+# include "Rep.h"
+# include "../system/FreestyleConfig.h"
+
+using namespace std;
+
+/*! Base class for all lines objects */
+class LIB_SCENE_GRAPH_EXPORT LineRep : public Rep
+{
+public:
+
+ /*! Line description style */
+ enum LINES_STYLE{LINES, LINE_STRIP, LINE_LOOP};
+ inline LineRep() : Rep() {_width = 0.f;}
+
+ /*! Builds a single line from 2 vertices
+ * v1
+ * first vertex
+ * v2
+ * second vertex
+ */
+ inline LineRep(const Vec3r& v1, const Vec3r& v2)
+ : Rep()
+ {
+ setStyle(LINES);
+ AddVertex(v1);
+ AddVertex(v2);
+ _width = 0.f;
+ }
+
+ /*! Builds a line rep from a vertex chain */
+ inline LineRep(const vector<Vec3r>& vertices)
+ : Rep()
+ {
+ _vertices = vertices;
+ setStyle(LINE_STRIP);
+ _width = 0.f;
+ }
+
+ /*! Builds a line rep from a vertex chain */
+ inline LineRep(const list<Vec3r>& vertices)
+ : Rep()
+ {
+ for(list<Vec3r>::const_iterator v=vertices.begin(), end=vertices.end();
+ v!=end;
+ v++)
+ {
+ _vertices.push_back(*v);
+ }
+ setStyle(LINE_STRIP);
+ _width = 0.f;
+ }
+
+ virtual ~LineRep()
+ {
+ _vertices.clear();
+ }
+
+ /*! accessors */
+ inline const LINES_STYLE style() const {return _Style;}
+ inline const vector<Vec3r>& vertices() const {return _vertices;}
+ inline float width() const {return _width;}
+
+ /*! modifiers */
+ inline void setStyle(const LINES_STYLE iStyle) {_Style = iStyle;}
+ inline void AddVertex(const Vec3r& iVertex) {_vertices.push_back(iVertex);}
+ inline void setVertices(const vector<Vec3r>& iVertices)
+ {
+ if(0 != _vertices.size())
+ {
+ _vertices.clear();
+ }
+ for(vector<Vec3r>::const_iterator v=iVertices.begin(), end=iVertices.end();
+ v!=end;
+ v++)
+ {
+ _vertices.push_back(*v);
+ }
+ }
+ inline void setWidth(float iWidth) {_width=iWidth;}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitLineRep(*this);
+ }
+
+ /*! Computes the line bounding box.*/
+ virtual void ComputeBBox();
+
+private:
+ LINES_STYLE _Style;
+ vector<Vec3r> _vertices;
+ float _width;
+};
+
+#endif // LINEREP_H
diff --git a/source/blender/freestyle/intern/scene_graph/Node.h b/source/blender/freestyle/intern/scene_graph/Node.h
new file mode 100755
index 00000000000..41afaa353be
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Node.h
@@ -0,0 +1,97 @@
+//
+// Filename : Node.h
+// Author(s) : Stephane Grabli
+// Purpose : Abstract class for scene graph nodes. Inherits from
+// BaseObject which defines the addRef release mechanism.
+// Date of creation : 24/01/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 NODE_H
+# define NODE_H
+
+# include "../system/FreestyleConfig.h"
+# include "../system/BaseObject.h"
+# include "SceneVisitor.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "../system/Precision.h"
+
+using namespace std;
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT Node : public BaseObject
+{
+public:
+
+ inline Node() : BaseObject() {}
+ inline Node(const Node& iBrother) : BaseObject()
+ {
+ _BBox = iBrother.bbox();
+ }
+ virtual ~Node(){}
+
+ /*! Accept the corresponding visitor
+ * Each inherited node
+ * must overload this method
+ */
+ virtual void accept(SceneVisitor& v) {
+ v.visitNode(*this);
+ }
+
+ /*! bounding box management */
+ /*! Returns the node bounding box
+ * If no bounding box exists, an empty bbox
+ * is returned
+ */
+ virtual const BBox<Vec3r>& bbox() const {return _BBox;}
+
+ /*! Sets the Node bounding box */
+ virtual void setBBox(const BBox<Vec3r>& iBox) {_BBox = iBox;}
+
+ /*! Makes the union of _BBox and iBox */
+ virtual void AddBBox(const BBox<Vec3r>& iBox)
+ {
+ if(iBox.empty())
+ return;
+
+ if(_BBox.empty())
+ _BBox = iBox;
+ else
+ _BBox += iBox;
+ }
+
+ /*! Updates the BBox */
+ virtual const BBox<Vec3r>& UpdateBBox() {return _BBox;}
+
+ /*! Clears the bounding box */
+ virtual void clearBBox() { _BBox.clear(); }
+
+protected:
+
+private:
+ BBox<Vec3r> _BBox;
+};
+
+#endif // NODE_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp
new file mode 100644
index 00000000000..1d095b35a0d
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.cpp
@@ -0,0 +1,120 @@
+#include <string.h> // for memcpy
+#include "NodeCamera.h"
+#include <math.h>
+
+void loadIdentity(double * matrix){
+ int i;
+
+ // Build Identity matrix
+ for(i=0;i<16;++i){
+ double value ;
+ if((i % 5) == 0)
+ value = 1.0;
+ else
+ value = 0;
+ matrix[i] = value;
+ }
+}
+
+NodeCamera::NodeCamera(CameraType camera_type)
+:camera_type_(camera_type){
+ loadIdentity(modelview_matrix_);
+ loadIdentity(projection_matrix_);
+}
+
+NodeCamera::NodeCamera(const NodeCamera& iBrother)
+:camera_type_(iBrother.camera_type_){
+ memcpy(modelview_matrix_, iBrother.modelview_matrix_, 16*sizeof(double));
+ memcpy(projection_matrix_, iBrother.projection_matrix_, 16*sizeof(double));
+}
+
+void NodeCamera::accept(SceneVisitor& v){
+ v.visitNodeCamera(*this) ;
+}
+
+void NodeCamera::setModelViewMatrix(double modelview_matrix[16]){
+ memcpy(modelview_matrix_, modelview_matrix,16*sizeof(double));
+}
+
+void NodeCamera::setProjectionMatrix(double projection_matrix[16]){
+ memcpy(projection_matrix_, projection_matrix,16*sizeof(double));
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera()
+:NodeCamera(NodeCamera::ORTHOGRAPHIC),
+left_(0),right_(0),bottom_(0),top_(0),zNear_(0),zFar_(0){
+ loadIdentity(projection_matrix_);
+ loadIdentity(modelview_matrix_);
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera(double left
+ , double right
+ , double bottom
+ , double top
+ , double zNear
+ , double zFar
+ )
+:NodeCamera(NodeCamera::ORTHOGRAPHIC),
+left_(left),
+right_(right),
+bottom_(bottom),
+top_(top),
+zNear_(zNear),
+zFar_(zFar){
+
+ loadIdentity(projection_matrix_);
+
+ projection_matrix_[0] = 2.0/(right-left);
+ projection_matrix_[3] = -(right + left) / (right - left) ;
+ projection_matrix_[5] = 2.0/(top-bottom);
+ projection_matrix_[7] = -(top + bottom) / (top - bottom) ;
+ projection_matrix_[10] = -2.0/(zFar-zNear);
+ projection_matrix_[11] = -(zFar + zNear) / (zFar - zNear);
+
+}
+
+NodeOrthographicCamera::NodeOrthographicCamera(const NodeOrthographicCamera& iBrother)
+:NodeCamera(iBrother),left_(iBrother.left_),right_(iBrother.right_),bottom_(iBrother.bottom_),top_(iBrother.top_),zNear_(iBrother.zNear_),zFar_(iBrother.zFar_){
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera()
+:NodeCamera(NodeCamera::PERSPECTIVE){
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera(double fovy
+ , double aspect
+ , double zNear
+ , double zFar)
+:NodeCamera(NodeCamera::PERSPECTIVE){
+ loadIdentity(projection_matrix_);
+
+ double f = cos(fovy/2.0)/sin(fovy/2.0); // cotangent
+
+ projection_matrix_[0] = f/aspect;
+ projection_matrix_[5] = f;
+ projection_matrix_[10] = (zNear+zFar)/(zNear-zFar);
+ projection_matrix_[11] = (2.0*zNear*zFar)/(zNear-zFar);
+ projection_matrix_[14] = -1.0;
+ projection_matrix_[15] = 0;
+
+}
+
+NodePerspectiveCamera::NodePerspectiveCamera(double left,
+ double right,
+ double bottom,
+ double top,
+ double zNear,
+ double zFar)
+:NodeCamera(NodeCamera::PERSPECTIVE){
+ loadIdentity(projection_matrix_);
+
+ projection_matrix_[0] = (2.0*zNear)/(right-left);
+ projection_matrix_[2] = (right+left)/(right-left);
+ projection_matrix_[5] = (2.0*zNear)/(top-bottom);
+ projection_matrix_[6] = (top+bottom)/(top-bottom);
+ projection_matrix_[10] = - (zFar+zNear)/(zFar-zNear);
+ projection_matrix_[11] = - (2.0*zFar*zNear)/(zFar-zNear);
+ projection_matrix_[14] = -1.0;
+ projection_matrix_[15] = 0;
+}
+
diff --git a/source/blender/freestyle/intern/scene_graph/NodeCamera.h b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
new file mode 100644
index 00000000000..cdd6fa83048
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeCamera.h
@@ -0,0 +1,192 @@
+//
+// Filename : NodeCamera.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a light node
+// Date of creation : 25/01/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 NODE_CAMERA_H_
+#define NODE_CAMERA_H_
+
+# include "../geometry/Geom.h"
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+
+using namespace Geometry;
+
+class NodeOrthographicCamera;
+class NodePerspectiveCamera;
+class LIB_SCENE_GRAPH_EXPORT NodeCamera : public Node
+{
+public:
+ typedef enum {PERSPECTIVE,ORTHOGRAPHIC,GENERIC} CameraType;
+
+ /*! Default matrices: Identity for both projection and modelview. */
+ NodeCamera(CameraType camera_type = GENERIC);
+ NodeCamera(const NodeCamera& iBrother);
+
+ virtual ~NodeCamera() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Matrix is copied */
+ void setModelViewMatrix(double modelview_matrix[16]);
+ /*! Matrix is copied */
+ void setProjectionMatrix(double projection_matrix[16]);
+
+ double * modelViewMatrix() {return modelview_matrix_;}
+ double * projectionMatrix() {return projection_matrix_;}
+
+protected:
+ // row major right handed matrix
+ double modelview_matrix_[16];
+ // row major right handed matrix
+ double projection_matrix_[16];
+
+ CameraType camera_type_;
+};
+
+class LIB_SCENE_GRAPH_EXPORT NodeOrthographicCamera : public NodeCamera{
+public:
+ NodeOrthographicCamera();
+ /*! Builds a parallel projection matrix a la glOrtho.
+ A 0 0 tx
+ 0 B 0 ty
+ 0 0 C tz
+ 0 0 0 1
+
+ where
+
+ A =
+ 2 / (right - left)
+ B =
+ 2 / (top - bottom)
+ C =
+ -2 / (far - near)
+ tx =
+ -(right + left) / (right - left)
+ ty =
+ -(top + bottom) / (top - bottom)
+ tz =
+ -(zFar + zNear) / (zFar - zNear)
+ */
+ NodeOrthographicCamera(double left
+ , double right
+ , double bottom
+ , double top
+ , double zNear
+ , double zFar
+ );
+
+ double left() const {return left_;}
+ double right() const {return right_;}
+ double bottom() const {return bottom_;}
+ double top() const {return top_;}
+ double zNear() const {return zNear_;}
+ double zFar() const {return zFar_;}
+
+ NodeOrthographicCamera(const NodeOrthographicCamera& iBrother);
+
+private:
+ double left_;
+ double right_;
+ double bottom_;
+ double top_;
+ double zNear_;
+ double zFar_;
+};
+
+class LIB_SCENE_GRAPH_EXPORT NodePerspectiveCamera : public NodeCamera {
+public:
+ NodePerspectiveCamera();
+ /*! Builds a perspective projection matrix a la gluPerspective.
+ Given f defined as follows:
+ fovy
+ f = cotangent(____)
+ 2
+ The generated matrix is
+
+
+ ( f )
+ | ______ |
+ | aspect 0 0 0 |
+ | |
+ | 0 f 0 0 |
+ | |
+ | zNear+zFar 2*zNear*zFar |
+ | __________ ____________ |
+ | 0 0 zNear-zFar zNear-zFar |
+ | |
+ ( 0 0 -1 0 )
+ \param fovy
+ Field of View specified in radians.
+ */
+ NodePerspectiveCamera(double fovy
+ , double aspect
+ , double zNear
+ , double zFar);
+
+ /*! Builds a perspective projection matrix a la glFrustum.
+ ( 2*zNear )
+ | __________ |
+ | right-left 0 A 0 |
+ | |
+ | 2*zNear |
+ | 0 __________ B 0 |
+ | top-bottom |
+ | |
+ | 0 0 C D |
+ | |
+ | 0 0 -1 0 |
+ ( )
+
+ right+left
+ A = __________
+ right-left
+
+ top+bottom
+ B = __________
+ top-bottom
+
+ zFar+zNear
+ C = - __________
+ zFar-zNear
+
+ 2*zFar*zNear
+ D = - ____________
+ zFar-zNear
+ */
+ NodePerspectiveCamera(double left,
+ double right,
+ double bottom,
+ double top,
+ double zNear,
+ double zFar);
+};
+
+
+#endif // NODE_CAMERA_H_
diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
new file mode 100755
index 00000000000..acd740ee055
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.cpp
@@ -0,0 +1,34 @@
+
+//
+// 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 "NodeDrawingStyle.h"
+
+void NodeDrawingStyle::accept(SceneVisitor& v) {
+ v.visitNodeDrawingStyle(*this);
+
+ v.visitNodeDrawingStyleBefore(*this);
+ v.visitDrawingStyle(_DrawingStyle);
+ for(vector<Node*>::iterator node=_Children.begin(), end=_Children.end();
+ node!=end;
+ node++)
+ (*node)->accept(v);
+ v.visitNodeDrawingStyleAfter(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h
new file mode 100755
index 00000000000..012f963ea8c
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeDrawingStyle.h
@@ -0,0 +1,70 @@
+//
+// Filename : NodeDrawingStyle.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a Drawing Style to be applied
+// to the underlying children. Inherits from NodeGroup.
+// Date of creation : 06/02/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 NODEDRAWINGSTYLE_H
+# define NODEDRAWINGSTYLE_H
+
+# include "../system/FreestyleConfig.h"
+# include "NodeGroup.h"
+# include "DrawingStyle.h"
+
+class LIB_SCENE_GRAPH_EXPORT NodeDrawingStyle : public NodeGroup
+{
+public:
+
+ inline NodeDrawingStyle() : NodeGroup() {}
+ virtual ~NodeDrawingStyle() {}
+
+ inline const DrawingStyle& drawingStyle() const { return _DrawingStyle; }
+ inline void setDrawingStyle(const DrawingStyle& iDrawingStyle) { _DrawingStyle = iDrawingStyle; }
+
+ /*! Sets the style. Must be one of FILLED, LINES, POINTS, INVISIBLE. */
+ inline void setStyle(const DrawingStyle::STYLE iStyle) { _DrawingStyle.setStyle(iStyle); }
+ /*! Sets the line width in the LINES style case */
+ inline void setLineWidth(const float iLineWidth) { _DrawingStyle.setLineWidth(iLineWidth); }
+ /*! Sets the Point size in the POINTS style case */
+ inline void setPointSize(const float iPointSize) { _DrawingStyle.setPointSize(iPointSize); }
+ /*! Enables or disables the lighting. TRUE = enable */
+ inline void setLightingEnabled(const bool iEnableLighting) { _DrawingStyle.setLightingEnabled(iEnableLighting); }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! accessors */
+ inline DrawingStyle::STYLE style() const {return _DrawingStyle.style();}
+ inline float lineWidth() const {return _DrawingStyle.lineWidth();}
+ inline float pointSize() const {return _DrawingStyle.pointSize();}
+ inline bool lightingEnabled() const {return _DrawingStyle.lightingEnabled();}
+
+private:
+ DrawingStyle _DrawingStyle;
+};
+
+#endif // NODEDRAWINGSTYLE_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp
new file mode 100755
index 00000000000..3d2aa2c8694
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.cpp
@@ -0,0 +1,122 @@
+
+//
+// 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 "NodeGroup.h"
+
+void NodeGroup::AddChild(Node *iChild)
+{
+ if(NULL == iChild)
+ return;
+
+ _Children.push_back(iChild);
+ iChild->addRef();
+}
+
+int NodeGroup::destroy()
+{
+ /*! Node::destroy makes a release on the object
+ * and then returns the reference counter.
+ * If the reference counter is equal to 0,
+ * that means that nobody else is linking
+ * this node group and that we can destroy the whole
+ * underlying tree.
+ * Else, one or several Node link this node group,
+ * and we only returns the reference counter
+ * decremented by Node::destroy();
+ */
+ int refThis = Node::destroy();
+
+ // if refThis != 0, we can't destroy the tree
+ if(0 != refThis)
+ return refThis;
+
+ // If we are here, that means that nobody else
+ // needs our NodeGroup and we can destroy it.
+ int refCount = 0;
+ vector<Node *>::iterator node;
+
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ refCount = (*node)->destroy();
+ if(0 == refCount)
+ delete (*node);
+ }
+
+ _Children.clear();
+
+ return refThis;
+}
+
+void NodeGroup::accept(SceneVisitor& v) {
+ v.visitNodeGroup(*this);
+
+ v.visitNodeGroupBefore(*this);
+ for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end();
+ node!=end;
+ node++)
+ (*node)->accept(v);
+ v.visitNodeGroupAfter(*this);
+}
+
+void NodeGroup::DetachChildren()
+{
+ vector<Node *>::iterator node;
+
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ (*node)->release();
+ }
+
+ _Children.clear();
+}
+
+void NodeGroup::DetachChild(Node *iChild)
+{
+ int found = 0;
+ vector<Node*>::iterator node;
+
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ if((*node) == iChild)
+ {
+ (*node)->release();
+ _Children.erase(node);
+ found = 1;
+ break;
+ }
+ }
+}
+
+void NodeGroup::RetrieveChildren(vector<Node*>& oNodes){
+ oNodes = _Children;
+}
+
+const BBox<Vec3r>& NodeGroup::UpdateBBox()
+{
+ vector<Node *>::iterator node;
+ clearBBox();
+ for(node=_Children.begin(); node!=_Children.end(); node++)
+ {
+ AddBBox((*node)->UpdateBBox());
+ }
+
+ return Node::UpdateBBox();
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeGroup.h b/source/blender/freestyle/intern/scene_graph/NodeGroup.h
new file mode 100755
index 00000000000..a1bd2b57e56
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeGroup.h
@@ -0,0 +1,84 @@
+//
+// Filename : NodeGroup.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a group node. This node can contains
+// several children. It also contains a transform matrix
+// indicating the transform state of the underlying
+// children.
+// Date of creation : 24/01/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 NODEGROUP_H
+# define NODEGROUP_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+
+using namespace std;
+
+class LIB_SCENE_GRAPH_EXPORT NodeGroup : public Node
+{
+public:
+
+ inline NodeGroup(): Node() {}
+ virtual ~NodeGroup(){}
+
+ /*! Adds a child. Makes a addRef on the
+ * iChild reference counter */
+ virtual void AddChild(Node *iChild);
+
+ /*! destroys all the underlying nodes
+ * Returns the reference counter
+ * after having done a release() */
+ virtual int destroy();
+
+ /*! Detaches all the children */
+ virtual void DetachChildren();
+
+ /*! Detached the sepcified child */
+ virtual void DetachChild(Node *iChild);
+
+ /*! Retrieve children */
+ virtual void RetrieveChildren(vector<Node*>& oNodes);
+
+
+ /*! Renders every children */
+ // virtual void Render(Renderer *iRenderer);
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Updates the BBox */
+ virtual const BBox<Vec3r>& UpdateBBox();
+
+ /*! Returns the number of children */
+ virtual int numberOfChildren() {return _Children.size();}
+
+protected:
+ vector<Node*> _Children;
+};
+
+#endif // NODEGROUP_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.cpp b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp
new file mode 100755
index 00000000000..61a46155cfa
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.cpp
@@ -0,0 +1,80 @@
+
+//
+// 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 "NodeLight.h"
+
+int NodeLight::numberOfLights = 0;
+
+NodeLight::NodeLight()
+: Node()
+{
+ if(numberOfLights > 7)
+ {
+ _number = 7;
+ }
+ else
+ {
+ _number = numberOfLights;
+ numberOfLights++;
+ }
+
+ Ambient[0] = Ambient[1] = Ambient[2] = 0.f;
+ Ambient[3] = 1.f;
+
+ for(int i=0; i<4; i++)
+ {
+ Diffuse[i] = 1.f;
+ Specular[i] = 1.f;
+ }
+
+ Position[0] = Position[1] = Position[3] = 0.f;
+ Position[2] = 1.f;
+
+ on = true;
+}
+
+NodeLight::NodeLight(NodeLight& iBrother)
+: Node(iBrother)
+{
+ if(numberOfLights > 7)
+ {
+ _number = 7;
+ }
+ else
+ {
+ _number = numberOfLights;
+ numberOfLights++;
+ }
+
+ for(int i=0; i<4; i++)
+ {
+ Ambient[i] = iBrother.ambient()[i];
+ Diffuse[i] = iBrother.diffuse()[i];
+ Specular[i] = iBrother.specular()[i];
+ Position[i] = iBrother.position()[i];
+ }
+
+ on = iBrother.isOn();
+}
+
+void NodeLight::accept(SceneVisitor& v) {
+ v.visitNodeLight(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeLight.h b/source/blender/freestyle/intern/scene_graph/NodeLight.h
new file mode 100755
index 00000000000..0689505fb24
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeLight.h
@@ -0,0 +1,86 @@
+//
+// Filename : NodeLight.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a light node
+// Date of creation : 25/01/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 NODELIGHT_H
+# define NODELIGHT_H
+
+# include "../geometry/Geom.h"
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeLight : public Node
+{
+public:
+
+ NodeLight();
+ NodeLight(NodeLight& iBrother);
+
+ virtual ~NodeLight() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Accessors for the light properties */
+ inline const float * ambient() const {return Ambient;}
+ inline const float * diffuse() const {return Diffuse;}
+ inline const float * specular() const {return Specular;}
+ inline const float * position() const {return Position;}
+ inline bool isOn() const {return on;}
+ inline int number() const {return _number;}
+
+private:
+ // Data members
+ // ============
+
+ /*! on=true, the light is on */
+ bool on;
+
+ /*! The color definition */
+ float Ambient[4];
+ float Diffuse[4];
+ float Specular[4];
+
+ /*! Light position. if w = 0, the light is
+ * placed at infinite.
+ */
+ float Position[4];
+
+ /*! used to manage the number of lights */
+ /*! numberOfLights
+ * the number of lights in the scene.
+ * Initially, 0.
+ */
+ static int numberOfLights;
+ /*! The current lignt number */
+ int _number;
+};
+
+#endif // NODELIGHT_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.cpp b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp
new file mode 100755
index 00000000000..9083c852d36
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeShape.cpp
@@ -0,0 +1,51 @@
+
+//
+// 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 "NodeShape.h"
+
+NodeShape::~NodeShape()
+{
+ vector<Rep *>::iterator rep;
+
+ if(0 != _Shapes.size())
+ {
+ for(rep=_Shapes.begin(); rep!=_Shapes.end(); rep++)
+ {
+ int refCount = (*rep)->destroy();
+ if(0 == refCount)
+ delete (*rep);
+ }
+
+ _Shapes.clear();
+ }
+}
+
+void NodeShape::accept(SceneVisitor& v) {
+ v.visitNodeShape(*this);
+
+ v.visitFrsMaterial(_FrsMaterial);
+
+ v.visitNodeShapeBefore(*this);
+ vector<Rep *>::iterator rep;
+ for(rep = _Shapes.begin(); rep != _Shapes.end(); rep++)
+ (*rep)->accept(v);
+ v.visitNodeShapeAfter(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeShape.h b/source/blender/freestyle/intern/scene_graph/NodeShape.h
new file mode 100755
index 00000000000..9849d4661b8
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeShape.h
@@ -0,0 +1,89 @@
+//
+// Filename : NodeShape.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build a shape node. It contains a Rep,
+// which is the shape geometry
+// Date of creation : 25/01/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 NODESHAPE_H
+# define NODESHAPE_H
+
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "Node.h"
+# include "Rep.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "FrsMaterial.h"
+
+using namespace std;
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeShape : public Node
+{
+public:
+
+ inline NodeShape() : Node() {}
+
+ virtual ~NodeShape();
+
+ /*! Adds a Rep to the _Shapes list
+ * The delete of the rep is done
+ * when it is not used any more by
+ * the Scene Manager. So, it must not
+ * be deleted by the caller
+ */
+ virtual void AddRep(Rep *iRep)
+ {
+ if(NULL == iRep)
+ return;
+ _Shapes.push_back(iRep);
+ iRep->addRef();
+
+ // updates bbox:
+ AddBBox(iRep->bbox());
+ }
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Sets the shape material */
+ inline void setFrsMaterial(const FrsMaterial& iMaterial) { _FrsMaterial = iMaterial; }
+
+ /*! accessors */
+ /*! returns the shape's material */
+ inline FrsMaterial& frs_material() { return _FrsMaterial; }
+ inline const vector<Rep*>& shapes() {return _Shapes;}
+
+private:
+ /*! list of shapes */
+ vector<Rep*> _Shapes;
+
+ /*! Shape Material */
+ FrsMaterial _FrsMaterial;
+};
+
+#endif // NODESHAPE_H
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
new file mode 100755
index 00000000000..8f706c78259
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.cpp
@@ -0,0 +1,166 @@
+//
+// 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 "../system/FreestyleConfig.h"
+#include "NodeTransform.h"
+
+void NodeTransform::Translate(real x, real y, real z)
+{
+ _Matrix(0, 3) += x;
+ _Matrix(1, 3) += y;
+ _Matrix(2, 3) += z;
+}
+
+void NodeTransform::Rotate(real iAngle, real x, real y, real z)
+{
+ //Normalize the x,y,z vector;
+ real norm = (real)sqrt(x*x+y*y+z*z);
+ if(0 == norm)
+ return;
+
+ x /= norm;
+ y /= norm;
+ z /= norm;
+
+ // find the corresponding matrix with the Rodrigues formula:
+ // R = I + sin(iAngle)*Ntilda + (1-cos(iAngle))*Ntilda*Ntilda
+ Matrix33r Ntilda;
+ Ntilda(0,0) = Ntilda(1,1) = Ntilda(2,2) = 0.f;
+ Ntilda(0,1) = -z;
+ Ntilda(0,2) = y;
+ Ntilda(1,0) = z;
+ Ntilda(1,2) = -x;
+ Ntilda(2,0) = -y;
+ Ntilda(2,1) = x;
+
+ const Matrix33r Ntilda2(Ntilda * Ntilda);
+
+
+ const real sinAngle = (real)sin((iAngle/180.f)*M_PI);
+ const real cosAngle = (real)cos((iAngle/180.f)*M_PI);
+
+ Matrix33r NS(Ntilda*sinAngle);
+ Matrix33r NC(Ntilda2*(1.f-cosAngle));
+ Matrix33r R;
+ R = Matrix33r::identity();
+ R += NS + NC;
+
+ //R4 is the corresponding 4x4 matrix
+ Matrix44r R4;
+ R4 = Matrix44r::identity();
+
+ for(int i=0; i<3; i++)
+ for(int j=0; j<3; j++)
+ R4(i,j) = R(i,j);
+
+ // Finally, we multiply our current matrix by R4:
+ Matrix44r mat_tmp(_Matrix);
+ _Matrix = mat_tmp * R4;
+}
+
+void NodeTransform::Scale(real x, real y, real z)
+{
+ _Matrix(0,0) *= x;
+ _Matrix(1,1) *= y;
+ _Matrix(2,2) *= z;
+
+ _Scaled = true;
+}
+
+void NodeTransform::MultiplyMatrix(const Matrix44r &iMatrix)
+{
+ Matrix44r mat_tmp(_Matrix);
+ _Matrix = mat_tmp * iMatrix;
+}
+
+void NodeTransform::setMatrix(const Matrix44r &iMatrix)
+{
+ _Matrix = iMatrix;
+ if(isScaled(iMatrix))
+ _Scaled = true;
+}
+
+void NodeTransform::accept(SceneVisitor& v) {
+ v.visitNodeTransform(*this);
+
+ v.visitNodeTransformBefore(*this);
+ for(vector<Node *>::iterator node=_Children.begin(), end=_Children.end();
+ node!=end;
+ node++)
+ (*node)->accept(v);
+ v.visitNodeTransformAfter(*this);
+}
+
+void NodeTransform::AddBBox(const BBox<Vec3r>& iBBox)
+{
+ Vec3r oldMin(iBBox.getMin());
+ Vec3r oldMax(iBBox.getMax());
+
+ // compute the 8 corners of the bbox
+ HVec3r box[8];
+ box[0] = HVec3r(iBBox.getMin());
+ box[1] = HVec3r(oldMax[0], oldMin[1], oldMin[2]);
+ box[2] = HVec3r(oldMax[0], oldMax[1], oldMin[2]);
+ box[3] = HVec3r(oldMin[0], oldMax[1], oldMin[2]);
+ box[4] = HVec3r(oldMin[0], oldMin[1], oldMax[2]);
+ box[5] = HVec3r(oldMax[0], oldMin[1], oldMax[2]);
+ box[6] = HVec3r(oldMax[0], oldMax[1], oldMax[2]);
+ box[7] = HVec3r(oldMin[0], oldMax[1], oldMax[2]);
+
+ // Computes the transform iBBox
+ HVec3r tbox[8];
+ unsigned i;
+ for(i = 0; i < 8; i++)
+ tbox[i] = _Matrix * box[i];
+
+ Vec3r newMin(tbox[0]);
+ Vec3r newMax(tbox[0]);
+ for (i=0; i<8; i++)
+ {
+ for (unsigned int j=0; j<3; j++)
+ {
+ if (newMin[j] > tbox[i][j])
+ newMin[j] = tbox[i][j];
+ if (newMax[j] < tbox[i][j])
+ newMax[j] = tbox[i][j];
+ }
+ }
+
+ BBox<Vec3r> transformBox(newMin, newMax);
+
+ Node::AddBBox(transformBox);
+}
+
+bool NodeTransform::isScaled(const Matrix44r &M)
+{
+ for(unsigned int j=0; j<3; j++)
+ {
+ real norm = 0;
+ for(unsigned int i=0; i<3; i++)
+ {
+ norm += M(i,j)*M(i,j);
+ }
+ if((norm > 1.01) || (norm < 0.99))
+ return true;
+ }
+
+ return false;
+}
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.h b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
new file mode 100755
index 00000000000..e75132466f0
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
@@ -0,0 +1,107 @@
+//
+// Filename : NodeTransform.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to represent a transform node. A Transform node
+// contains one or several children, all affected by the
+// transformation.
+// Date of creation : 06/02/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 NODETRANSFORM_H
+# define NODETRANSFORM_H
+
+# include "../geometry/Geom.h"
+# include "../system/FreestyleConfig.h"
+# include "NodeGroup.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT NodeTransform : public NodeGroup
+{
+public:
+
+ inline NodeTransform() : NodeGroup() {
+ _Matrix = Matrix44r::identity();
+ _Scaled=false;
+ }
+
+ virtual ~NodeTransform() {}
+
+ /*! multiplys the current matrix by the
+ * x, y, z translation matrix.
+ */
+ void Translate(real x, real y, real z);
+
+ /*! multiplys the current matrix by a
+ * rotation matrix
+ * iAngle
+ * The rotation angle
+ * x, y, z
+ * The rotation axis
+ */
+ void Rotate(real iAngle, real x, real y, real z);
+
+ /*! multiplys the current matrix by a
+ * scaling matrix.
+ * x, y, z
+ * The scaling coefficients
+ * with respect to the x,y,z axis
+ */
+ void Scale(real x, real y, real z);
+
+ /*! Multiplys the current matrix
+ * by iMatrix
+ */
+ void MultiplyMatrix(const Matrix44r &iMatrix);
+
+ /*! Sets the current matrix to iMatrix */
+ void setMatrix(const Matrix44r &iMatrix);
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+
+ /*! Overloads the Node::AddBBox in order to take care
+ * about the transformation
+ */
+ virtual void AddBBox(const BBox<Vec3r>& iBBox);
+
+ /*! Checks whether a matrix contains a scale factor
+ * or not.
+ * Returns true if yes.
+ * iMatrix
+ * The matrix to check
+ */
+ bool isScaled(const Matrix44r &M);
+
+ /*! accessors */
+ inline const Matrix44r& matrix() const { return _Matrix; }
+ inline bool scaled() const {return _Scaled;}
+
+private:
+ Matrix44r _Matrix;
+ bool _Scaled;
+};
+
+#endif // NODETRANSFORM_H
diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
new file mode 100755
index 00000000000..94068983596
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.cpp
@@ -0,0 +1,31 @@
+
+//
+// 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 "OrientedLineRep.h"
+#include "../system/BaseObject.h"
+
+void OrientedLineRep::accept(SceneVisitor& v) {
+ Rep::accept(v);
+ if(!frs_material())
+ v.visitOrientedLineRep(*this);
+ else
+ v.visitLineRep(*this);
+}
diff --git a/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h
new file mode 100755
index 00000000000..4274581e39a
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/OrientedLineRep.h
@@ -0,0 +1,67 @@
+//
+// Filename : OrientedLineRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to display an oriented line representation.
+// Date of creation : 24/10/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 VIEWEDGEREP_H
+# define VIEWEDGEREP_H
+
+# include "../system/FreestyleConfig.h"
+# include "LineRep.h"
+
+class LIB_SCENE_GRAPH_EXPORT OrientedLineRep : public LineRep
+{
+public:
+
+ OrientedLineRep() : LineRep() {}
+ /*! Builds a single line from 2 vertices
+ * v1
+ * first vertex
+ * v2
+ * second vertex
+ */
+ inline OrientedLineRep(const Vec3r& v1, const Vec3r& v2)
+ : LineRep(v1,v2)
+ {}
+
+ /*! Builds a line rep from a vertex chain */
+ inline OrientedLineRep(const vector<Vec3r>& vertices)
+ : LineRep(vertices)
+ {}
+
+ /*! Builds a line rep from a vertex chain */
+ inline OrientedLineRep(const list<Vec3r>& vertices)
+ : LineRep(vertices)
+ {}
+
+ virtual ~OrientedLineRep() {}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v);
+};
+
+#endif // VIEWEDGEREP_H
diff --git a/source/blender/freestyle/intern/scene_graph/Rep.cpp b/source/blender/freestyle/intern/scene_graph/Rep.cpp
new file mode 100755
index 00000000000..84ad2c2a966
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Rep.cpp
@@ -0,0 +1 @@
+#include "Rep.h"
diff --git a/source/blender/freestyle/intern/scene_graph/Rep.h b/source/blender/freestyle/intern/scene_graph/Rep.h
new file mode 100755
index 00000000000..6b213b01ba7
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/Rep.h
@@ -0,0 +1,127 @@
+//
+// Filename : Rep.h
+// Author(s) : Stephane Grabli
+// Purpose : Base class for all shapes. Inherits from BasicObjects
+// for references counter management (addRef, release).
+// Date of creation : 25/01/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 REP_H
+# define REP_H
+
+# include "../system/BaseObject.h"
+# include "SceneVisitor.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+# include "../system/Precision.h"
+# include "FrsMaterial.h"
+# include "../system/Id.h"
+
+using namespace Geometry;
+
+class LIB_SCENE_GRAPH_EXPORT Rep : public BaseObject
+{
+public:
+
+ inline Rep() : BaseObject() {_Id = 0; _FrsMaterial=0;}
+ inline Rep(const Rep& iBrother)
+ : BaseObject()
+ {
+ _Id = iBrother._Id;
+ if(0 == iBrother._FrsMaterial)
+ _FrsMaterial = 0;
+ else
+ _FrsMaterial = new FrsMaterial(*(iBrother._FrsMaterial));
+
+ _BBox = iBrother.bbox();
+ }
+ inline void swap(Rep& ioOther){
+ std::swap(_BBox,ioOther._BBox);
+ std::swap(_Id, ioOther._Id);
+ std::swap(_FrsMaterial,ioOther._FrsMaterial);
+ }
+ Rep& operator=(const Rep& iBrother){
+ if(&iBrother != this){
+ _Id = iBrother._Id;
+ if(0 == iBrother._FrsMaterial)
+ _FrsMaterial = 0;
+ else{
+ if(_FrsMaterial == 0){
+ _FrsMaterial = new FrsMaterial(*iBrother._FrsMaterial);
+ }else{
+ (*_FrsMaterial)=(*(iBrother._FrsMaterial));
+ }
+ _BBox = iBrother.bbox();
+ }
+ }
+ return *this;
+ }
+ virtual ~Rep()
+ {
+ if(0 != _FrsMaterial)
+ {
+ delete _FrsMaterial;
+ _FrsMaterial = 0;
+ }
+ }
+
+ /*! Accept the corresponding visitor
+ * Must be overload by
+ * inherited classes
+ */
+ virtual void accept(SceneVisitor& v) {
+ if(_FrsMaterial)
+ v.visitFrsMaterial(*_FrsMaterial);
+ v.visitRep(*this);
+ }
+
+ /*! Computes the rep bounding box.
+ * Each Inherited rep must compute
+ * its bbox depending on the way the data
+ * are stored. So, each inherited class
+ * must overload this method
+ */
+ virtual void ComputeBBox() = 0;
+
+ /*! Returns the rep bounding box */
+ virtual const BBox<Vec3r>& bbox() const {return _BBox;}
+ inline Id getId() const {return _Id;}
+ inline const FrsMaterial * frs_material() const {return _FrsMaterial;}
+
+ /*! Sets the Rep bounding box */
+ virtual void setBBox(const BBox<Vec3r>& iBox) {_BBox = iBox;}
+ inline void setId(const Id& id) {_Id = id;}
+ inline void setFrsMaterial(const FrsMaterial& iMaterial)
+ {
+ _FrsMaterial = new FrsMaterial(iMaterial);
+ }
+
+private:
+ BBox<Vec3r> _BBox;
+ Id _Id;
+ FrsMaterial *_FrsMaterial;
+};
+
+#endif // REP_H
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
new file mode 100755
index 00000000000..aeee87f8222
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.cpp
@@ -0,0 +1,86 @@
+
+//
+// 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 <iomanip>
+#include "ScenePrettyPrinter.h"
+#include "IndexedFaceSet.h"
+
+#define VISIT(CLASS) \
+ void ScenePrettyPrinter::visit##CLASS(CLASS&) { \
+ _ofs << _space << #CLASS << endl; \
+ }
+
+VISIT(Node)
+VISIT(NodeShape)
+VISIT(NodeGroup)
+VISIT(NodeLight)
+VISIT(NodeDrawingStyle)
+VISIT(NodeTransform)
+
+void ScenePrettyPrinter::visitNodeShapeBefore(NodeShape&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeShapeAfter(NodeShape&) {
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeGroupBefore(NodeGroup&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeGroupAfter(NodeGroup&) {
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeDrawingStyleBefore(NodeDrawingStyle&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeDrawingStyleAfter(NodeDrawingStyle&) {
+ decreaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeTransformBefore(NodeTransform&) {
+ increaseSpace();
+}
+
+void ScenePrettyPrinter::visitNodeTransformAfter(NodeTransform&) {
+ decreaseSpace();
+}
+
+VISIT(LineRep)
+VISIT(OrientedLineRep)
+VISIT(TriangleRep)
+VISIT(VertexRep)
+
+void ScenePrettyPrinter::visitIndexedFaceSet(IndexedFaceSet& ifs) {
+ const real* vertices = ifs.vertices();
+ unsigned vsize = ifs.vsize();
+
+ _ofs << _space << "IndexedFaceSet" << endl;
+ const real *p = vertices;
+ for (unsigned i = 0; i < vsize / 3; i++) {
+ _ofs << _space << " " << setw(3) << setfill('0') << i << ": "
+ << p[0] << ", " << p[1] << ", " << p[2] << endl;
+ p += 3;
+ }
+}
diff --git a/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
new file mode 100755
index 00000000000..4e83825ff55
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/ScenePrettyPrinter.h
@@ -0,0 +1,105 @@
+//
+// Filename : ScenePrettyPrinter.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class to display textual information
+// about a scene graph.
+// Date of creation : 26/04/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 SCENE_PRETTY_PRINTER_H
+# define SCENE_PRETTY_PRINTER_H
+
+# include <iostream>
+# include <fstream>
+# include <string>
+# include "SceneVisitor.h"
+
+using namespace std;
+
+class ScenePrettyPrinter : public SceneVisitor
+{
+public:
+
+ ScenePrettyPrinter(const string filename = "SceneLog.txt")
+ : SceneVisitor() {
+ if (!filename.empty())
+ _ofs.open(filename.c_str());
+ if (!_ofs.is_open())
+ cerr << "Warning, unable to open file \"" << filename << "\"" << endl;
+ _space = "";
+ }
+
+ virtual ~ScenePrettyPrinter() {
+ if (_ofs.is_open())
+ _ofs.close();
+ }
+
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_DECL(Node)
+ VISIT_DECL(NodeShape)
+ VISIT_DECL(NodeGroup)
+ VISIT_DECL(NodeLight)
+ VISIT_DECL(NodeDrawingStyle)
+ VISIT_DECL(NodeTransform)
+
+ VISIT_DECL(LineRep)
+ VISIT_DECL(OrientedLineRep)
+ VISIT_DECL(TriangleRep)
+ VISIT_DECL(VertexRep)
+ VISIT_DECL(IndexedFaceSet)
+
+ virtual void visitNodeShapeBefore(NodeShape&);
+ virtual void visitNodeShapeAfter(NodeShape&);
+ virtual void visitNodeGroupBefore(NodeGroup&);
+ virtual void visitNodeGroupAfter(NodeGroup&);
+ virtual void visitNodeDrawingStyleBefore(NodeDrawingStyle&);
+ virtual void visitNodeDrawingStyleAfter(NodeDrawingStyle&);
+ virtual void visitNodeTransformBefore(NodeTransform&);
+ virtual void visitNodeTransformAfter(NodeTransform&);
+
+ protected:
+
+ void increaseSpace()
+ {
+ _space += " ";
+ }
+
+ void decreaseSpace()
+ {
+ _space.erase(0, 2);
+ }
+
+ private:
+
+ ofstream _ofs;
+ string _space;
+};
+
+#endif // SCENE_PRETTY_PRINTER_H
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp
new file mode 100755
index 00000000000..da9c94930bd
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.cpp
@@ -0,0 +1 @@
+#include "SceneVisitor.h"
diff --git a/source/blender/freestyle/intern/scene_graph/SceneVisitor.h b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
new file mode 100755
index 00000000000..5f67b4b44aa
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/SceneVisitor.h
@@ -0,0 +1,98 @@
+//
+// Filename : SceneVisitor.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Class to visit (without doing anything)
+// a scene graph structure
+// Date of creation : 26/04/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 SCENE_VISITOR_H
+# define SCENE_VISITOR_H
+
+# define VISIT_COMPLETE_DEF(type) \
+virtual void visit##type(type&) {} \
+virtual void visit##type##Before(type&) {} \
+virtual void visit##type##After(type&) {}
+
+# define VISIT_DECL(type) virtual void visit##type(type&);
+
+# define VISIT_COMPLETE_DECL(type) \
+ virtual void visit##type##Before(type&); \
+ virtual void visit##type(type&); \
+ virtual void visit##type##After(type&);
+
+#include "../system/FreestyleConfig.h"
+
+class Node;
+class NodeShape;
+class NodeGroup;
+class NodeLight;
+class NodeCamera;
+class NodeDrawingStyle;
+class NodeTransform;
+
+class Rep;
+class LineRep;
+class OrientedLineRep;
+class TriangleRep;
+class VertexRep;
+class IndexedFaceSet;
+class DrawingStyle;
+class FrsMaterial;
+
+class LIB_SCENE_GRAPH_EXPORT SceneVisitor
+{
+public:
+
+ SceneVisitor() {}
+ virtual ~SceneVisitor() {}
+
+ virtual void beginScene() {}
+ virtual void endScene() {}
+
+ //
+ // visitClass methods
+ //
+ //////////////////////////////////////////////
+
+ VISIT_COMPLETE_DEF(Node)
+ VISIT_COMPLETE_DEF(NodeShape)
+ VISIT_COMPLETE_DEF(NodeGroup)
+ VISIT_COMPLETE_DEF(NodeLight)
+ VISIT_COMPLETE_DEF(NodeCamera)
+ VISIT_COMPLETE_DEF(NodeDrawingStyle)
+ VISIT_COMPLETE_DEF(NodeTransform)
+
+ VISIT_COMPLETE_DEF(Rep)
+ VISIT_COMPLETE_DEF(LineRep)
+ VISIT_COMPLETE_DEF(OrientedLineRep)
+ VISIT_COMPLETE_DEF(TriangleRep)
+ VISIT_COMPLETE_DEF(VertexRep)
+ VISIT_COMPLETE_DEF(IndexedFaceSet)
+ VISIT_COMPLETE_DEF(DrawingStyle)
+ VISIT_COMPLETE_DEF(FrsMaterial)
+};
+
+#endif // SCENEVISITOR_H
diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp
new file mode 100755
index 00000000000..f73a8498714
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.cpp
@@ -0,0 +1,59 @@
+
+//
+// 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 "TriangleRep.h"
+
+void TriangleRep::ComputeBBox()
+{
+ real XMax = _vertices[0][0];
+ real YMax = _vertices[0][1];
+ real ZMax = _vertices[0][2];
+
+ real XMin = _vertices[0][0];
+ real YMin = _vertices[0][1];
+ real ZMin = _vertices[0][2];
+
+ // parse all the coordinates to find
+ // the XMax, YMax, ZMax
+ for(int i=0; i<3; ++i)
+ {
+ // X
+ if(_vertices[i][0] > XMax)
+ XMax = _vertices[i][0];
+ if(_vertices[i][0] < XMin)
+ XMin = _vertices[i][0];
+
+ // Y
+ if(_vertices[i][1] > YMax)
+ YMax = _vertices[i][1];
+ if(_vertices[i][1] < YMin)
+ YMin = _vertices[i][1];
+
+ // Z
+ if(_vertices[i][2] > ZMax)
+ ZMax = _vertices[i][2];
+ if(_vertices[i][2] < ZMin)
+ ZMin = _vertices[i][2];
+
+ }
+
+ setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax)));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/TriangleRep.h b/source/blender/freestyle/intern/scene_graph/TriangleRep.h
new file mode 100755
index 00000000000..9d986857060
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/TriangleRep.h
@@ -0,0 +1,106 @@
+//
+// Filename : TriangleRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the represenation of a triangle
+// Date of creation : 16/12/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 TRIANGLEREP_H
+# define TRIANGLEREP_H
+
+//! inherits from class Rep
+#include "Rep.h"
+
+/*! Base class for all lines objects */
+class LIB_SCENE_GRAPH_EXPORT TriangleRep : public Rep
+{
+public:
+
+ /*! Line description style */
+ enum TRIANGLE_STYLE{FILL, LINES};
+private:
+ TRIANGLE_STYLE _Style;
+ Vec3r _vertices[3];
+ Vec3r _colors[3];
+public:
+ inline TriangleRep() : Rep() {_Style = FILL;}
+
+ /*! Builds a triangle from 3 vertices
+ * v0
+ * first vertex
+ * v1
+ * second vertex
+ * v2
+ * third vertex
+ */
+ inline TriangleRep(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2)
+ : Rep()
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ _Style = FILL;
+ }
+ inline TriangleRep( const Vec3r& v0, const Vec3r& c0,
+ const Vec3r& v1, const Vec3r& c1,
+ const Vec3r& v2, const Vec3r& c2)
+ : Rep()
+ {
+ _vertices[0] = v0;
+ _vertices[1] = v1;
+ _vertices[2] = v2;
+ _colors[0] = c0;
+ _colors[1] = c1;
+ _colors[2] = c2;
+ _Style = FILL;
+ }
+
+ virtual ~TriangleRep()
+ {}
+
+ /*! accessors */
+ inline const TRIANGLE_STYLE style() const {return _Style;}
+ inline const Vec3r& vertex(int index) const {return _vertices[index];}
+ inline const Vec3r& color(int index) const {return _colors[index];}
+ /*! modifiers */
+ inline void setStyle(const TRIANGLE_STYLE iStyle) {_Style = iStyle;}
+ inline void setVertex(int index, const Vec3r& iVertex) {_vertices[index] = iVertex;}
+ inline void setColor(int index, const Vec3r& iColor) {_colors[index] = iColor;}
+ inline void setVertices(const Vec3r& v0, const Vec3r& v1, const Vec3r& v2) {_vertices[0] = v0; _vertices[1] = v1; _vertices[2] = v2;}
+ inline void setColors(const Vec3r& c0, const Vec3r& c1, const Vec3r& c2) {_colors[0] = c0; _colors[1] = c1; _colors[2] = c2;}
+
+ /*! Accept the corresponding visitor */
+ virtual void accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitTriangleRep(*this);
+ }
+
+ /*! Computes the triangle bounding box.*/
+ virtual void ComputeBBox();
+
+
+};
+
+#endif
diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.cpp b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp
new file mode 100755
index 00000000000..e4f774bfb84
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/VertexRep.cpp
@@ -0,0 +1,29 @@
+
+//
+// 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 "VertexRep.h"
+
+void VertexRep::ComputeBBox()
+{
+
+ setBBox(BBox<Vec3r>(Vec3r(_coordinates[0], _coordinates[1], _coordinates[2]),
+ Vec3r(_coordinates[0], _coordinates[1], _coordinates[2])));
+}
diff --git a/source/blender/freestyle/intern/scene_graph/VertexRep.h b/source/blender/freestyle/intern/scene_graph/VertexRep.h
new file mode 100755
index 00000000000..9e31b4b8ef9
--- /dev/null
+++ b/source/blender/freestyle/intern/scene_graph/VertexRep.h
@@ -0,0 +1,87 @@
+//
+// Filename : VertexRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the representation of a vertex for
+// displaying purpose.
+// Date of creation : 03/04/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 VERTEXREP_H
+# define VERTEXREP_H
+
+#include "Rep.h"
+
+class LIB_SCENE_GRAPH_EXPORT VertexRep : public Rep
+{
+public:
+
+ inline VertexRep() : Rep() {_vid = 0;_PointSize = 0.f;}
+ inline VertexRep(real x, real y, real z, int id = 0)
+ : Rep()
+ {
+ _coordinates[0] = x;
+ _coordinates[1] = y;
+ _coordinates[2] = z;
+
+ _vid = id;
+ _PointSize = 0.f;
+ }
+
+ inline ~VertexRep() {}
+
+ /*! Accept the corresponding visitor */
+
+ virtual void accept(SceneVisitor& v) {
+ Rep::accept(v);
+ v.visitVertexRep(*this);
+ }
+
+ /*! Computes the rep bounding box.
+ */
+ virtual void ComputeBBox();
+
+ /*! accessors */
+ inline const int vid() const {return _vid;}
+ inline const real * coordinates() const {return _coordinates;}
+ inline real x() const {return _coordinates[0];}
+ inline real y() const {return _coordinates[1];}
+ inline real z() const {return _coordinates[2];}
+ inline float pointSize() const {return _PointSize;}
+
+ /*! modifiers */
+ inline void setVid(int id) {_vid = id;}
+ inline void setX(real x) {_coordinates[0] = x;}
+ inline void setY(real y) {_coordinates[1] = y;}
+ inline void setZ(real z) {_coordinates[2] = z;}
+ inline void setCoordinates(real x, real y, real z) {_coordinates[0] = x;_coordinates[1] = y; _coordinates[2] = z;}
+ inline void setPointSize(float iPointSize) {_PointSize = iPointSize;}
+
+private:
+ int _vid; // vertex id
+ real _coordinates[3];
+ float _PointSize;
+};
+
+#endif // VERTEXREP_H
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp
new file mode 100755
index 00000000000..7a51a1a78df
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.cpp
@@ -0,0 +1,92 @@
+
+//
+// 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 "../view_map/Functions0D.h"
+# include "AdvancedFunctions0D.h"
+# include "../view_map/SteerableViewMap.h"
+# include "Canvas.h"
+
+namespace Functions0D {
+
+ int DensityF0D::operator()(Interface0DIterator& iter) {
+ Canvas* canvas = Canvas::getInstance();
+ int bound = _filter.getBound();
+ if( (iter->getProjectedX()-bound < 0) || (iter->getProjectedX()+bound>canvas->width())
+ || (iter->getProjectedY()-bound < 0) || (iter->getProjectedY()+bound>canvas->height())) {
+ result = 0.0;
+ return 0;
+ }
+ RGBImage image;
+ canvas->readColorPixels((int)iter->getProjectedX() - bound,
+ (int)iter->getProjectedY() - bound,
+ _filter.maskSize(),
+ _filter.maskSize(),
+ image);
+ result = _filter.getSmoothedPixel<RGBImage>(&image, (int)iter->getProjectedX(),
+ (int)iter->getProjectedY());
+ return 0;
+ }
+
+
+ int LocalAverageDepthF0D::operator()(Interface0DIterator& iter) {
+ Canvas * iViewer = Canvas::getInstance();
+ int bound = _filter.getBound();
+
+ if( (iter->getProjectedX()-bound < 0) || (iter->getProjectedX()+bound>iViewer->width())
+ || (iter->getProjectedY()-bound < 0) || (iter->getProjectedY()+bound>iViewer->height())) {
+ result = 0.0;
+ return 0;
+ }
+ GrayImage image ;
+ iViewer->readDepthPixels((int)iter->getProjectedX()-bound,(int)iter->getProjectedY()-bound,_filter.maskSize(),_filter.maskSize(),image);
+ result = _filter.getSmoothedPixel(&image, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int ReadMapPixelF0D::operator()(Interface0DIterator& iter) {
+ Canvas * canvas = Canvas::getInstance();
+ result = canvas->readMapPixel(_mapName, _level, (int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int ReadSteerableViewMapPixelF0D::operator()(Interface0DIterator& iter) {
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ result = svm->readSteerableViewMapPixel(_orientation, _level,(int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int ReadCompleteViewMapPixelF0D::operator()(Interface0DIterator& iter) {
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ result = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY());
+ return 0;
+ }
+
+ int GetViewMapGradientNormF0D::operator()(Interface0DIterator& iter){
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ float pxy = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY());
+ float gx = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX()+_step, (int)iter->getProjectedY())
+ - pxy;
+ float gy = svm->readCompleteViewMapPixel(_level,(int)iter->getProjectedX(), (int)iter->getProjectedY()+_step)
+ - pxy;
+ result = Vec2f(gx,gy).norm();
+ return 0;
+ }
+} // end of namespace Functions0D
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h
new file mode 100755
index 00000000000..5d62ea8d9eb
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions0D.h
@@ -0,0 +1,209 @@
+//
+// Filename : AdvancedFunctions0D.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 ADVANCED_FUNCTIONS0D_HPP
+# define ADVANCED_FUNCTIONS0D_HPP
+
+
+# include "../image/Image.h"
+# include "../image/GaussianFilter.h"
+# include "../view_map/Functions0D.h"
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions0D {
+
+ // DensityF0D
+ /*! Returns the density of the (result) image evaluated at an Interface0D.
+ * This density is evaluated using a pixels square window around the
+ * evaluation point and integrating these values using
+ * a gaussian.
+ */
+ class LIB_STROKE_EXPORT DensityF0D : public UnaryFunction0D<double>
+ {
+ public:
+ /*! Builds the functor from the gaussian sigma value.
+ * \param sigma
+ * sigma indicates the x value for which the gaussian
+ * function is 0.5. It leads to the window size
+ * value. (the larger, the smoother)
+ */
+ DensityF0D(double sigma = 2) : UnaryFunction0D<double>() {
+ _filter.setSigma((float)sigma);
+ }
+ /*! Returns the string "DensityF0D"*/
+ string getName() const {
+ return "DensityF0D";
+ }
+ /*! The () operator. */
+ int operator()(Interface0DIterator& iter);
+
+ private:
+
+ GaussianFilter _filter;
+ };
+
+ // LocalAverageDepthF0D
+ /*! Returns the average depth around a point.
+ * The result is obtained by querying the
+ * depth buffer on a window around that point.
+ */
+ class LIB_STROKE_EXPORT LocalAverageDepthF0D : public UnaryFunction0D<double>
+ {
+ private:
+ GaussianFilter _filter;
+ public:
+ /*! Builds the functor from the size of the mask that
+ * will be used.
+ */
+ LocalAverageDepthF0D(real maskSize=5.f) : UnaryFunction0D<double>() {
+ _filter.setSigma((float)maskSize/2.f);
+ }
+ /*! Returns the string "LocalAverageDepthF0D"*/
+ string getName() const {
+ return "LocalAverageDepthF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ReadMapPixel
+ /*! Reads a pixel in a map.
+ */
+ class LIB_STROKE_EXPORT ReadMapPixelF0D : public UnaryFunction0D<float>
+ {
+ private:
+ const char * _mapName;
+ int _level;
+ public:
+ /*! Builds the functor from name of the
+ * Map that must be read.
+ * \param iMapName
+ * The name of the map.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ ReadMapPixelF0D(const char *iMapName, int level) : UnaryFunction0D<float>() {
+ _mapName = iMapName;
+ _level = level;
+ }
+ /*! Returns the string "ReadMapPixelF0D"*/
+ string getName() const {
+ return "ReadMapPixelF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ReadSteerableViewMapPixel
+ /*! Reads a pixel in one of the level of one of the steerable viewmaps.
+ */
+ class LIB_STROKE_EXPORT ReadSteerableViewMapPixelF0D : public UnaryFunction0D<float>
+ {
+ private:
+ unsigned _orientation;
+ int _level;
+ public:
+ /*! Builds the functor
+ * \param nOrientation
+ * The integer belonging to [0,4] indicating the orientation (E,NE,N,NW)
+ * we are interested in.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ ReadSteerableViewMapPixelF0D(unsigned nOrientation, int level) : UnaryFunction0D<float>() {
+ _orientation = nOrientation;
+ _level = level;
+ }
+ /*! Returns the string "ReadSteerableViewMapPixelF0D"*/
+ string getName() const {
+ return "ReadSteerableViewMapPixelF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // ReadCompleteViewMapPixel
+ /*! Reads a pixel in one of the level of the complete viewmap.
+ */
+ class LIB_STROKE_EXPORT ReadCompleteViewMapPixelF0D : public UnaryFunction0D<float>
+ {
+ private:
+ int _level;
+ public:
+ /*! Builds the functor
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ ReadCompleteViewMapPixelF0D(int level) : UnaryFunction0D<float>() {
+ _level = level;
+ }
+ /*! Returns the string "ReadCompleteViewMapPixelF0D"*/
+ string getName() const {
+ return "ReadCompleteViewMapPixelF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+
+ // GetViewMapGradientNormF0D
+ /*! Returns the norm of the gradient of the global viewmap density image.
+ */
+ class LIB_STROKE_EXPORT GetViewMapGradientNormF0D: public UnaryFunction0D< float>
+ {
+ private:
+ int _level;
+ float _step;
+ public:
+ /*! Builds the functor
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ */
+ GetViewMapGradientNormF0D(int level) : UnaryFunction0D<float>() {
+ _level = level;
+ _step = (float)pow(2.0,_level);
+ }
+ /*! Returns the string "GetOccludeeF0D"*/
+ string getName() const {
+ return "GetViewMapGradientNormF0D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface0DIterator& iter);
+ };
+} // end of namespace Functions0D
+
+#endif // ADVANCED_FUNCTIONS0D_HPP
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
new file mode 100755
index 00000000000..2548ce38659
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.cpp
@@ -0,0 +1,110 @@
+
+//
+// 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 "AdvancedFunctions1D.h"
+# include "../view_map/SteerableViewMap.h"
+# include "Canvas.h"
+
+// FIXME
+namespace Functions1D {
+
+ int GetSteerableViewMapDensityF1D::operator()(Interface1D& inter) {
+ SteerableViewMap * svm = Canvas::getInstance()->getSteerableViewMap();
+ Interface0DIterator it = inter.pointsBegin(_sampling);
+ Interface0DIterator itnext = it;++itnext;
+ FEdge *fe;
+ unsigned nSVM;
+ vector<float> values;
+ while(!itnext.isEnd()){
+ Interface0D& i0D = (*it);
+ Interface0D& i0Dnext = (*itnext);
+ fe = i0D.getFEdge(i0Dnext);
+ if(fe == 0){
+ cerr << "GetSteerableViewMapDensityF1D warning: no FEdge between " << i0D.getId() << " and " << i0Dnext.getId() << endl;
+ // compute the direction between these two ???
+ Vec2f dir = i0Dnext.getPoint2D()-i0D.getPoint2D();
+ nSVM = svm->getSVMNumber(dir);
+ }else{
+ nSVM = svm->getSVMNumber(fe->getId().getFirst());
+ }
+ Vec2r m((i0D.getProjectedX()+i0Dnext.getProjectedX())/2.0,
+ (i0D.getProjectedY()+i0Dnext.getProjectedY())/2.0);
+ values.push_back(svm->readSteerableViewMapPixel(nSVM,_level,(int)m[0],(int)m[1]));
+ ++it;++itnext;
+ }
+ float res, res_tmp;
+ vector<float>::iterator v = values.begin(), vend=values.end();
+ unsigned size = 1;
+ switch(_integration) {
+ case MIN:
+ res = *v;++v;
+ for (; v!=vend; ++v) {
+ res_tmp = *v;
+ if (res_tmp < res)
+ res = res_tmp;
+ }
+ break;
+ case MAX:
+ res = *v;++v;
+ for (; v!=vend; ++v) {
+ res_tmp = *v;
+ if (res_tmp > res)
+ res = res_tmp;
+ }
+ break;
+ case FIRST:
+ res = *v;
+ break;
+ case LAST:
+ --vend;
+ res = *vend;
+ break;
+ case MEAN:
+ default:
+ res = *v;++v;
+ for (; v!=vend; ++v, ++size)
+ res += *v;
+ res /= (size ? size : 1);
+ break;
+ }
+ result = res;
+ return 0;
+ }
+
+ int GetDirectionalViewMapDensityF1D::operator()(Interface1D& inter) {
+ //soc unsigned size;
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+
+ int GetCompleteViewMapDensityF1D::operator()(Interface1D& inter) {
+ //soc unsigned size;
+ Id id = inter.getId();
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+
+ int GetViewMapGradientNormF1D::operator()(Interface1D& inter){
+ result = integrate(_func, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+}
+
diff --git a/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
new file mode 100755
index 00000000000..ab963c68034
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedFunctions1D.h
@@ -0,0 +1,288 @@
+//
+// Filename : AdvancedFunctions1D.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 ADVANCED_FUNCTIONS1D_HPP
+# define ADVANCED_FUNCTIONS1D_HPP
+
+
+# include "../view_map/Functions1D.h"
+# include "AdvancedFunctions0D.h"
+
+//
+// Functions definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Functions1D {
+
+ // DensityF1D
+ /*! Returns the density evaluated for an Interface1D.
+ * The density is evaluated for a set of points along
+ * the Interface1D (using the DensityF0D functor)
+ * with a user-defined sampling and
+ * then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class DensityF1D : public UnaryFunction1D<double>
+ {
+ private:
+ float _sampling;
+ public:
+ /*! Builds the functor.
+ * \param sigma
+ * Thesigma used in DensityF0D and determining
+ * the window size used in each density query.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ DensityF1D(double sigma = 2, IntegrationType iType = MEAN, float sampling=2.f) : UnaryFunction1D<double>(iType), _fun(sigma) {
+ _sampling = sampling;
+ }
+ /*! Destructor */
+ virtual ~DensityF1D(){}
+
+ /*! Returns the string "DensityF1D"*/
+ string getName() const {
+ return "DensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.pointsBegin(_sampling), inter.pointsEnd(_sampling), _integration);
+ return 0;
+ }
+ private:
+ Functions0D::DensityF0D _fun;
+ };
+
+ // LocalAverageDepthF1D
+ /*! Returns the average depth evaluated for an Interface1D.
+ * The average depth is evaluated for a set of points along
+ * the Interface1D (using the LocalAverageDepthF0D functor)
+ * with a user-defined sampling and
+ * then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class LocalAverageDepthF1D : public UnaryFunction1D<double>
+ {
+ public:
+ /*! Builds the functor.
+ * \param sigma
+ * The sigma used in DensityF0D and determining
+ * the window size used in each density query.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ */
+ LocalAverageDepthF1D(real sigma, IntegrationType iType = MEAN)
+ : UnaryFunction1D<double>(iType), _fun(sigma){
+ }
+ /*! Returns the string "LocalAverageDepthF1D"*/
+ string getName() const {
+ return "LocalAverageDepthF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+ private:
+ Functions0D::LocalAverageDepthF0D _fun;
+ };
+
+ // GetCompleteViewMapDensity
+ /*! Returns the density evaluated for an Interface1D in the
+ * complete viewmap image.
+ * The density is evaluated for a set of points along
+ * the Interface1D (using the ReadCompleteViewMapPixelF0D functor)
+ * and then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class LIB_STROKE_EXPORT GetCompleteViewMapDensityF1D : public UnaryFunction1D<double>
+ {
+ public:
+ /*! Builds the functor.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetCompleteViewMapDensityF1D(unsigned level, IntegrationType iType = MEAN, float sampling=2.f)
+ : UnaryFunction1D<double>(iType), _fun(level){_sampling = sampling;}
+ /*! Returns the string "GetCompleteViewMapDensityF1D"*/
+ string getName() const {
+ return "GetCompleteViewMapDensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+
+ private:
+ Functions0D::ReadCompleteViewMapPixelF0D _fun;
+ float _sampling;
+ };
+
+ // GetDirectionalViewMapDensity
+ /*! Returns the density evaluated for an Interface1D in of the
+ * steerable viewmaps image.
+ * The direction telling which Directional map to choose
+ * is explicitely specified by the user.
+ * The density is evaluated for a set of points along
+ * the Interface1D (using the ReadSteerableViewMapPixelF0D functor)
+ * and then integrated into a single value using
+ * a user-defined integration method.
+ */
+ class LIB_STROKE_EXPORT GetDirectionalViewMapDensityF1D : public UnaryFunction1D<double>
+ {
+ public:
+ /*! Builds the functor.
+ * \param iOrientation
+ * The number of the directional map
+ * we must work with.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetDirectionalViewMapDensityF1D(unsigned iOrientation, unsigned level, IntegrationType iType = MEAN, float sampling=2.f)
+ : UnaryFunction1D<double>(iType), _fun(iOrientation,level){_sampling = sampling;}
+ /*! Returns the string "GetDirectionalViewMapDensityF1D"*/
+ string getName() const {
+ return "GetDirectionalViewMapDensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+
+ private:
+ Functions0D::ReadSteerableViewMapPixelF0D _fun;
+ float _sampling;
+ };
+
+ // GetSteerableViewMapDensityF1D
+ /*! Returns the density of the viewmap
+ * for a given Interface1D. The density of each
+ * FEdge is evaluated in the proper steerable
+ * ViewMap depending on its oorientation.
+ */
+ class LIB_STROKE_EXPORT GetSteerableViewMapDensityF1D : public UnaryFunction1D<real>
+ {
+ private:
+ int _level;
+ float _sampling;
+ public:
+ /*! Builds the functor from the level
+ * of the pyramid from which the pixel must be read.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetSteerableViewMapDensityF1D(int level,IntegrationType iType = MEAN, float sampling=2.f) : UnaryFunction1D<real>(iType) {
+ _level = level;
+ _sampling = sampling;
+ }
+ /*! Destructor */
+ virtual ~GetSteerableViewMapDensityF1D(){}
+
+ /*! Returns the string "GetSteerableViewMapDensityF1D"*/
+ string getName() const {
+ return "GetSteerableViewMapDensityF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+
+ // GetViewMapGradientNormF1D
+ /*! Returns the density of the viewmap
+ * for a given Interface1D. The density of each
+ * FEdge is evaluated in the proper steerable
+ * ViewMap depending on its oorientation.
+ */
+ class LIB_STROKE_EXPORT GetViewMapGradientNormF1D : public UnaryFunction1D<real>
+ {
+ private:
+ int _level;
+ float _sampling;
+ Functions0D::GetViewMapGradientNormF0D _func;
+ public:
+ /*! Builds the functor from the level
+ * of the pyramid from which the pixel must be read.
+ * \param level
+ * The level of the pyramid from which
+ * the pixel must be read.
+ * \param iType
+ * The integration method used to compute
+ * a single value from a set of values.
+ * \param sampling
+ * The resolution used to sample the chain: the corresponding 0D function
+ * is evaluated at each sample point and the result is obtained by
+ * combining the resulting values into a single one, following the
+ * method specified by iType.
+ */
+ GetViewMapGradientNormF1D(int level,IntegrationType iType = MEAN, float sampling=2.f)
+ : UnaryFunction1D<real>(iType), _func(level) {
+ _level = level;
+ _sampling = sampling;
+ }
+
+ /*! Returns the string "GetSteerableViewMapDensityF1D"*/
+ string getName() const {
+ return "GetViewMapGradientNormF1D";
+ }
+ /*! the () operator.*/
+ int operator()(Interface1D& inter);
+ };
+} // end of namespace Functions1D
+
+#endif // ADVANCED_FUNCTIONS1D_HPP
diff --git a/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h
new file mode 100755
index 00000000000..91b63168aa9
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedPredicates1D.h
@@ -0,0 +1,84 @@
+//
+// Filename : AdvancedPredicates1D.h
+// Author(s) : Stephane Grabli
+// Purpose : Class gathering stroke creation algorithms
+// 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 ADVANCED_PREDICATES1D_H
+# define ADVANCED_PREDICATES1D_H
+
+# include <string>
+# include "../view_map/Interface1D.h"
+# include "AdvancedFunctions1D.h"
+# include "Predicates1D.h"
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates1D {
+
+ // DensityLowerThanUP1D
+ /*! Returns true if the density evaluated for the
+ * Interface1D is less than a user-defined density value.
+ */
+ class DensityLowerThanUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Builds the functor.
+ * \param threshold
+ * The value of the threshold density.
+ * Any Interface1D having a density lower than
+ * this threshold will match.
+ * \param sigma
+ * The sigma value defining the density evaluation window size
+ * used in the DensityF0D functor.
+ */
+ DensityLowerThanUP1D(double threshold, double sigma = 2) {
+ _threshold = threshold;
+ _sigma = sigma;
+ }
+ /*! Returns the string "DensityLowerThanUP1D"*/
+ string getName() const {
+ return "DensityLowerThanUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ Functions1D::DensityF1D fun(_sigma);
+ if (fun(inter) < 0)
+ return -1;
+ result = (fun.result < _threshold);
+ return 0;
+ }
+ private:
+ double _sigma;
+ double _threshold;
+ };
+
+} // end of namespace Predicates1D
+
+#endif // ADVANCED_PREDICATES1D_H
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
new file mode 100755
index 00000000000..05da47914f3
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
@@ -0,0 +1,431 @@
+
+//
+// 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 "AdvancedStrokeShaders.h"
+#include "../system/PseudoNoise.h"
+#include "../system/RandGen.h"
+#include "StrokeIterators.h"
+
+/////////////////////////////////////////
+//
+// CALLIGRAPHICS SHADER
+//
+/////////////////////////////////////////
+
+
+CalligraphicShader::CalligraphicShader (real iMinThickness, real iMaxThickness,
+ const Vec2f &iOrientation, bool clamp)
+ : StrokeShader()
+{
+ _minThickness=iMinThickness;
+ _maxThickness=iMaxThickness;
+ _orientation = iOrientation;
+ _orientation.normalize();
+ _clamp = clamp;
+}
+
+float ksinToto=0;
+
+int
+CalligraphicShader::shade(Stroke &ioStroke) const
+{
+ Interface0DIterator v;
+ Functions0D::VertexOrientation2DF0D fun;
+ StrokeVertex* sv;
+ for(v=ioStroke.verticesBegin();
+ !v.isEnd();
+ ++v)
+ {
+ real thickness;
+ if (fun(v) < 0)
+ return -1;
+ Vec2f vertexOri(fun.result);
+ Vec2r ori2d(-vertexOri[1], vertexOri[0]);
+ ori2d.normalizeSafe();
+ real scal = ori2d * _orientation;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ if (_clamp && (scal<0)) {
+ scal=0.0;
+ sv->attribute().setColor(1,1,1);
+ }
+ else {
+ scal=fabs(scal);
+ sv->attribute().setColor(0,0,0);
+ }
+ thickness=_minThickness+scal*(_maxThickness-_minThickness);
+ if (thickness<0.0)
+ thickness=0.0;
+ sv->attribute().setThickness(thickness/2.0,thickness/2.0);
+ }
+
+ return 0;
+}
+
+//void
+//TipRemoverShader::shade(Stroke &ioStroke) const
+//{
+//
+// StrokeInternal::StrokeVertexIterator v, vend;
+// for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+// v!=vend;
+// ++v)
+// {
+// if (((*v)->curvilinearAbscissa()<_tipLength) ||
+// ((*v)->strokeLength()-(*v)->curvilinearAbscissa()<_tipLength))
+// {
+// (*v)->attribute().setThickness(0.0, 0.0);
+// (*v)->attribute().setColor(1,1,1);
+// }
+// }
+//
+//}
+
+
+
+/////////////////////////////////////////
+//
+// SPATIAL NOISE SHADER
+//
+/////////////////////////////////////////
+
+static const unsigned NB_VALUE_NOISE = 512;
+
+SpatialNoiseShader::SpatialNoiseShader (float ioamount, float ixScale, int nbOctave,
+ bool smooth, bool pureRandom)
+ : StrokeShader()
+{
+ _amount = ioamount;
+ if (ixScale==0) _xScale=0;
+ else _xScale=1.0/ixScale/real(NB_VALUE_NOISE);
+ _nbOctave=nbOctave;
+ _smooth=smooth;
+ _pureRandom=pureRandom;
+}
+int
+SpatialNoiseShader::shade(Stroke &ioStroke) const
+{
+ Interface0DIterator v, v2;
+ v=ioStroke.verticesBegin();
+ Vec2r p(v->getProjectedX(), v->getProjectedY());
+ v2=v; ++v2;
+ Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
+ p0=p+2*(p-p0);
+ StrokeVertex* sv;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ real initU = sv->strokeLength()*real(NB_VALUE_NOISE);
+ if (_pureRandom) initU+=RandGen::drand48()*real(NB_VALUE_NOISE);
+
+ Functions0D::VertexOrientation2DF0D fun;
+ while (!v.isEnd())
+ {
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ Vec2r p(sv->getPoint());
+ if (fun(v) < 0)
+ return -1;
+ Vec2r vertexOri(fun.result);
+ Vec2r ori2d(vertexOri[0], vertexOri[1]);
+ ori2d = Vec2r(p-p0);
+ ori2d.normalizeSafe();
+
+ PseudoNoise mynoise;
+ real bruit;
+
+ if (_smooth)
+ bruit=mynoise.turbulenceSmooth(_xScale*sv->curvilinearAbscissa()+initU,
+ _nbOctave);
+ else
+ bruit=mynoise.turbulenceLinear(_xScale*sv->curvilinearAbscissa()+initU,
+ _nbOctave);
+
+ Vec2r noise(-ori2d[1]*_amount*bruit,
+ ori2d[0]*_amount*bruit);
+
+ sv->setPoint(p[0]+noise[0], p[1]+noise[1]);
+ p0=p;
+
+ ++v;
+ }
+
+ return 0;
+}
+
+
+
+/////////////////////////////////////////
+//
+// SMOOTHING SHADER
+//
+/////////////////////////////////////////
+
+
+SmoothingShader::SmoothingShader (int ionbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
+ : StrokeShader()
+{
+ _nbIterations=ionbIteration;
+ _factorCurvature=ifactorCurvature;
+ _factorCurvatureDifference=iFactorCurvatureDifference;
+ _anisoNormal=iAnisoNormal;
+ _anisoCurvature=iAnisoCurvature;
+ _carricatureFactor=iCarricatureFactor;
+ _factorPoint=iFactorPoint;
+ _anisoPoint=iAnisoPoint;
+}
+
+
+
+int
+SmoothingShader::shade(Stroke &ioStroke) const
+{
+ //cerr<<" Smoothing a stroke "<<endl;
+
+ Smoother smoother(ioStroke);
+ smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference,
+ _anisoPoint, _anisoNormal, _anisoCurvature, _carricatureFactor);
+ return 0;
+}
+
+// SMOOTHER
+////////////////////////////
+
+Smoother::Smoother(Stroke &ioStroke)
+{
+ _stroke=&ioStroke;
+
+ _nbVertices=ioStroke.vertices_size();
+ _vertex=new Vec2r[_nbVertices];
+ _curvature=new real[_nbVertices];
+ _normal=new Vec2r[_nbVertices];
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd();
+ v != vend;
+ ++v)
+ {
+ _vertex[i]=(v)->getPoint();
+ i++;
+ }
+ Vec2r vec_tmp(_vertex[0]-_vertex[_nbVertices-1]);
+ _isClosedCurve = (vec_tmp.norm() < M_EPSILON);
+
+ _safeTest=(_nbVertices>4);
+}
+
+void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
+{
+ _factorCurvature=ifactorCurvature;
+ _factorCurvatureDifference=iFactorCurvatureDifference;
+ _anisoNormal=iAnisoNormal;
+ _anisoCurvature=iAnisoCurvature;
+ _carricatureFactor=iCarricatureFactor;
+ _factorPoint=iFactorPoint;
+ _anisoPoint=iAnisoPoint;
+
+ for (int i=0; i<nbIteration; i++)
+ iteration ();
+ copyVertices();
+}
+
+real edgeStopping (real x, real sigma)
+{
+ if (sigma==0.0) return 1.0;
+ return exp(-x*x/(sigma*sigma));
+}
+
+void
+Smoother::iteration ()
+{
+ computeCurvature();
+ for (int i=1; i<_nbVertices-1; i++)
+ {
+ real motionNormal=_factorCurvature*_curvature[i]*
+ edgeStopping(_curvature[i], _anisoNormal);
+
+ real diffC1=_curvature[i]-_curvature[i-1];
+ real diffC2=_curvature[i]-_curvature[i+1];
+ real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 +
+ edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference;
+ motionCurvature*=_factorCurvatureDifference;
+ //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2);
+ if (_safeTest)
+ _vertex[i]=Vec2r(_vertex[i]+(motionNormal+motionCurvature)*_normal[i]);
+ Vec2r v1(_vertex[i-1]-_vertex[i]);
+ Vec2r v2(_vertex[i+1]-_vertex[i]);
+ real d1 = v1.norm();
+ real d2 = v2.norm();
+ _vertex[i]=Vec2r(_vertex[i]+
+ _factorPoint*edgeStopping(d2, _anisoPoint)*(_vertex[i-1]-_vertex[i]) +
+ _factorPoint*edgeStopping(d1, _anisoPoint)*(_vertex[i+1]-_vertex[i]) );
+ }
+
+ if (_isClosedCurve)
+ {
+ real motionNormal=_factorCurvature*_curvature[0]*
+ edgeStopping(_curvature[0], _anisoNormal);
+
+ real diffC1=_curvature[0]-_curvature[_nbVertices-2];
+ real diffC2=_curvature[0]-_curvature[1];
+ real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 +
+ edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference;
+ motionCurvature*=_factorCurvatureDifference;
+ //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2);
+ _vertex[0]=Vec2r(_vertex[0]+(motionNormal+motionCurvature)*_normal[0]);
+ _vertex[_nbVertices-1]=_vertex[0];
+ }
+}
+
+
+void
+Smoother::computeCurvature ()
+{
+ int i;
+ Vec2r BA, BC, normalCurvature;
+ for (i = 1; i < _nbVertices - 1; i++)
+ {
+ BA=_vertex[i-1]-_vertex[i];
+ BC=_vertex[i+1]-_vertex[i];
+ real lba=BA.norm(), lbc=BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ normalCurvature = BA + BC;
+
+ _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]);
+ _normal[i].normalizeSafe();
+
+ _curvature[i] = normalCurvature * _normal[i];
+ if (lba+lbc > M_EPSILON)
+ _curvature[i]/=(0.5*lba+lbc);
+ }
+ _curvature[0]=_curvature[1];
+ _curvature[_nbVertices-1]=_curvature[_nbVertices-2];
+ Vec2r di(_vertex[1]-_vertex[0]);
+ _normal[0] = Vec2r(-di[1], di[0]);
+ _normal[0].normalizeSafe();
+ di=_vertex[_nbVertices-1]-_vertex[_nbVertices-2];
+ _normal[_nbVertices-1]=Vec2r(-di[1], di[0]);
+ _normal[_nbVertices-1].normalizeSafe();
+
+ if (_isClosedCurve)
+ {
+ BA=_vertex[_nbVertices-2]-_vertex[0];
+ BC=_vertex[1]-_vertex[0];
+ real lba=BA.norm(), lbc=BC.norm();
+ BA.normalizeSafe();
+ BC.normalizeSafe();
+ normalCurvature = BA + BC;
+
+ _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]);
+ _normal[i].normalizeSafe();
+
+ _curvature[i] = normalCurvature * _normal[i];
+ if (lba+lbc > M_EPSILON)
+ _curvature[i]/=(0.5*lba+lbc);
+
+ _normal[_nbVertices-1]=_normal[0];
+ _curvature[_nbVertices-1]=_curvature[0];
+ }
+}
+
+void
+Smoother::copyVertices ()
+{
+ int i=0;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for(v=_stroke->strokeVerticesBegin(), vend=_stroke->strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ const Vec2r p0((v)->getPoint());
+ const Vec2r p1(_vertex[i]);
+ Vec2r p(p0 + _carricatureFactor * (p1 - p0));
+
+ (v)->setPoint(p[0], p[1]);
+ i++;
+ }
+
+}
+
+
+/////////////////////////////////////////
+//
+// OMISSION SHADER
+//
+/////////////////////////////////////////
+
+OmissionShader::OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat)
+{
+ _sizeWindow=sizeWindow;
+ _thresholdVariation=thrVari;
+ _thresholdFlat=thrFlat;
+ _lengthFlat=lFlat;
+}
+
+int
+OmissionShader::shade(Stroke &ioStroke) const
+{
+ Omitter omi(ioStroke);
+ omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat);
+
+ return 0;
+}
+
+
+// OMITTER
+///////////////////////////
+
+Omitter::Omitter (Stroke &ioStroke)
+ :Smoother (ioStroke)
+{
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ _u[i]=(v)->curvilinearAbscissa();
+ i++;
+ }
+
+}
+
+void
+Omitter::omit (real sizeWindow, real thrVari, real thrFlat, real lFlat)
+{
+ _sizeWindow=sizeWindow;
+ _thresholdVariation=thrVari;
+ _thresholdFlat=thrFlat;
+ _lengthFlat=lFlat;
+
+ for (int i=1; i<_nbVertices-1; i++)
+ {
+ if (_u[i]<_lengthFlat) continue;
+ // is the previous segment flat?
+ int j=i-1;
+ while ((j>=0) && (_u[i]-_u[j]<_lengthFlat))
+ {
+ if ((_normal[j] * _normal[i]) < _thresholdFlat)
+ ; // FIXME
+ j--;
+ }
+
+ }
+}
diff --git a/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
new file mode 100755
index 00000000000..f2e56222cc0
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.h
@@ -0,0 +1,222 @@
+//
+// Filename : AdvancedStrokeShaders.h
+// Author : Fredo Durand
+// Purpose : Fredo's stroke shaders
+// Date of creation : 17/12/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 ADVANCEDSTROKESHADERS_H
+# define ADVANCEDSTROKESHADERS_H
+
+# include "BasicStrokeShaders.h"
+
+/*! [ Thickness Shader ].
+ * Assigns thicknesses to the stroke vertices
+ * so that the stroke looks like made with a calligraphic tool.
+ * i.e. The stroke will be the thickest in a main direction,
+ * the thinest in the direction perpendicular to this one,
+ * and an interpolation inbetween.
+ */
+class LIB_STROKE_EXPORT CalligraphicShader : public StrokeShader
+{
+
+public:
+ /*! Builds the shader.
+ * \param iMinThickness
+ * The minimum thickness in the direction perpandicular
+ * to the main direction.
+ * \param iMaxThickness
+ * The maximum thickness in the main direction.
+ * \param iOrientation
+ * The 2D vector giving the main direction.
+ * \param clamp
+ * Tells ???
+ */
+ CalligraphicShader (real iMinThickness, real iMaxThickness,
+ const Vec2f &iOrientation, bool clamp);
+ /*! Destructor. */
+ virtual ~CalligraphicShader () {}
+ /*! The shading method */
+ virtual int shade(Stroke &ioStroke) const;
+protected:
+ real _maxThickness;
+ real _minThickness;
+ Vec2f _orientation;
+ bool _clamp;
+};
+
+/*! [ Geometry Shader ].
+ * Spatial Noise stroke shader.
+ * Moves the vertices to make the stroke more noisy.
+ * @see \htmlonly <a href=noise/noise.html>noise/noise.html</a> \endhtmlonly
+ */
+class LIB_STROKE_EXPORT SpatialNoiseShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iAmount
+ * The amplitude of the noise.
+ * \param ixScale
+ * The noise frequency
+ * \param nbOctave
+ * The number of octaves
+ * \param smooth
+ * If you want the noise to be smooth
+ * \param pureRandom
+ * If you don't want any coherence
+ */
+ SpatialNoiseShader (float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom);
+ /*! Destructor. */
+ virtual ~SpatialNoiseShader () {}
+ /*! The shading method. */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+
+ float _amount;
+ float _xScale;
+ int _nbOctave;
+ bool _smooth;
+ bool _pureRandom;
+};
+
+/*! [ Geometry Shader ].
+ * Smoothes the stroke.
+ * (Moves the vertices to make the stroke smoother).
+ * Uses curvature flow to converge towards a curve of constant
+ * curvature. The diffusion method we use is anisotropic
+ * to prevent the diffusion accross corners.
+ * @see \htmlonly <a href=/smoothing/smoothing.html>smoothing/smoothing.html</a> endhtmlonly
+ */
+class LIB_STROKE_EXPORT SmoothingShader : public StrokeShader
+{
+public:
+ /*! Builds the shader.
+ * \param iNbIteration
+ * The number of iterations. (400)
+ * \param iFactorPoint
+ * 0
+ * \param ifactorCurvature
+ * 0
+ * \param iFactorCurvatureDifference
+ * 0.2
+ * \param iAnisoPoint
+ * 0
+ * \param iAnisNormal
+ * 0
+ * \param iAnisoCurvature
+ * 0
+ * \param icarricatureFactor
+ * 1
+ */
+ SmoothingShader (int iNbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor);
+ /*! Destructor. */
+ virtual ~SmoothingShader () {}
+
+ /*! The shading method. */
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+
+ int _nbIterations;
+ real _factorPoint;
+ real _factorCurvature;
+ real _factorCurvatureDifference;
+ real _anisoPoint;
+ real _anisoNormal;
+ real _anisoCurvature;
+ real _carricatureFactor;
+};
+
+class LIB_STROKE_EXPORT Smoother
+{
+public:
+ Smoother (Stroke &ioStroke);
+
+ virtual ~Smoother () {}
+
+ void smooth (int nbIterations, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
+ real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor);
+ void computeCurvature ();
+
+protected:
+ real _factorPoint;
+ real _factorCurvature;
+ real _factorCurvatureDifference;
+ real _anisoPoint;
+ real _anisoNormal;
+ real _anisoCurvature;
+ real _carricatureFactor;
+
+ void iteration();
+ void copyVertices ();
+
+ Stroke *_stroke;
+ int _nbVertices;
+ Vec2r *_vertex;
+ Vec2r *_normal;
+ real *_curvature;
+ bool *_isFixedVertex;
+
+ bool _isClosedCurve;
+ bool _safeTest;
+};
+
+class LIB_STROKE_EXPORT Omitter : public Smoother
+{
+public:
+ Omitter (Stroke &ioStroke);
+ virtual ~Omitter () {}
+
+ void omit (real sizeWindow, real thrVari, real thrFlat, real lFlat);
+protected:
+ real *_u;
+
+ real _sizeWindow;
+ real _thresholdVariation;
+ real _thresholdFlat;
+ real _lengthFlat;
+};
+
+/*! Omission shader
+ */
+class LIB_STROKE_EXPORT OmissionShader : public StrokeShader
+{
+public:
+ OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat);
+ virtual ~OmissionShader () {}
+
+ virtual int shade(Stroke &ioStroke) const;
+
+protected:
+
+ real _sizeWindow;
+ real _thresholdVariation;
+ real _thresholdFlat;
+ real _lengthFlat;
+};
+
+#endif // ADVANCEDSTROKESHADERS_H
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
new file mode 100755
index 00000000000..bc9edcef057
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
@@ -0,0 +1,1160 @@
+
+//
+// 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 "StrokeRenderer.h"
+#include <fstream>
+#include "BasicStrokeShaders.h"
+#include "../system/PseudoNoise.h"
+#include "../system/RandGen.h"
+#include "../view_map/Functions0D.h"
+#include "../view_map/Functions1D.h"
+#include "AdvancedFunctions0D.h"
+#include "AdvancedFunctions1D.h"
+#include "StrokeIterators.h"
+#include "../system/StringUtils.h"
+#include "StrokeIO.h"
+
+//soc #include <qimage.h>
+//soc #include <QString>
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+}
+
+// Internal function
+
+// soc
+// void convert(const QImage& iImage, float **oArray, unsigned &oSize) {
+// oSize = iImage.width();
+// *oArray = new float[oSize];
+// for(unsigned i=0; i<oSize; ++i) {
+// QRgb rgb = iImage.pixel(i,0);
+// (*oArray)[i] = ((float)qBlue(rgb))/255.f;
+// }
+// }
+void convert(ImBuf *imBuf, float **oArray, unsigned &oSize) {
+ oSize = imBuf->x;
+ *oArray = new float[oSize];
+
+ char *pix;
+ for(unsigned i=0; i < oSize; ++i) {
+ pix = (char*) imBuf->rect + i*4;
+ (*oArray)[i] = ((float) pix[2] )/255.f;
+ }
+}
+
+namespace StrokeShaders {
+
+ //
+ // Thickness modifiers
+ //
+ //////////////////////////////////////////////////////////
+
+ int ConstantThicknessShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ int size = stroke.strokeVerticesSize();
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if((1 == i) || (size-2 == i))
+ v->attribute().setThickness(_thickness/4.0,_thickness/4.0);
+ if((0 == i) || (size-1 == i))
+ v->attribute().setThickness(0,0);
+
+ v->attribute().setThickness(_thickness/2.0, _thickness/2.0);
+ }
+ return 0;
+ }
+
+ int ConstantExternThicknessShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ int size = stroke.strokeVerticesSize();
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if((1 == i) || (size-2 == i))
+ v->attribute().setThickness(_thickness/2.0,0);
+ if((0 == i) || (size-1 == i))
+ v->attribute().setThickness(0,0);
+
+ v->attribute().setThickness(_thickness, 0);
+ }
+ return 0;
+ }
+
+ int IncreasingThicknessShader::shade(Stroke& stroke) const
+ {
+
+ int n=stroke.strokeVerticesSize()-1;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+
+ ++v)
+ {
+ float t;
+ if(i < (float)n/2.f)
+ t = (1.0-(float)i/(float)n)*_ThicknessMin + (float)i/(float)n*_ThicknessMax;
+ else
+ t = (1.0-(float)i/(float)n)*_ThicknessMax + (float)i/(float)n*_ThicknessMin;
+ v->attribute().setThickness(t/2.0, t/2.0);
+ ++i;
+ }
+ return 0;
+ }
+
+ int ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const
+ {
+ float slength = stroke.getLength2D();
+ float maxT = min(_ratio*slength,_ThicknessMax);
+ int n=stroke.strokeVerticesSize()-1;
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+
+ ++v)
+ {
+ float t;
+ if(i < (float)n/2.f)
+ t = (1.0-(float)i/(float)n)*_ThicknessMin + (float)i/(float)n*maxT;
+ else
+ t = (1.0-(float)i/(float)n)*maxT + (float)i/(float)n*_ThicknessMin;
+ v->attribute().setThickness(t/2.0, t/2.0);
+ if(i == n-1)
+ v->attribute().setThickness(_ThicknessMin/2.0, _ThicknessMin/2.0);
+ ++i;
+ }
+ return 0;
+ }
+
+
+ int LengthDependingThicknessShader::shade(Stroke& stroke) const
+ {
+ float step = (_maxThickness-_minThickness)/3.f;
+ float l = stroke.getLength2D();
+ float thickness = 0.0;
+ if(l>300.f)
+ thickness = _minThickness+3.f*step;
+ else if((l< 300.f) && (l>100.f))
+ thickness = _minThickness+2.f*step;
+ else if((l<100.f) && (l>50.f))
+ thickness = _minThickness+1.f*step;
+ else if(l< 50.f)
+ thickness = _minThickness;
+
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int i=0;
+ int size = stroke.strokeVerticesSize();
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if((1 == i) || (size-2 == i))
+ v->attribute().setThickness(thickness/4.0,thickness/4.0);
+ if((0 == i) || (size-1 == i))
+ v->attribute().setThickness(0,0);
+
+ v->attribute().setThickness(thickness/2.0, thickness/2.0);
+ }
+ return 0;
+ }
+
+
+ ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name,
+ float iMinThickness,
+ float iMaxThickness,
+ bool stretch)
+ : StrokeShader() {
+ _stretch = stretch;
+ _minThickness = iMinThickness;
+ _maxThickness = iMaxThickness;
+ ImBuf *image = 0; //soc
+ vector<string> pathnames;
+ StringUtils::getPathName(TextureManager::Options::getPatternsPath(),
+ pattern_name,
+ pathnames);
+ for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+ ifstream ifs(j->c_str());
+ if (ifs.is_open()) {
+ //soc image.load(j->c_str());
+ image = IMB_loadiffname(j->c_str(), 0);
+ break;
+ }
+ }
+ if (image == 0) //soc
+ cerr << "Error: cannot find pattern \"" << pattern_name
+ << "\" - check the path in the Options" << endl;
+ else
+ convert(image, &_aThickness, _size);
+ }
+
+ int ThicknessVariationPatternShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ float *array = 0;
+ int size;
+ array = _aThickness;
+ size = _size;
+ // }
+ int vert_size = stroke.strokeVerticesSize();
+ int sig = 0;
+ unsigned index;
+ const float* originalThickness;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ originalThickness = v->attribute().getThickness();
+ if (_stretch) {
+ float tmp = v->u()*(_size-1);
+ index = (unsigned)floor(tmp);
+ if((tmp-index) > (index+1-tmp))
+ ++index;
+ }
+ else
+ index = (unsigned)floor(v->curvilinearAbscissa());
+ index %= _size;
+ float thicknessR = array[index]*originalThickness[0];
+ float thicknessL = array[index]*originalThickness[1];
+ if(thicknessR+thicknessL < _minThickness)
+ {
+ thicknessL = _minThickness/2.f;
+ thicknessR = _minThickness/2.f;
+ }
+ if(thicknessR+thicknessL > _maxThickness)
+ {
+ thicknessL = _maxThickness/2.f;
+ thicknessR = _maxThickness/2.f;
+ }
+ if((sig==0) || (sig==vert_size-1))
+ v->attribute().setThickness(1, 1);
+ else
+ v->attribute().setThickness(thicknessR, thicknessL);
+ ++sig;
+ }
+ return 0;
+ }
+
+
+ static const unsigned NB_VALUE_NOISE = 512;
+ ThicknessNoiseShader::ThicknessNoiseShader()
+ :StrokeShader()
+ {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;}
+
+ ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod)
+ :StrokeShader()
+ {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;}
+
+
+ int ThicknessNoiseShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ real initU1=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE);
+ real initU2=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE);
+
+ real bruit, bruit2;
+ PseudoNoise mynoise, mynoise2;
+ for(;
+ v!=vend;
+ ++v)
+ {
+
+ bruit=mynoise.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU1,
+ 2); //2 : nbOctaves
+ bruit2=mynoise2.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU2,
+ 2); //2 : nbOctaves
+ const float *originalThickness = v->attribute().getThickness();
+ float r = bruit*_amplitude+originalThickness[0];
+ float l = bruit2*_amplitude+originalThickness[1];
+ v->attribute().setThickness(r,l);
+ }
+
+ return 0;
+ }
+
+ //
+ // Color shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int ConstantColorShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ v->attribute().setColor(_color[0], _color[1], _color[2]);
+ v->attribute().setAlpha(_color[3]);
+ }
+ return 0;
+ }
+
+ int IncreasingColorShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ int n=stroke.strokeVerticesSize()-1;
+ int yo=0;
+ float newcolor[4];
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+
+ ++v)
+ {
+ for(int i=0; i<4; ++i)
+ {
+ newcolor[i] = (1.0-(float)yo/(float)n)*_colorMin[i] + (float)yo/(float)n*_colorMax[i];
+ }
+ v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]);
+ v->attribute().setAlpha(newcolor[3]);
+ ++yo;
+ }
+ return 0;
+ }
+
+ ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name,
+ bool stretch)
+ : StrokeShader() {
+ _stretch = stretch;
+ ImBuf *image = 0; //soc
+ vector<string> pathnames;
+ StringUtils::getPathName(TextureManager::Options::getPatternsPath(),
+ pattern_name,
+ pathnames);
+ for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); j++) {
+ ifstream ifs(j->c_str());
+ if (ifs.is_open()) {
+ image = IMB_loadiffname(j->c_str(), 0); //soc
+ break;
+ }
+ }
+ if (image == 0) //soc
+ cerr << "Error: cannot find pattern \"" << pattern_name
+ << "\" - check the path in the Options" << endl;
+ else
+ convert(image, &_aVariation, _size);
+ }
+
+ int ColorVariationPatternShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v, vend;
+ unsigned index;
+ for(v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ v!=vend;
+ ++v)
+ {
+ const float *originalColor = v->attribute().getColor();
+ if (_stretch) {
+ float tmp = v->u()*(_size-1);
+ index = (unsigned)floor(tmp);
+ if((tmp-index) > (index+1-tmp))
+ ++index;
+ }
+ else
+ index = (unsigned)floor(v->curvilinearAbscissa());
+ index %= _size;
+ float r = _aVariation[index]*originalColor[0];
+ float g = _aVariation[index]*originalColor[1];
+ float b = _aVariation[index]*originalColor[2];
+ v->attribute().setColor(r,g,b);
+ }
+ return 0;
+ }
+
+ int MaterialColorShader::shade(Stroke& stroke) const
+ {
+ Interface0DIterator v, vend;
+ Functions0D::MaterialF0D fun;
+ StrokeVertex *sv;
+ for(v=stroke.verticesBegin(), vend=stroke.verticesEnd();
+ v!=vend;
+ ++v)
+ {
+ if (fun(v) < 0)
+ return -1;
+ const float *diffuse = fun.result.diffuse();
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ sv->attribute().setColor(diffuse[0]*_coefficient, diffuse[1]*_coefficient, diffuse[2]*_coefficient);
+ sv->attribute().setAlpha(diffuse[3]);
+ }
+ return 0;
+ }
+
+
+ int CalligraphicColorShader::shade(Stroke& stroke) const
+ {
+ Interface0DIterator v;
+ Functions0D::VertexOrientation2DF0D fun;
+ StrokeVertex* sv;
+ for(v=stroke.verticesBegin();
+ !v.isEnd();
+ ++v)
+ {
+ if (fun(v) < 0)
+ return -1;
+ Vec2f vertexOri(fun.result);
+ Vec2d ori2d(-vertexOri[1], vertexOri[0]);
+ ori2d.normalizeSafe();
+ real scal = ori2d * _orientation;
+ sv = dynamic_cast<StrokeVertex*>(&(*v));
+ if ((scal<0))
+ sv->attribute().setColor(0,0,0);
+ else
+ sv->attribute().setColor(1,1,1);
+ }
+ return 0;
+ }
+
+
+ ColorNoiseShader::ColorNoiseShader()
+ :StrokeShader()
+ {_amplitude=1.f;_scale=1.f/2.f/(float)NB_VALUE_NOISE;}
+
+ ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod)
+ :StrokeShader()
+ {_amplitude=iAmplitude;_scale=1.f/iPeriod/(float)NB_VALUE_NOISE;}
+
+
+ int ColorNoiseShader::shade(Stroke& stroke) const
+ {
+ StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ real initU=v->strokeLength()*real(NB_VALUE_NOISE)+RandGen::drand48()*real(NB_VALUE_NOISE);
+
+ real bruit;
+ PseudoNoise mynoise;
+ for(;
+ v!=vend;
+ ++v)
+ {
+
+ bruit=mynoise.turbulenceSmooth(_scale*v->curvilinearAbscissa()+initU,
+ 2); //2 : nbOctaves
+ const float *originalColor = v->attribute().getColor();
+ float r = bruit*_amplitude+originalColor[0];
+ float g = bruit*_amplitude+originalColor[1];
+ float b = bruit*_amplitude+originalColor[2];
+ v->attribute().setColor(r,g,b);
+ }
+
+ return 0;
+ }
+
+
+ //
+ // Texture Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int TextureAssignerShader::shade(Stroke& stroke) const
+ {
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+ // getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
+
+ TextureManager * instance = TextureManager::getInstance();
+ if(!instance)
+ return 0;
+ string pathname;
+ Stroke::MediumType mediumType;
+ bool hasTips = false;
+ switch(_textureId)
+ {
+ case 0:
+ //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp";
+ pathname = "/charcoalAlpha.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = false;
+ break;
+ case 1:
+ pathname = "/washbrushAlpha.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 2:
+ pathname = "/oil.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 3:
+ pathname = "/oilnoblend.bmp";
+ mediumType = Stroke::HUMID_MEDIUM;
+ hasTips = true;
+ break;
+ case 4:
+ pathname = "/charcoalAlpha.bmp";
+ mediumType = Stroke::DRY_MEDIUM;
+ hasTips = false;
+ break;
+ case 5:
+ mediumType = Stroke::DRY_MEDIUM;
+ hasTips = true;
+ break;
+ case 6:
+ pathname = "/opaqueDryBrushAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = true;
+ break;
+ case 7:
+ pathname = "/opaqueBrushAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = true;
+ break;
+ default:
+ pathname = "/smoothAlpha.bmp";
+ mediumType = Stroke::OPAQUE_MEDIUM;
+ hasTips = false;
+ break;
+ }
+ unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType);
+ stroke.setMediumType(mediumType);
+ stroke.setTips(hasTips);
+ stroke.setTextureId(texId);
+ return 0;
+ }
+
+ // FIXME
+ int StrokeTextureShader::shade(Stroke& stroke) const
+ {
+ TextureManager * instance = TextureManager::getInstance();
+ if(!instance)
+ return 0;
+ string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath;
+ unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType);
+ stroke.setMediumType(_mediumType);
+ stroke.setTips(_tips);
+ stroke.setTextureId(texId);
+ return 0;
+ }
+
+ //
+ // Geometry Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+
+ int BackboneStretcherShader::shade(Stroke& stroke) const
+ {
+ float l=stroke.getLength2D();
+ if(l <= 50)
+ return 0;
+
+ StrokeInternal::StrokeVertexIterator v0=stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator v1=v0;++v1;
+ StrokeInternal::StrokeVertexIterator vn=stroke.strokeVerticesEnd();--vn;
+ StrokeInternal::StrokeVertexIterator vn_1=vn;--vn_1;
+
+
+ Vec2d first((v0)->x(), (v0)->y());
+ Vec2d last((vn)->x(), (vn)->y());
+
+ Vec2d d1(first-Vec2d((v1)->x(), (v1)->y()));
+ d1.normalize();
+ Vec2d dn(last-Vec2d((vn_1)->x(), (vn_1)->y()));
+ dn.normalize();
+
+ Vec2d newFirst(first+_amount*d1);
+ (v0)->setPoint(newFirst[0], newFirst[1]);
+ Vec2d newLast(last+_amount*dn);
+ (vn)->setPoint(newLast[0], newLast[1]);
+ return 0;
+ }
+
+ int SamplingShader::shade(Stroke& stroke) const
+ {
+ stroke.Resample(_sampling);
+ return 0;
+ }
+
+ int ExternalContourStretcherShader::shade(Stroke& stroke) const
+ {
+ //float l=stroke.getLength2D();
+ Interface0DIterator it=stroke.verticesBegin();
+ Functions0D::Normal2DF0D fun;
+ StrokeVertex* sv;
+ while (!it.isEnd())
+ {
+ if (fun(it) < 0)
+ return -1;
+ Vec2f n(fun.result);
+ sv = dynamic_cast<StrokeVertex*>(&(*it));
+ Vec2d newPoint(sv->x()+_amount*n.x(), sv->y()+_amount*n.y());
+ sv->setPoint(newPoint[0], newPoint[1]);
+ ++it;
+ }
+ return 0;
+ }
+
+ int BSplineShader::shade(Stroke& stroke) const
+ {
+ if(stroke.strokeVerticesSize() < 4)
+ return 0;
+
+ // Find the new vertices
+ vector<Vec2d> newVertices;
+ double t=0.f;
+ float _sampling = 5.f;
+
+ StrokeInternal::StrokeVertexIterator p0,p1,p2,p3, end;
+ p0 = stroke.strokeVerticesBegin();
+ p1 = p0;
+ p2 = p1;
+ p3 = p2;
+ end = stroke.strokeVerticesEnd();
+ double a[4],b[4];
+ int n=0;
+ while(p1 != end)
+ {
+ // if(p1 == end)
+ // p1 = p0;
+ if(p2 == end)
+ p2 = p1;
+ if(p3 == end)
+ p3 = p2;
+ // compute new matrix
+ a[0] = (-(p0)->x()+3*(p1)->x()-3*(p2)->x()+(p3)->x())/6.0;
+ a[1] = (3*(p0)->x()-6*(p1)->x()+3*(p2)->x())/6.0;
+ a[2] = (-3*(p0)->x()+3*(p2)->x())/6.0;
+ a[3] = ((p0)->x()+4*(p1)->x()+(p2)->x())/6.0;
+
+ b[0] = (-(p0)->y()+3*(p1)->y()-3*(p2)->y()+(p3)->y())/6.0;
+ b[1] = (3*(p0)->y()-6*(p1)->y()+3*(p2)->y())/6.0;
+ b[2] = (-3*(p0)->y()+3*(p2)->y())/6.0;
+ b[3] = ((p0)->y()+4*(p1)->y()+(p2)->y())/6.0;
+
+
+ // draw the spline depending on resolution:
+ Vec2d p1p2((p2)->x()-(p1)->x(), (p2)->y()-(p1)->y());
+ double norm = p1p2.norm();
+ //t = _sampling/norm;
+ t=0;
+ while(t<1)
+ {
+ newVertices.push_back(Vec2d((a[3] + t*(a[2] + t*(a[1] + t*a[0]))),
+ (b[3] + t*(b[2] + t*(b[1] + t*b[0])))));
+ t = t + _sampling/norm;
+ }
+ if(n > 2)
+ {
+ ++p0;
+ ++p1;
+ ++p2;
+ ++p3;
+ }
+ else
+ {
+ if(n==0)
+ ++p3;
+ if(n==1)
+ {++p2;++p3;}
+ if(n==2)
+ {++p1;++p2;++p3;}
+ ++n;
+ }
+ }
+ //last point:
+ newVertices.push_back(Vec2d((p0)->x(), (p0)->y()));
+
+ int originalSize = newVertices.size();
+ _sampling = stroke.ComputeSampling(originalSize);
+
+ // Resample and set x,y coordinates
+ stroke.Resample(_sampling);
+ int newsize = stroke.strokeVerticesSize();
+
+ int nExtraVertex=0;
+ if(newsize < originalSize)
+ cerr << "Warning: unsufficient resampling" << endl;
+ else
+ {
+ nExtraVertex = newsize - originalSize;
+ }
+
+ // assigns the new coordinates:
+ vector<Vec2d>::iterator p,pend;
+ p=newVertices.begin();pend=newVertices.end();
+ vector<Vec2d>::iterator last = p;
+ n=0;
+ StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd();
+ it=stroke.strokeVerticesBegin();
+ for(;
+ ((it!=itend) && (p!=pend));
+ ++it)
+ {
+ it->setX(p->x());
+ it->setY(p->y());
+ last = p;
+ ++p;
+ ++n;
+ }
+ // nExtraVertex should stay unassigned
+ for(int i=0; i< nExtraVertex; ++i)
+ {
+ it->setX(last->x());
+ it->setY(last->y());
+ if(it.isEnd())
+ cerr << "Warning: Problem encountered while creating B-spline" << endl;
+ ++it;
+ ++n;
+ }
+ return 0;
+ }
+
+ //!! Bezier curve stroke shader
+ int BezierCurveShader::shade(Stroke& stroke) const
+ {
+ if(stroke.strokeVerticesSize() < 4)
+ return 0;
+
+ // Build the Bezier curve from this set of data points:
+ vector<Vec2d> data;
+ StrokeInternal::StrokeVertexIterator v=stroke.strokeVerticesBegin(), vend=stroke.strokeVerticesEnd();
+ data.push_back(Vec2d(v->x(), v->y()));//first one
+ StrokeInternal::StrokeVertexIterator previous = v;++v;
+ for(;
+ v!=vend;
+ ++v)
+ {
+ if(!((fabs(v->x() -(previous)->x())<M_EPSILON) && ((fabs(v->y() - (previous)->y())<M_EPSILON))))
+ data.push_back(Vec2d(v->x(), v->y()));
+ previous = v;
+ }
+
+ // Vec2d tmp;bool equal=false;
+ // if(data.front() == data.back())
+ // {
+ // tmp = data.back();
+ // data.pop_back();
+ // equal=true;
+ // }
+ // here we build the bezier curve
+ BezierCurve bcurve(data, _error);
+
+ // bad performances are here !!! // FIXME
+ vector<Vec2d> CurveVertices;
+ vector<BezierCurveSegment*>& bsegments = bcurve.segments();
+ vector<BezierCurveSegment*>::iterator s=bsegments.begin(),send=bsegments.end();
+ vector<Vec2d>& segmentsVertices = (*s)->vertices();
+ vector<Vec2d>::iterator p,pend;
+ // first point
+ CurveVertices.push_back(segmentsVertices[0]);
+ for(;
+ s!=send;
+ ++s)
+ {
+ segmentsVertices = (*s)->vertices();
+ p=segmentsVertices.begin(); pend=segmentsVertices.end();
+ ++p;
+ for(;
+ p!=pend;
+ ++p)
+ {
+ CurveVertices.push_back((*p));
+ }
+ }
+
+ //if(equal)
+ // if(data.back() == data.front())
+ // {
+ // vector<Vec2d>::iterator d=data.begin(), dend=data.end();
+ // cout << "ending point = starting point" << endl;
+ // cout << "---------------DATA----------" << endl;
+ // for(;
+ // d!=dend;
+ // ++d)
+ // {
+ // cout << d->x() << "-" << d->y() << endl;
+ // }
+ // cout << "--------------BEZIER RESULT----------" << endl;
+ // d=CurveVertices.begin(), dend=CurveVertices.end();
+ // for(;d!=dend;++d)
+ // {
+ // cout << d->x() << "-" << d->y() << endl;
+ // }
+ // }
+
+ // Resample the Stroke depending on the number of
+ // vertices of the bezier curve:
+ int originalSize = CurveVertices.size();
+ //float sampling = stroke.ComputeSampling(originalSize);
+ //stroke.Resample(sampling);
+ stroke.Resample(originalSize);
+ int newsize = stroke.strokeVerticesSize();
+ int nExtraVertex=0;
+ if(newsize < originalSize)
+ cerr << "Warning: unsufficient resampling" << endl;
+ else
+ {
+ //cout << "Oversampling" << endl;
+ nExtraVertex = newsize - originalSize;
+ if(nExtraVertex != 0)
+ cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl;
+ }
+
+ // assigns the new coordinates:
+ p=CurveVertices.begin();pend=CurveVertices.end();
+ vector<Vec2d>::iterator last = p;
+ int n=0;
+ StrokeInternal::StrokeVertexIterator it=stroke.strokeVerticesBegin(), itend=stroke.strokeVerticesEnd();
+ // while(p!=pend)
+ // {
+ // ++n;
+ // ++p;
+ // }
+ it=stroke.strokeVerticesBegin();
+ for(;
+ ((it!=itend) && (p!=pend));
+ ++it)
+ {
+ it->setX(p->x());
+ it->setY(p->y());
+ // double x = p->x();
+ // double y = p->y();
+ // cout << "x = " << x << "-" << "y = " << y << endl;
+ last = p;
+ ++p;
+ ++n;
+ }
+
+ // Deal with extra vertices:
+ if(nExtraVertex == 0)
+ return 0;
+
+ // nExtraVertex should stay unassigned
+ vector<StrokeAttribute> attributes;
+ vector<StrokeVertex*> verticesToRemove;
+ for(int i=0; i< nExtraVertex; ++i)
+ {
+ verticesToRemove.push_back(&(*it));
+ if(it.isEnd())
+ cout << "fucked up" << endl;
+ ++it;
+ ++n;
+ }
+ it=stroke.strokeVerticesBegin();
+ for(;
+ it!=itend;
+ ++it)
+ {
+ attributes.push_back(it->attribute());
+ }
+
+ for(vector<StrokeVertex*>::iterator vr=verticesToRemove.begin(), vrend=verticesToRemove.end();
+ vr!=vrend;
+ ++vr)
+ {
+ stroke.RemoveVertex(*vr);
+ }
+ it=stroke.strokeVerticesBegin();
+ itend=stroke.strokeVerticesEnd();
+ vector<StrokeAttribute>::iterator a=attributes.begin(), aend=attributes.end();
+ int index = 0;
+ int index1 = (int)floor((float)originalSize/2.0);
+ int index2 = index1+nExtraVertex;
+ for(;
+ (it!=itend) && (a!=aend);
+ ++it)
+ {
+ (it)->setAttribute(*a);
+ if((index <= index1)||(index>index2))
+ ++a;
+ ++index;
+ }
+ return 0;
+ }
+
+ int InflateShader::shade(Stroke& stroke) const
+ {
+ // we're computing the curvature variance of the stroke.(Combo 5)
+ // If it's too high, forget about it
+ Functions1D::Curvature2DAngleF1D fun;
+ if (fun(stroke) < 0)
+ return -1;
+ if (fun.result > _curvatureThreshold)
+ return 0;
+
+ Functions0D::VertexOrientation2DF0D ori_fun;
+ Functions0D::Curvature2DAngleF0D curv_fun;
+ Functions1D::Normal2DF1D norm_fun;
+ Interface0DIterator it=stroke.verticesBegin();
+ StrokeVertex* sv;
+ while (!it.isEnd())
+ {
+ if (ori_fun(it) < 0)
+ return -1;
+ Vec2f ntmp(ori_fun.result);
+ Vec2f n(ntmp.y(), -ntmp.x());
+ if (norm_fun(stroke) < 0)
+ return -1;
+ Vec2f strokeN(norm_fun.result);
+ if(n*strokeN < 0)
+ {
+ n[0] = -n[0];
+ n[1] = -n[1];
+ }
+ sv = dynamic_cast<StrokeVertex*>(&(*it));
+ float u=sv->u();
+ float t = 4.f*(0.25f - (u-0.5)*(u-0.5));
+ if (curv_fun(it) < 0)
+ return -1;
+ float curvature_coeff = (M_PI-curv_fun.result)/M_PI;
+ Vec2d newPoint(sv->x()+curvature_coeff*t*_amount*n.x(), sv->y()+curvature_coeff*t*_amount*n.y());
+ sv->setPoint(newPoint[0], newPoint[1]);
+ ++it;
+ }
+ return 0;
+ }
+
+ class CurvePiece
+ {
+ public:
+ StrokeInternal::StrokeVertexIterator _begin;
+ StrokeInternal::StrokeVertexIterator _last;
+ Vec2d A;
+ Vec2d B;
+ int size;
+ float _error;
+
+ CurvePiece(StrokeInternal::StrokeVertexIterator b, StrokeInternal::StrokeVertexIterator l, int iSize)
+ {
+ _begin = b;
+ _last = l;
+ A = Vec2d((_begin)->x(),(_begin)->y());
+ B = Vec2d((_last)->x(),(_last)->y());
+ size = iSize;
+ }
+
+ float error()
+ {
+ float maxE = 0.f;
+ for(StrokeInternal::StrokeVertexIterator it=_begin;
+ it!=_last;
+ ++it)
+ {
+ Vec2d P(it->x(), it->y());
+ float d = GeomUtils::distPointSegment(P,A,B);
+ if(d > maxE)
+ maxE = d;
+ }
+ _error = maxE;
+ return maxE;
+ }
+ //! Subdivides the curve into two pieces.
+ // The first piece is this same object (modified)
+ // the second piece is returned by the method
+ CurvePiece * subdivide()
+ {
+ StrokeInternal::StrokeVertexIterator it=_begin;
+ int actualSize = 1;
+ for(int i=0; i<size/2; ++i)
+ {
+ ++it;
+ ++actualSize;
+ }
+ CurvePiece * second = new CurvePiece(it, _last, size-actualSize+1);
+ size = actualSize;
+ _last = it;
+ B = Vec2d((_last)->x(), (_last)->y());
+ return second;
+ }
+ };
+
+ int PolygonalizationShader::shade(Stroke& stroke) const
+ {
+ vector<CurvePiece*> _pieces;
+ vector<CurvePiece*> _results;
+ vector<CurvePiece*>::iterator cp,cpend;
+
+ // Compute first approx:
+ StrokeInternal::StrokeVertexIterator a=stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator b=stroke.strokeVerticesEnd();--b;
+ int size = stroke.strokeVerticesSize();
+
+ CurvePiece * piece = new CurvePiece(a,b,size);
+ _pieces.push_back(piece);
+
+ while(!_pieces.empty())
+ {
+ piece = _pieces.back();_pieces.pop_back();
+ if(piece->error() > _error)
+ {
+ CurvePiece * second = piece->subdivide();
+ _pieces.push_back(second);
+ _pieces.push_back(piece);
+ }
+ else
+ {
+ _results.push_back(piece);
+ }
+ }
+
+ // actually modify the geometry for each piece:
+ for(cp=_results.begin(), cpend=_results.end();
+ cp!=cpend;
+ ++cp)
+ {
+ a = (*cp)->_begin;
+ b = (*cp)->_last;
+ Vec2d u = (*cp)->B-(*cp)->A;
+ Vec2d n(u[1], -u[0]);n.normalize();
+ //Vec2d n(0,0);
+ float offset = ((*cp)->_error);
+ StrokeInternal::StrokeVertexIterator v,vlast;
+ for(v=a;
+ v!=b;
+ ++v)
+ {
+ v->setPoint((*cp)->A.x()+v->u()*u.x()+n.x()*offset, (*cp)->A.y()+v->u()*u.y()+n.y()*offset);
+ }
+ // u.normalize();
+ // (*a)->setPoint((*a)->x()-u.x()*10, (*a)->y()-u.y()*10);
+ }
+
+ // delete stuff
+ for(cp=_results.begin(), cpend=_results.end();
+ cp!=cpend;
+ ++cp)
+ {
+ delete (*cp);
+ }
+ _results.clear();
+ return 0;
+ }
+
+ int GuidingLinesShader::shade(Stroke& stroke) const
+ {
+ Functions1D::Normal2DF1D norm_fun;
+ StrokeInternal::StrokeVertexIterator a=stroke.strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator b=stroke.strokeVerticesEnd();--b;
+ int size = stroke.strokeVerticesSize();
+ CurvePiece piece(a,b,size);
+
+ Vec2d u = piece.B-piece.A;
+ Vec2f n(u[1], -u[0]);n.normalize();
+ if (norm_fun(stroke) < 0)
+ return -1;
+ Vec2f strokeN(norm_fun.result);
+ if(n*strokeN < 0)
+ {
+ n[0] = -n[0];
+ n[1] = -n[1];
+ }
+ float offset = (piece.error())/2.f*_offset;
+ StrokeInternal::StrokeVertexIterator v=a,vend=stroke.strokeVerticesEnd();
+ for(;
+ v!=vend;
+ ++v)
+ {
+ v->setPoint(piece.A.x()+v->u()*u.x()+n.x()*offset, piece.A.y()+v->u()*u.y()+n.y()*offset);
+ }
+ return 0;
+ }
+
+ /////////////////////////////////////////
+ //
+ // Tip Remover
+ //
+ /////////////////////////////////////////
+
+
+ TipRemoverShader::TipRemoverShader(real tipLength)
+ : StrokeShader()
+ {
+ _tipLength = tipLength;
+ }
+
+ int
+ TipRemoverShader::shade(Stroke& stroke) const
+ {
+ int originalSize = stroke.strokeVerticesSize();
+
+ if(originalSize<4)
+ return 0;
+
+ StrokeInternal::StrokeVertexIterator v, vend;
+ vector<StrokeVertex*> verticesToRemove;
+ vector<StrokeAttribute> oldAttributes;
+ v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd();
+ for(;
+ v!=vend;
+ ++v)
+ {
+ if ((v->curvilinearAbscissa()<_tipLength) ||
+ (v->strokeLength()-v->curvilinearAbscissa()<_tipLength))
+ {
+ verticesToRemove.push_back(&(*v));
+ }
+ oldAttributes.push_back(v->attribute());
+ }
+
+ if(originalSize-verticesToRemove.size() < 2)
+ return 0;
+
+ vector<StrokeVertex*>::iterator sv=verticesToRemove.begin(), svend=verticesToRemove.end();
+ for(;
+ sv!=svend;
+ ++sv)
+ {
+ stroke.RemoveVertex((*sv));
+ }
+
+ // Resample so that our new stroke have the same
+ // number of vertices than before
+ stroke.Resample(originalSize);
+
+ if((int)stroke.strokeVerticesSize() != originalSize) //soc
+ cerr << "Warning: resampling problem" << endl;
+
+ // assign old attributes to new stroke vertices:
+ v=stroke.strokeVerticesBegin(); vend=stroke.strokeVerticesEnd();
+ vector<StrokeAttribute>::iterator a=oldAttributes.begin(), aend=oldAttributes.end();
+ //cout << "-----------------------------------------------" << endl;
+ for(;(v!=vend)&&(a!=aend);++v,++a)
+ {
+ v->setAttribute(*a);
+ //cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl;
+ }
+ // we're done!
+ return 0;
+ }
+
+ int streamShader::shade(Stroke& stroke) const{
+ cout << stroke << endl;
+ return 0;
+ }
+ int fstreamShader::shade(Stroke& stroke) const{
+ _stream << stroke << endl;
+ return 0;
+ }
+
+} // end of namespace StrokeShaders
+
diff --git a/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
new file mode 100755
index 00000000000..a0c0a44c9b6
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/BasicStrokeShaders.h
@@ -0,0 +1,890 @@
+//
+// Filename : BasicStrokeShaders.h
+// Author : Stephane Grabli
+// Purpose : Class gathering basic stroke shaders
+// Date of creation : 17/12/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 BASIC_STROKE_SHADERS_H
+# define BASIC_STROKE_SHADERS_H
+
+# include "Stroke.h"
+# include "../geometry/Geom.h"
+# include "../geometry/Bezier.h"
+# include "StrokeShader.h"
+# include <fstream>
+
+using namespace std;
+using namespace Geometry;
+
+namespace StrokeShaders {
+
+ //
+ // Thickness modifiers
+ //
+ //////////////////////////////////////////////////////
+ /*! [ Thickness Shader ].
+ * Assigns an absolute constant thickness to every
+ * vertices of the Stroke.
+ */
+ class LIB_STROKE_EXPORT ConstantThicknessShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader.
+ * \param thickness
+ * The thickness that must be assigned
+ * to the stroke.
+ */
+ ConstantThicknessShader(float thickness) : StrokeShader() {
+ _thickness = thickness;
+ }
+ /*! Destructor. */
+ virtual ~ConstantThicknessShader() {}
+ /*! Returns the string "ConstantThicknessShader".*/
+ virtual string getName() const {
+ return "ConstantThicknessShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+ float _thickness;
+ };
+
+ /* [ Thickness Shader ].
+ * Assigns an absolute constant external thickness to every
+ * vertices of the Stroke. The external thickness of a point
+ * is its thickness from the point to the strip border
+ * in the direction pointing outside the object the
+ * Stroke delimitates.
+ */
+ class LIB_STROKE_EXPORT ConstantExternThicknessShader : public StrokeShader
+ {
+ public:
+
+ ConstantExternThicknessShader(float thickness) : StrokeShader() {
+ _thickness = thickness;
+ }
+
+ virtual ~ConstantExternThicknessShader() {}
+
+ virtual string getName() const {
+ return "ConstantExternThicknessShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float _thickness;
+ };
+
+ /*! [ Thickness Shader ].
+ * Assigns thicknesses values such as the thickness
+ * increases from a thickness value A to a thickness value B
+ * between the first vertex to the midpoint vertex and
+ * then decreases from B to a A between this midpoint vertex
+ * and the last vertex.
+ * The thickness is linearly interpolated from A to B.
+ */
+ class LIB_STROKE_EXPORT IncreasingThicknessShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader.
+ * \param iThicknessMin
+ * The first thickness value.
+ * \param iThicknessMax
+ * The second thickness value.
+ */
+ IncreasingThicknessShader(float iThicknessMin, float iThicknessMax)
+ : StrokeShader()
+ {
+ _ThicknessMin = iThicknessMin;
+ _ThicknessMax = iThicknessMax;
+ }
+ /*! Destructor.*/
+ virtual ~IncreasingThicknessShader() {}
+
+ virtual string getName() const {
+ return "IncreasingThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float _ThicknessMin;
+ float _ThicknessMax;
+ };
+
+ /*! [ Thickness shader ].
+ * Same as previous but
+ * here we allow the user to control the ratio thickness/length so that
+ * we don't get fat short lines
+ */
+ class LIB_STROKE_EXPORT ConstrainedIncreasingThicknessShader : public StrokeShader
+ {
+ private:
+ float _ThicknessMin;
+ float _ThicknessMax;
+ float _ratio;
+ public:
+ /*! Builds the shader.
+ * \param iThicknessMin
+ * The first thickness value.
+ * \param iThicknessMax
+ * The second thickness value.
+ * \param iRatio
+ * The ration thickness/length we don't want to
+ * exceed.
+ */
+ ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio)
+ : StrokeShader()
+ {
+ _ThicknessMin = iThicknessMin;
+ _ThicknessMax = iThicknessMax;
+ _ratio = iRatio;
+ }
+ /*! Destructor.*/
+ virtual ~ConstrainedIncreasingThicknessShader() {}
+
+ virtual string getName() const {
+ return "ConstrainedIncreasingThicknessShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /* [ Thickness Shader ].
+ * Modifys the thickness in a relative way
+ * depending on its length.
+ */
+ class LIB_STROKE_EXPORT LengthDependingThicknessShader : public StrokeShader
+ {
+ private:
+ float _minThickness;
+ float _maxThickness;
+ // We divide the strokes in 4 categories:
+ // l > 300
+ // 100 < l < 300
+ // 50 < l < 100
+ // l < 50
+ public:
+ LengthDependingThicknessShader(float iMinThickness, float iMaxThickness)
+ : StrokeShader()
+ {
+ _minThickness = iMinThickness;
+ _maxThickness = iMaxThickness;
+ }
+ virtual ~LengthDependingThicknessShader() {}
+
+ virtual string getName() const {
+ return "LengthDependingThicknessShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Thickness Shader ].
+ * Applys a pattern (texture) to vary thickness.
+ * The new thicknesses are the result of the multiplication
+ * of the pattern and the original thickness
+ */
+ class LIB_STROKE_EXPORT ThicknessVariationPatternShader : public StrokeShader
+ {
+ public:
+
+ /*! Builds the shader.
+ * \param pattern_name
+ * The texture file name.
+ * \param iMinThickness
+ * The minimum thickness we don't want to exceed.
+ * \param iMaxThickness
+ * The maximum thickness we don't want to exceed.
+ * \param stretch
+ * Tells whether the pattern texture must
+ * be stretched or repeted to fit the stroke.
+ */
+ ThicknessVariationPatternShader(const string pattern_name,
+ float iMinThickness = 1.f,
+ float iMaxThickness = 5.f,
+ bool stretch = true);
+ /*! Destructor.*/
+ virtual ~ThicknessVariationPatternShader()
+ {
+ if(0 != _aThickness)
+ {
+ delete [] _aThickness;
+ _aThickness = 0;
+ }
+ }
+
+ virtual string getName() const {
+ return "ThicknessVariationPatternShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float* _aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1)
+ unsigned _size;
+ float _minThickness;
+ float _maxThickness;
+ bool _stretch;
+ };
+
+ /*! [ Thickness Shader ].
+ * Adds some noise to the stroke thickness.
+ * \see \htmlonly <a href=noise/noise.html>noise/noise.html</a>\endhtmlonly
+ */
+ class LIB_STROKE_EXPORT ThicknessNoiseShader : public StrokeShader
+ {
+ private:
+ float _amplitude;
+ float _scale;
+ public:
+ ThicknessNoiseShader();
+ /*! Builds a Thickness Noise Shader
+ * \param iAmplitude
+ * The amplitude of the noise signal
+ * \param iPeriod
+ * The period of the noise signal
+ */
+ ThicknessNoiseShader(float iAmplitude, float iPeriod);
+
+ virtual string getName() const {
+ return "ThicknessNoiseShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ //
+ // Color shaders
+ //
+ /////////////////////////////////////////////////////////
+ /*! [ Color Shader ].
+ * Assigns a constant color to every vertices of the Stroke.
+ */
+ class LIB_STROKE_EXPORT ConstantColorShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader from a user-specified color.
+ * \param iR
+ * The red component
+ * \param iG
+ * The green component
+ * \param iB
+ * The blue component
+ * \param iAlpha
+ * The alpha value
+ */
+ ConstantColorShader(float iR, float iG, float iB, float iAlpha=1.f)
+ : StrokeShader()
+ {
+ _color[0] = iR;
+ _color[1] = iG;
+ _color[2] = iB;
+ _color[3] = iAlpha;
+ }
+
+ virtual string getName() const {
+ return "ConstantColorShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float _color[4];
+ };
+
+ /*! [ Color Shader ].
+ * Assigns a varying color to the stroke.
+ * The user specifies 2 colors A and B. The stroke
+ * color will change linearly from A to B between the
+ * first and the last vertex.
+ */
+ class LIB_STROKE_EXPORT IncreasingColorShader : public StrokeShader
+ {
+ private:
+ float _colorMin[4];
+ float _colorMax[4];
+ public:
+ /*! Builds the shader from 2 user-specified colors.
+ * \param iRm
+ * The first color red component
+ * \param iGm
+ * The first color green component
+ * \param iBm
+ * The first color blue component
+ * \param iAlpham
+ * The first color alpha value
+ * \param iRM
+ * The second color red component
+ * \param iGM
+ * The second color green component
+ * \param iBM
+ * The second color blue component
+ * \param iAlphaM
+ * The second color alpha value
+ */
+ IncreasingColorShader(float iRm, float iGm, float iBm, float iAlpham,
+ float iRM, float iGM, float iBM, float iAlphaM)
+ : StrokeShader()
+ {
+ _colorMin[0] = iRm;
+ _colorMin[1] = iGm;
+ _colorMin[2] = iBm;
+ _colorMin[3] = iAlpham;
+
+ _colorMax[0] = iRM;
+ _colorMax[1] = iGM;
+ _colorMax[2] = iBM;
+ _colorMax[3] = iAlphaM;
+ }
+
+ virtual string getName() const {
+ return "IncreasingColorShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Color Shader ].
+ * Applys a pattern to vary original color.
+ * The new color is the result of the multiplication
+ * of the pattern and the original color
+ */
+ class LIB_STROKE_EXPORT ColorVariationPatternShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader from the pattern texture file name.
+ * \param pattern_name
+ * The file name of the texture file to use as pattern
+ * \param stretch
+ * Tells whether the texture must be strecthed or repeted
+ * to fit the stroke.
+ */
+ ColorVariationPatternShader(const string pattern_name, bool stretch = true);
+ /*! Destructor */
+ virtual ~ColorVariationPatternShader()
+ {
+ if(0 != _aVariation)
+ {
+ delete [] _aVariation;
+ _aVariation = 0;
+ }
+ }
+
+ virtual string getName() const {
+ return "ColorVariationPatternShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+
+ private:
+
+ float* _aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1)
+ unsigned _size;
+ bool _stretch;
+ };
+
+ /* [ Color Shader ].
+ * Assigns a color to the stroke depending
+ * on the material of the shape to which ot belongs
+ * to. (Disney shader)
+ */
+ class LIB_STROKE_EXPORT MaterialColorShader : public StrokeShader
+ {
+ private:
+ float _coefficient;
+ public:
+ MaterialColorShader(float coeff=1.f)
+ : StrokeShader()
+ {_coefficient=coeff;}
+
+ virtual string getName() const {
+ return "MaterialColorShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ class LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader
+ {
+ private:
+ int _textureId;
+ Vec2d _orientation;
+ public:
+ CalligraphicColorShader(
+ const Vec2d &iOrientation)
+ : StrokeShader()
+ {
+ _orientation=iOrientation;
+ _orientation.normalize();
+ }
+
+ virtual string getName() const {
+ return "CalligraphicColorShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+
+ };
+
+ /*! [ Color Shader ].
+ * Shader to add noise to the stroke colors.
+ */
+ class LIB_STROKE_EXPORT ColorNoiseShader : public StrokeShader
+ {
+ private:
+ float _amplitude;
+ float _scale;
+
+ public:
+ ColorNoiseShader();
+ /*! Builds a Color Noise Shader
+ * \param iAmplitude
+ * The amplitude of the noise signal
+ * \param iPeriod
+ * The period of the noise signal
+ */
+ ColorNoiseShader(float iAmplitude, float iPeriod);
+
+ virtual string getName() const {
+ return "ColorNoiseShader";
+ }
+
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ //
+ // Texture Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ /*! [ Texture Shader ].
+ * Assigns a texture to the stroke in order to simulate
+ * its marks system. This shader takes as input an integer value
+ * telling which texture and blending mode to use among a set of
+ * predefined textures.
+ * Here are the different presets:
+ * 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM
+ * 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM
+ * 2) -> /brushes/oil.bmp, HUMID_MEDIUM
+ * 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM
+ * 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM
+ * 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM
+ * 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM
+ * 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM
+ * Any other value will lead to the following preset:
+ * default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM.
+ */
+ class LIB_STROKE_EXPORT TextureAssignerShader : public StrokeShader // FIXME
+ {
+ private:
+ int _textureId;
+ public:
+ /*! Builds the shader.
+ * \param id
+ * The number of the preset to use.
+ */
+ TextureAssignerShader(int id)
+ : StrokeShader()
+ {
+ _textureId = id;
+ }
+
+ virtual string getName() const {
+ return "TextureAssignerShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+
+ };
+ /*! [ Texture Shader ].
+ * Assigns a texture and a blending mode to the stroke
+ * in order to simulate its marks system.
+ */
+ class LIB_STROKE_EXPORT StrokeTextureShader : public StrokeShader
+ {
+ private:
+ string _texturePath;
+ Stroke::MediumType _mediumType;
+ bool _tips; // 0 or 1
+
+ public:
+ /*! Builds the shader from the texture file name and the blending mode to use.
+ * \param textureFile
+ * The the texture file name.
+ * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes
+ * directory.
+ * \param mediumType
+ * The medium type and therefore, the blending mode that must
+ * be used for the rendering of this stroke.
+ * \param iTips
+ * Tells whether the texture includes tips or not.
+ * If it is the case, the texture image must respect the following
+ * format:
+ * \verbatim
+ * __________
+ * | |
+ * | A |
+ * |__________|
+ * | | |
+ * | B | C |
+ * |_____|____|
+ *
+ * \endverbatim
+ * - A : The stroke's corpus texture
+ * - B : The stroke's left extremity texture
+ * - C : The stroke's right extremity texture
+ */
+ StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM, bool iTips = false)
+ : StrokeShader()
+ {
+ _texturePath = textureFile;
+ _mediumType = mediumType;
+ _tips = iTips;
+ }
+
+ virtual string getName() const {
+ return "StrokeTextureShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+
+ };
+
+
+ //
+ // Geometry Shaders
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ /*! [ Geometry Shader ].
+ * Stretches the stroke at its two extremities and following the
+ * respective directions: v(1)v(0) and v(n-1)v(n).
+ */
+ class LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader
+ {
+ private:
+ float _amount;
+ public:
+ /*! Builds the shader.
+ * \param iAmount
+ * The stretching amount value.
+ */
+ BackboneStretcherShader(float iAmount=2.f)
+ : StrokeShader()
+ {
+ _amount = iAmount;
+ }
+
+ virtual string getName() const {
+ return "BackboneStretcherShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Geometry Shader. ]
+ * Resamples the stroke.
+ * @see Stroke::Resample(float).
+ */
+ class LIB_STROKE_EXPORT SamplingShader: public StrokeShader
+ {
+ private:
+ float _sampling;
+ public:
+ /*! Builds the shader.
+ * \param sampling
+ * The sampling to use for the
+ * stroke resampling
+ */
+ SamplingShader(float sampling)
+ : StrokeShader()
+ {
+ _sampling = sampling;
+ }
+
+ virtual string getName() const {
+ return "SamplingShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ class LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader
+ {
+ private:
+ float _amount;
+ public:
+ ExternalContourStretcherShader(float iAmount=2.f)
+ : StrokeShader()
+ {
+ _amount = iAmount;
+ }
+
+ virtual string getName() const {
+ return "ExternalContourStretcherShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ // B-Spline stroke shader
+ class LIB_STROKE_EXPORT BSplineShader: public StrokeShader
+ {
+ public:
+ BSplineShader()
+ : StrokeShader()
+ {}
+
+ virtual string getName() const {
+ return "BSplineShader";
+ }
+
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ // Bezier curve stroke shader
+ /*! [ Geometry Shader ].
+ * Transforms the stroke backbone geometry
+ * so that it corresponds to a Bezier Curve
+ * approximation of the original backbone geometry.
+ * @see \htmlonly <a href=bezier/bezier.html>bezier/bezier.html</a> \endhtmlonly
+ */
+ class LIB_STROKE_EXPORT BezierCurveShader : public StrokeShader
+ {
+ private:
+ float _error;
+ public:
+ /*! Builds the shader.
+ * \param error
+ * The error we're allowing for the approximation.
+ * This error is the max distance allowed between
+ * the new curve and the original geometry.
+ */
+ BezierCurveShader(float error = 4.0)
+ : StrokeShader()
+ {_error=error;}
+
+ virtual string getName() const {
+ return "BezierCurveShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /* Shader to inflate the curves. It keeps the extreme
+ * points positions and moves the other ones along
+ * the 2D normal. The displacement value is proportional
+ * to the 2d curvature at the considered point (the higher
+ * the curvature, the smaller the displacement) and to a value
+ * specified by the user.
+ */
+ class LIB_STROKE_EXPORT InflateShader : public StrokeShader
+ {
+ private:
+ float _amount;
+ float _curvatureThreshold;
+ public:
+ /*! Builds an inflate shader
+ * \param iAmount
+ * A multiplicative coefficient that
+ * acts on the amount and direction of displacement
+ * \param iThreshold
+ * The curves having a 2d curvature > iThreshold
+ * at one of their points is not inflated
+ */
+ InflateShader(float iAmount,float iThreshold)
+ : StrokeShader()
+ {
+ _amount = iAmount;
+ _curvatureThreshold = iThreshold;
+ }
+
+ virtual string getName() const {
+ return "InflateShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Geometry Shader ].
+ * Shader to modify the Stroke geometry so that
+ * it looks more "polygonal".
+ * The basic idea is to start from the
+ * minimal stroke approximation consisting in
+ * a line joining the first vertex to the last one and
+ * to subdivide using the original stroke vertices
+ * until a certain error is reached.
+ */
+ class LIB_STROKE_EXPORT PolygonalizationShader : public StrokeShader
+ {
+ private:
+ float _error;
+ public:
+ /*! Builds the shader.
+ * \param iError
+ * The error we want our polygonal approximation
+ * to have with respect to the original geometry.
+ * The smaller, the closer the new stroke to
+ * the orinal one.
+ * This error corresponds to the maximum distance
+ * between the new stroke and the old one.
+ */
+ PolygonalizationShader(float iError) : StrokeShader()
+ {_error = iError;}
+
+ virtual string getName() const {
+ return "PolygonalizationShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+
+ /*! [ Geometry Shader ].
+ * Shader to modify the Stroke geometry so that
+ * it corresponds to its main direction line.
+ * This shader must be used together with the
+ * splitting operator using the curvature criterion.
+ * Indeed, the precision of the approximation
+ * will depend on the size of the stroke's pieces.
+ * The bigger the pieces, the rougher the approximation.
+ */
+ class LIB_STROKE_EXPORT GuidingLinesShader : public StrokeShader
+ {
+ private:
+ float _offset;
+ public:
+ /*! Builds a Guiding Lines shader
+ * \param iOffset
+ * The line that replaces the stroke
+ * is initially in the middle
+ * of the initial stroke "bbox".
+ * iOffset is the value of the displacement
+ * which is applied to this line along its
+ * normal.
+ */
+ GuidingLinesShader(float iOffset) : StrokeShader()
+ {_offset = iOffset;}
+
+ virtual string getName() const {
+ return "GuidingLinesShader";
+ }
+
+ /*! The shading method */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ Geometry Shader ].
+ * Removes the stroke's extremities.
+ */
+ class LIB_STROKE_EXPORT TipRemoverShader : public StrokeShader
+ {
+ public:
+ /*! Builds the shader.
+ * \param tipLength
+ * The length of the piece of stroke
+ * we want to remove at each extremity.
+ */
+ TipRemoverShader (real tipLength);
+ /*! Destructor. */
+ virtual ~TipRemoverShader () {}
+ /*! The shading method */
+ virtual string getName() const {
+ return "TipRemoverShader";
+ }
+
+ virtual int shade(Stroke &stroke) const;
+
+ protected:
+
+ real _tipLength;
+ };
+
+ /*! [ output Shader ].
+ * streams the Stroke
+ */
+ class LIB_STROKE_EXPORT streamShader : public StrokeShader
+ {
+ public:
+ /*! Destructor. */
+ virtual ~streamShader() {}
+ /*! Returns the string "streamShader".*/
+ virtual string getName() const {
+ return "streamShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+
+ /*! [ output Shader ].
+ * streams the Stroke in a file
+ */
+ class LIB_STROKE_EXPORT fstreamShader : public StrokeShader
+ {
+ protected:
+ mutable ofstream _stream;
+ public:
+ /*! Builds the shader from the output file name */
+ fstreamShader(const char *iFileName) : StrokeShader(){
+ _stream .open(iFileName);
+ if(!_stream.is_open()){
+ cout << "couldn't open file " << iFileName << endl;
+ }
+ }
+ /*! Destructor. */
+ virtual ~fstreamShader() {_stream.close();}
+ /*! Returns the string "fstreamShader".*/
+ virtual string getName() const {
+ return "fstreamShader";
+ }
+ /*! The shading method. */
+ virtual int shade(Stroke& stroke) const;
+ };
+} // end of namespace StrokeShaders
+
+#endif // BASIC_STROKE_SHADERS_H
diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp
new file mode 100755
index 00000000000..c1843b7a6c1
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Canvas.cpp
@@ -0,0 +1,454 @@
+
+//
+// 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 "StrokeRenderer.h"
+#include <vector>
+#include "../system/FreestyleConfig.h"
+#include "../system/TimeStamp.h"
+#include "../system/PseudoNoise.h"
+#include "Canvas.h"
+#include "../image/Image.h"
+#include "../image/GaussianFilter.h"
+#include "../image/ImagePyramid.h"
+#include "../view_map/SteerableViewMap.h"
+#include "StyleModule.h"
+
+//soc #include <qimage.h>
+//soc #include <QString>
+#include <sstream>
+
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "intern/IMB_bmp.h"
+}
+
+using namespace std;
+
+LIB_STROKE_EXPORT
+Canvas * Canvas::_pInstance = 0;
+
+LIB_STROKE_EXPORT
+const char * Canvas::_MapsPath = 0;
+
+using namespace std;
+
+Canvas::Canvas()
+{
+ _SelectedFEdge = 0;
+ _pInstance = this;
+ PseudoNoise::init(42);
+ _Renderer = 0;
+ _current_sm = NULL;
+ _steerableViewMap = new SteerableViewMap(NB_STEERABLE_VIEWMAP-1);
+ _basic = false;
+}
+
+Canvas::Canvas(const Canvas& iBrother)
+{
+ _SelectedFEdge = iBrother._SelectedFEdge;
+ _pInstance = this;
+ PseudoNoise::init(42);
+ _Renderer = iBrother._Renderer;
+ _current_sm = iBrother._current_sm;
+ _steerableViewMap = new SteerableViewMap(*(iBrother._steerableViewMap));
+ _basic = iBrother._basic;
+}
+
+Canvas::~Canvas()
+{
+ _pInstance = 0;
+
+ Clear();
+ if(_Renderer)
+ {
+ delete _Renderer;
+ _Renderer = 0;
+ }
+ // FIXME: think about an easy control
+ // for the maps memory management...
+ if(!_maps.empty()){
+ for(mapsMap::iterator m=_maps.begin(), mend=_maps.end();
+ m!=mend;
+ ++m){
+ delete ((*m).second);
+ }
+ _maps.clear();
+ }
+ if(_steerableViewMap)
+ delete _steerableViewMap;
+}
+
+void Canvas::preDraw() {}
+
+void Canvas::Draw()
+{
+ if(_StyleModules.empty())
+ return;
+ preDraw();
+ TimeStamp *timestamp = TimeStamp::instance();
+
+ for(unsigned i = 0; i < _StyleModules.size(); i++) {
+ _current_sm = _StyleModules[i];
+
+ if (i < _Layers.size() && _Layers[i])
+ delete _Layers[i];
+
+ _Layers[i] = _StyleModules[i]->execute();
+ if (!_Layers[i])
+ continue;
+
+ stroke_count += _Layers[i]->strokes_size();
+
+ timestamp->increment();
+ }
+ postDraw();
+}
+
+void Canvas::postDraw()
+{
+ update();
+}
+
+
+void Canvas::Clear()
+{
+ if(!_Layers.empty()) {
+ for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
+ sl != slend;
+ ++sl)
+ if (*sl)
+ delete (*sl);
+ _Layers.clear();
+ }
+
+ if(!_StyleModules.empty()) {
+ for (deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
+ s != send;
+ ++s)
+ if (*s)
+ delete (*s);
+ _StyleModules.clear();
+ }
+ if(_steerableViewMap)
+ _steerableViewMap->Reset();
+
+ stroke_count = 0;
+}
+
+void Canvas::Erase()
+{
+ if(!_Layers.empty())
+ {
+ for (deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
+ sl != slend;
+ ++sl)
+ if (*sl)
+ (*sl)->clear();
+ }
+ if(_steerableViewMap)
+ _steerableViewMap->Reset();
+ update();
+
+stroke_count = 0;
+}
+
+void Canvas::PushBackStyleModule(StyleModule *iStyleModule) {
+ StrokeLayer* layer = new StrokeLayer();
+ _StyleModules.push_back(iStyleModule);
+ _Layers.push_back(layer);
+}
+
+void Canvas::InsertStyleModule(unsigned index, StyleModule *iStyleModule) {
+ unsigned size = _StyleModules.size();
+ StrokeLayer* layer = new StrokeLayer();
+ if((_StyleModules.empty()) || (index == size)) {
+ _StyleModules.push_back(iStyleModule);
+ _Layers.push_back(layer);
+ return;
+ }
+ _StyleModules.insert(_StyleModules.begin() + index, iStyleModule);
+ _Layers.insert(_Layers.begin()+index, layer);
+}
+
+void Canvas::RemoveStyleModule(unsigned index)
+{
+ unsigned i=0;
+ if (!_StyleModules.empty())
+ {
+ for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
+ s!=send;
+ ++s)
+ {
+ if(i == index)
+ {
+ // remove shader
+ if (*s)
+ delete *s;
+ _StyleModules.erase(s);
+ break;
+ }
+ ++i;
+ }
+ }
+ i=0;
+ if(!_Layers.empty())
+ {
+ for(deque<StrokeLayer*>::iterator sl=_Layers.begin(), slend=_Layers.end();
+ sl!=slend;
+ ++sl)
+ {
+ if(i == index)
+ {
+ // remove layer
+ if (*sl)
+ delete *sl;
+ _Layers.erase(sl);
+ break;
+ }
+ ++i;
+ }
+ }
+}
+
+
+void Canvas::SwapStyleModules(unsigned i1, unsigned i2)
+{
+ StyleModule* tmp;
+ tmp = _StyleModules[i1];
+ _StyleModules[i1] = _StyleModules[i2];
+ _StyleModules[i2] = tmp;
+
+ StrokeLayer* tmp2;
+ tmp2 = _Layers[i1];
+ _Layers[i1] = _Layers[i2];
+ _Layers[i2] = tmp2;
+}
+
+void Canvas::ReplaceStyleModule(unsigned index, StyleModule *iStyleModule)
+{
+ unsigned i=0;
+ for(deque<StyleModule*>::iterator s=_StyleModules.begin(), send=_StyleModules.end();
+ s != send;
+ ++s)
+ {
+ if(i == index)
+ {
+ if (*s)
+ delete *s;
+ *s = iStyleModule;
+ break;
+ }
+ ++i;
+ }
+}
+
+void Canvas::setVisible(unsigned index, bool iVisible) {
+ _StyleModules[index]->setDisplayed(iVisible);
+}
+
+void Canvas::setModified(unsigned index, bool iMod)
+{
+ _StyleModules[index]->setModified(iMod);
+}
+
+void Canvas::resetModified(bool iMod/* =false */)
+{
+ unsigned size = _StyleModules.size();
+ for(unsigned i = 0; i < size; ++i)
+ setModified(i,iMod);
+}
+
+void Canvas::causalStyleModules(vector<unsigned>& vec, unsigned index) {
+ unsigned size = _StyleModules.size();
+
+ for(unsigned i = index; i < size; ++i)
+ if (_StyleModules[i]->getCausal())
+ vec.push_back(i);
+}
+
+void Canvas::Render(const StrokeRenderer *iRenderer)
+{
+ for (unsigned i = 0; i < _StyleModules.size(); i++) {
+ if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->Render(iRenderer);
+ }
+}
+
+void Canvas::RenderBasic(const StrokeRenderer *iRenderer)
+
+{
+ for (unsigned i = 0; i < _StyleModules.size(); i++) {
+ if(!_StyleModules[i]->getDisplayed() || !_Layers[i])
+ continue;
+ _Layers[i]->RenderBasic(iRenderer);
+ }
+}
+
+void Canvas::loadMap(const char *iFileName, const char *iMapName, unsigned int iNbLevels, float iSigma){
+ // check whether this map was already loaded:
+ if(!_maps.empty()){
+ mapsMap::iterator m = _maps.find(iMapName);
+ if(m!=_maps.end()){
+ // lazy check for size changes
+ ImagePyramid * pyramid = (*m).second;
+ if((pyramid->width() != width()) || (pyramid->height() != height())){
+ delete pyramid;
+ }else{
+ return;
+ }
+ }
+ }
+ string filePath;
+ if(_MapsPath){
+ filePath = _MapsPath;
+ filePath += iFileName;
+ }else{
+ filePath = iFileName;
+ }
+
+ //soc
+ // QImage *qimg;
+ // QImage newMap(filePath.c_str());
+ // if(newMap.isNull()){
+ // cout << "Could not load image file " << filePath << endl;
+ // return;
+ // }
+ // qimg = &newMap;
+ ImBuf *qimg = IMB_loadiffname(filePath.c_str(), 0);;
+ if( qimg == 0 ){
+ cout << "Could not load image file " << filePath << endl;
+ return;
+ }
+
+ // soc
+ //resize
+ // QImage scaledImg;
+ // if((newMap.width()!=width()) || (newMap.height()!=height())){
+ // scaledImg = newMap.scaled(width(), height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ // qimg = &scaledImg;
+ // }
+ ImBuf *scaledImg;
+ if( ( qimg->x != width() ) || ( qimg->y != height() ) ){
+ scaledImg = IMB_dupImBuf(qimg);
+ IMB_scaleImBuf(scaledImg, width(), height());
+ }
+
+
+ // deal with color image
+ // if(newMap->depth() != 8){
+ // int w = newMap->width();
+ // int h = newMap->height();
+ // QImage *tmp = new QImage(w, h, 8);
+ // for(unsigned y=0;y<h;++y){
+ // for(unsigned x=0;x<w;++x){
+ // int c = qGray(newMap->pixel(x,y));
+ // tmp->setPixel(x,y,c);
+ // }
+ // }
+ // delete newMap;
+ // newMap = tmp;
+ // }
+
+ int x,y;
+ int w = qimg->x;
+ int h = qimg->y;
+int rowbytes = w*4;
+ GrayImage tmp(w,h);
+ char *pix;
+
+ for(y=0; y<h;++y){
+ for(x=0;x<w;++x){
+ pix = (char*)qimg->rect + y*rowbytes + x*4;
+ float c = (pix[0]*11 + pix[1]*16 + pix[2]*5)/32;
+ tmp.setPixel(x,y,c);
+ }
+ }
+
+ // GrayImage blur(w,h);
+ // GaussianFilter gf(4.f);
+ // //int bound = gf.getBound();
+ // for(y=0; y<h;++y){
+ // for(x=0;x<w;++x){
+ // int c = gf.getSmoothedPixel<GrayImage>(&tmp, x,y);
+ // blur.setPixel(x,y,c);
+ // }
+ // }
+
+ GaussianPyramid *pyramid = new GaussianPyramid(tmp, iNbLevels, iSigma);
+ int ow = pyramid->width(0);
+ int oh = pyramid->height(0);
+ string base(iMapName); //soc
+ for(int i=0; i<pyramid->getNumberOfLevels(); ++i){
+ // save each image:
+ // w = pyramid.width(i);
+ // h = pyramid.height(i);
+
+ //soc QImage qtmp(ow, oh, QImage::Format_RGB32);
+ ImBuf *qtmp = IMB_allocImBuf(ow, oh, 32, IB_rect, 0);
+
+//int k = (1<<i);
+ for(y=0;y<oh;++y){
+ for(x=0;x<ow;++x){
+ int c = pyramid->pixel(x,y,i);//255*pyramid->pixel(x,y,i);
+ //soc qtmp.setPixel(x,y,qRgb(c,c,c));
+ pix = (char*)qtmp->rect + y*rowbytes + x*4;
+ pix[0] = pix [1] = pix[2] = c;
+ }
+ }
+ //soc qtmp.save(base+QString::number(i)+".bmp", "BMP");
+ stringstream filename;
+ filename << base;
+ filename << i << ".bmp";
+ imb_savebmp(qtmp, const_cast<char *>(filename.str().c_str()), 0);
+
+ }
+ // QImage *qtmp = new QImage(w, h, 32);
+ // for(y=0;y<h;++y){
+ // for(x=0;x<w;++x){
+ // int c = (int)blur.pixel(x,y);
+ // qtmp->setPixel(x,y,qRgb(c,c,c));
+ // }
+ // }
+ // delete newMap;
+ // newMap = qtmp;
+ //
+ _maps[iMapName] = pyramid;
+ // newMap->save("toto.bmp", "BMP");
+}
+
+float Canvas::readMapPixel(const char *iMapName, int level, int x, int y){
+ if(_maps.empty()){
+ cout << "readMapPixel warning: no map was loaded "<< endl;
+ return -1;
+ }
+ mapsMap::iterator m = _maps.find(iMapName);
+ if(m==_maps.end()){
+ cout << "readMapPixel warning: no map was loaded with the name " << iMapName << endl;
+ return -1;
+ }
+ ImagePyramid *pyramid = (*m).second;
+ if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height()))
+ return 0;
+
+ return pyramid->pixel(x,height()-1-y,level);
+}
diff --git a/source/blender/freestyle/intern/stroke/Canvas.h b/source/blender/freestyle/intern/stroke/Canvas.h
new file mode 100755
index 00000000000..707455c87f6
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Canvas.h
@@ -0,0 +1,196 @@
+//
+// Filename : Canvas.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a canvas designed to draw style modules
+// Date of creation : 20/10/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 CANVAS_H
+# define CANVAS_H
+
+# include <cstring>
+# include <deque>
+# include <vector>
+# include <map>
+# include "../system/FreestyleConfig.h"
+# include "StrokeLayer.h"
+# include "../geometry/BBox.h"
+# include "../geometry/Geom.h"
+
+using namespace Geometry;
+
+struct ltstr
+{
+ bool operator()(const char* s1, const char* s2) const
+ {
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+class InformationMap;
+class StrokeRenderer;
+class ViewMap;
+class ViewEdge;
+class FEdge;
+class RGBImage;
+class GrayImage;
+class QImage;
+class ImagePyramid;
+class SteerableViewMap;
+class StyleModule;
+
+/*! Class to define the canvas on which strokes are drawn.
+ * It's used to store state information about the drawing.
+ */
+class LIB_STROKE_EXPORT Canvas
+{
+public:
+ /*! Returns a pointer on the Canvas instance */
+ static Canvas * getInstance() {return _pInstance;}
+ typedef std::map<const char*, ImagePyramid*, ltstr> mapsMap ;
+ static const int NB_STEERABLE_VIEWMAP = 5;
+protected:
+ static Canvas *_pInstance;
+ std::deque<StrokeLayer*> _Layers;
+ std::deque<StyleModule*> _StyleModules;
+ FEdge *_SelectedFEdge;
+
+ StrokeRenderer *_Renderer;
+ StyleModule* _current_sm;
+ mapsMap _maps;
+ static const char * _MapsPath;
+ SteerableViewMap *_steerableViewMap;
+ bool _basic;
+
+public:
+ /* Builds the Canvas */
+ Canvas();
+ /* Copy constructor */
+ Canvas(const Canvas& iBrother);
+ /* Destructor */
+ virtual ~Canvas();
+
+ /* operations that need to be done before a draw */
+ virtual void preDraw();
+
+ /* Draw the canvas using the current shader */
+ virtual void Draw();
+
+ /* operations that need to be done after a draw */
+ virtual void postDraw();
+
+ /* Renders the created strokes */
+ virtual void Render(const StrokeRenderer *iRenderer);
+ /* Basic Renders the created strokes */
+ virtual void RenderBasic(const StrokeRenderer *iRenderer);
+ /* Renders a stroke */
+ virtual void RenderStroke(Stroke *iStroke) = 0;
+
+ /* init the canvas */
+ virtual void init() = 0;
+
+ /* Clears the Canvas (shaders stack, layers stack...)*/
+ void Clear();
+
+ /* Erases the layers */
+ virtual void Erase();
+
+ /* Reads a pixel area from the canvas */
+ virtual void readColorPixels(int x, int y,int w, int h, RGBImage& oImage) const = 0;
+ /* Reads a depth pixel area from the canvas */
+ virtual void readDepthPixels(int x, int y,int w, int h, GrayImage& oImage) const = 0;
+
+ /* update the canvas (display) */
+ virtual void update() = 0;
+
+ /* checks whether the canvas is empty or not */
+ bool isEmpty() const {return (_Layers.empty());}
+
+ /* Maps management */
+ /*! Loads an image map. The map will be scaled
+ * (without preserving the ratio in order
+ * to fit the actual canvas size.)
+ * The image must be a gray values image...
+ * \param iFileName
+ * The name of the image file
+ * \param iMapName
+ * The name that will be used to access
+ * this image
+ * \param iNbLevels
+ * The number of levels in the map pyramid. (default = 4).
+ * If iNbLevels == 0, the complete pyramid is built.
+ */
+ void loadMap(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma = 1.f);
+
+ /*! Reads a pixel value in a map.
+ * Returns a value between 0 and 1.
+ * \param iMapName
+ * The name of the map
+ * \param level
+ * The level of the pyramid from which the pixel must
+ * be 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 readMapPixel(const char *iMapName, int level, int x, int y);
+
+ /*! Sets the steerable viewmap */
+ void loadSteerableViewMap(SteerableViewMap * iSVM) {_steerableViewMap = iSVM;}
+
+ /*! Returns the steerable VM */
+ SteerableViewMap * getSteerableViewMap() {return _steerableViewMap;}
+
+ /*! accessors */
+ inline const FEdge * selectedFEdge() const {return _SelectedFEdge;}
+ inline FEdge * selectedFEdge() {return _SelectedFEdge;}
+ virtual int width() const = 0;
+ virtual int height() const = 0;
+ virtual BBox<Vec3r> scene3DBBox() const = 0;
+ inline const StrokeRenderer * renderer() const {return _Renderer;}
+ inline StyleModule* getCurrentStyleModule() { return _current_sm; }
+ virtual bool getRecordFlag() const {return false;}
+ int stroke_count;
+
+ /*! modifiers */
+ inline void setSelectedFEdge(FEdge *iFEdge) {_SelectedFEdge = iFEdge;}
+ /*! inserts a shader at pos index+1 */
+ void PushBackStyleModule(StyleModule *iStyleModule);
+ void InsertStyleModule(unsigned index, StyleModule *iStyleModule);
+ void RemoveStyleModule(unsigned index);
+ void SwapStyleModules(unsigned i1, unsigned i2);
+ void ReplaceStyleModule(unsigned index, StyleModule *iStyleModule);
+ void setVisible(unsigned index, bool iVisible) ;
+ //inline void setDensityMap(InformationMap<RGBImage>* iMap) {_DensityMap = iMap;}
+ inline void AddLayer(StrokeLayer *iLayer) {_Layers.push_back(iLayer);}
+ void resetModified(bool iMod=false);
+ void causalStyleModules(std::vector<unsigned>& vec, unsigned index = 0);
+ void setModified(unsigned index, bool b);
+};
+
+#endif // CANVAS_H
diff --git a/source/blender/freestyle/intern/stroke/Chain.cpp b/source/blender/freestyle/intern/stroke/Chain.cpp
new file mode 100755
index 00000000000..3776cd58a03
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Chain.cpp
@@ -0,0 +1,126 @@
+
+//
+// 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 "Chain.h"
+#include "../view_map/ViewMapIterators.h"
+#include "../view_map/ViewMapAdvancedIterators.h"
+
+void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation)
+{
+ ViewEdge::vertex_iterator v;
+ ViewEdge::vertex_iterator vend;
+ ViewEdge::vertex_iterator vfirst;
+ Vec3r previous, current;
+ if(true == orientation)
+ {
+ v=iViewEdge->vertices_begin();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+ else
+ {
+ v=iViewEdge->vertices_last();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+
+ if(!_Vertices.empty())
+ {
+ previous = _Vertices.back()->point2d();
+ if(orientation)
+ ++v;
+ else
+ --v;
+ }
+ else
+ previous = (*v)->point2d();
+ do{
+ current = (*v)->point2d();
+ Curve::push_vertex_back(*v);
+ //_Length += (current-previous).norm();
+ previous = current;
+ if(orientation)
+ ++v;
+ else
+ --v;
+ }while((v!=vend) && (v!=vfirst));
+
+ if(v==vfirst)
+ {
+ //Add last one:
+ current = (*v)->point2d();
+ Curve::push_vertex_back(*v);
+ //_Length += (current-previous).norm();
+ }
+}
+
+void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation)
+{
+ orientation = !orientation;
+ ViewEdge::vertex_iterator v;
+ ViewEdge::vertex_iterator vend;
+ ViewEdge::vertex_iterator vfirst;
+ Vec3r previous, current;
+ if(true == orientation)
+ {
+ v=iViewEdge->vertices_begin();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+ else
+ {
+ v=iViewEdge->vertices_last();
+ vfirst = v;
+ vend=iViewEdge->vertices_end();
+ }
+
+ if(!_Vertices.empty())
+ {
+ previous = _Vertices.front()->point2d();
+ if(orientation)
+ ++v;
+ else
+ --v;
+ }
+ else
+ previous = (*v)->point2d();
+ do{
+ current = (*v)->point2d();
+ Curve::push_vertex_front((*v));
+ //_Length += (current-previous).norm();
+ previous = current;
+ if(orientation)
+ ++v;
+ else
+ --v;
+ }while((v!=vend) && (v!=vfirst));
+
+ if(v==vfirst)
+ {
+ //Add last one:
+ current = (*v)->point2d();
+ Curve::push_vertex_front(*v);
+ //_Length += (current-previous).norm();
+ }
+}
+
+
+
diff --git a/source/blender/freestyle/intern/stroke/Chain.h b/source/blender/freestyle/intern/stroke/Chain.h
new file mode 100755
index 00000000000..711ae16a1a0
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Chain.h
@@ -0,0 +1,86 @@
+//
+// Filename : Chain.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a chain of viewedges.
+// 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 CHAIN_H
+# define CHAIN_H
+
+# include "../view_map/ViewMap.h"
+# include "Curve.h"
+/*! Class to represent a 1D elements issued
+ * from the chaining process.
+ * A Chain is the last step before the Stroke and
+ * is used in the Splitting and Creation processes.
+ */
+class Chain : public Curve
+{
+protected:
+ // tmp
+ Id * _splittingId;
+public:
+ /*! Defult constructor. */
+ Chain() : Curve() {_splittingId=0;}
+ /*! Builds a chain from its Id. */
+ Chain(const Id& id) : Curve(id) {_splittingId=0;}
+ /*! Copy Constructor */
+ Chain(const Chain& iBrother) : Curve(iBrother) {_splittingId=iBrother._splittingId;}
+ /*! Destructor. */
+ virtual ~Chain() {
+ // only the last splitted deletes this id
+ if(_splittingId){
+ if(*_splittingId == _Id)
+ delete _splittingId;
+ }
+ }
+ /*! Returns the string "Chain" */
+ virtual string getExactTypeName() const {
+ return "Chain";
+ }
+
+ /*! Adds a ViewEdge at the end of the chain
+ * \param iViewEdge
+ * The ViewEdge that must be added.
+ * \param orientation
+ * The orientation with which this ViewEdge
+ * must be processed.
+ */
+ void push_viewedge_back(ViewEdge *iViewEdge, bool orientation) ;
+ /*! Adds a ViewEdge at the beginning of the chain
+ * \param iViewEdge
+ * The ViewEdge that must be added.
+ * \param orientation
+ * The orientation with which this ViewEdge
+ * must be processed.
+ */
+ void push_viewedge_front(ViewEdge *iViewEdge, bool orientation) ;
+
+ inline void setSplittingId(Id * sid){_splittingId = sid;}
+ inline Id* getSplittingId() {return _splittingId;}
+};
+
+#endif // CHAIN_H
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.cpp b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp
new file mode 100755
index 00000000000..c54ee6ea1ee
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.cpp
@@ -0,0 +1,170 @@
+
+//
+// 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 "ChainingIterators.h"
+#include "../system/TimeStamp.h"
+
+ViewEdge* AdjacencyIterator::operator*() {
+ return (*_internalIterator).first;
+}
+bool AdjacencyIterator::isIncoming() const{
+ return (*_internalIterator).second;
+}
+
+int AdjacencyIterator::increment(){
+ ++_internalIterator;
+ while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
+ ++_internalIterator;
+ return 0;
+}
+
+bool AdjacencyIterator::isValid(ViewEdge* edge){
+ if(_restrictToSelection)
+ if(edge->getTimeStamp() != TimeStamp::instance()->getTimeStamp())
+ return false;
+ if(_restrictToUnvisited)
+ if(edge->getChainingTimeStamp() > TimeStamp::instance()->getTimeStamp())
+ return false;
+ return true;
+}
+
+int ChainingIterator::increment() {
+ _increment = true;
+ ViewVertex * vertex = getVertex();
+ if(!vertex){
+ _edge = 0;
+ return 0;
+ }
+ AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
+ if(it.isEnd()) {
+ _edge = 0;
+ return 0;
+ }
+ if (traverse(it) < 0)
+ return -1;
+ _edge = result;
+ if(_edge == 0)
+ return 0;
+ if(_edge->A() == vertex)
+ _orientation = true;
+ else
+ _orientation = false;
+ return 0;
+}
+
+int ChainingIterator::decrement() {
+ _increment = false;
+ ViewVertex * vertex = getVertex();
+ if(!vertex){
+ _edge = 0;
+ return 0;
+ }
+ AdjacencyIterator it = AdjacencyIterator(vertex, _restrictToSelection, _restrictToUnvisited);
+ if(it.isEnd()) {
+ _edge = 0;
+ return 0;
+ }
+ if (traverse(it) < 0)
+ return -1;
+ _edge = result;
+ if(_edge == 0)
+ return 0;
+ if(_edge->B() == vertex)
+ _orientation = true;
+ else
+ _orientation = false;
+ return 0;
+}
+
+//
+// ChainSilhouetteIterators
+//
+///////////////////////////////////////////////////////////
+
+int ChainSilhouetteIterator::traverse(const AdjacencyIterator& ait){
+ AdjacencyIterator it(ait);
+ ViewVertex* nextVertex = getVertex();
+ // we can't get a NULL nextVertex here, it was intercepted
+ // before
+ if(nextVertex->getNature() & Nature::T_VERTEX){
+ TVertex * tvertex = (TVertex*)nextVertex;
+ ViewEdge *mate = (tvertex)->mate(getCurrentEdge());
+ while(!it.isEnd()){
+ ViewEdge *ve = *it;
+ if(ve == mate) {
+ result = ve;
+ return 0;
+ }
+ ++it;
+ }
+ result = 0;
+ return 0;
+ }
+ if(nextVertex->getNature() & Nature::NON_T_VERTEX){
+ //soc NonTVertex * nontvertex = (NonTVertex*)nextVertex;
+ ViewEdge * newEdge(0);
+ // we'll try to chain the edges by keeping the same nature...
+ // the preseance order is : SILHOUETTE, BORDER, CREASE, SUGGESTIVE, VALLEY, RIDGE
+ Nature::EdgeNature natures[6] = {Nature::SILHOUETTE, Nature::BORDER, Nature::CREASE, Nature::SUGGESTIVE_CONTOUR, Nature::VALLEY, Nature::RIDGE};
+ for(unsigned i=0; i<6; ++i){
+ if(getCurrentEdge()->getNature() & natures[i]){
+ int n = 0;
+ while(!it.isEnd()){
+ ViewEdge *ve = *it;
+ if(ve->getNature() & natures[i]){
+ ++n;
+ newEdge = ve;
+ }
+ ++it;
+ }
+ if(n == 1){
+ result = newEdge;
+ }else{
+ result = 0;
+ }
+ return 0;
+ }
+ }
+ }
+ result = 0;
+ return 0;
+}
+
+int ChainPredicateIterator::traverse(const AdjacencyIterator& ait){
+ AdjacencyIterator it(ait);
+ // Iterates over next edges to see if one of them
+ // respects the predicate:
+ while(!it.isEnd()) {
+ ViewEdge *ve = *it;
+ if (_unary_predicate->operator()(*ve) < 0)
+ return -1;
+ if (_unary_predicate->result) {
+ if (_binary_predicate->operator()(*(getCurrentEdge()), *(ve)) < 0)
+ return -1;
+ if (_binary_predicate->result) {
+ result = ve;
+ return 0;
+ }
+ }
+ ++it;
+ }
+ result = 0;
+ return 0;
+}
diff --git a/source/blender/freestyle/intern/stroke/ChainingIterators.h b/source/blender/freestyle/intern/stroke/ChainingIterators.h
new file mode 100755
index 00000000000..fec8d5ab6dc
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ChainingIterators.h
@@ -0,0 +1,394 @@
+//
+// Filename : ChainingIterators
+// Author : Stephane Grabli
+// Purpose : Chaining iterators
+// 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 CHAININGITERATORS_H
+# define CHAININGITERATORS_H
+
+# include "../view_map/ViewMap.h"
+# include "../view_map/ViewMapIterators.h"
+# include "../view_map/ViewMapAdvancedIterators.h"
+# include <iostream>
+# include "Predicates1D.h"
+
+#include "../system/Iterator.h" //soc
+
+# include "../python/Director.h"
+
+//using namespace ViewEdgeInternal;
+
+//
+// Adjacency iterator used in the chaining process
+//
+///////////////////////////////////////////////////////////
+class LIB_STROKE_EXPORT AdjacencyIterator : public Iterator {
+protected:
+ ViewVertexInternal::orientedViewEdgeIterator _internalIterator;
+ bool _restrictToSelection;
+ bool _restrictToUnvisited;
+public:
+ AdjacencyIterator(){
+ _restrictToSelection = true;
+ _restrictToUnvisited = true;
+ }
+ AdjacencyIterator(ViewVertex *iVertex, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true){
+ _restrictToSelection = iRestrictToSelection;
+ _restrictToUnvisited = iRestrictToUnvisited;
+ _internalIterator = iVertex->edgesBegin();
+ while((!_internalIterator.isEnd()) && (!isValid((*_internalIterator).first)))
+ ++_internalIterator;
+ }
+ AdjacencyIterator(const AdjacencyIterator& iBrother){
+ _internalIterator = iBrother._internalIterator;
+ _restrictToSelection = iBrother._restrictToSelection;
+ _restrictToUnvisited = iBrother._restrictToUnvisited;
+ }
+ AdjacencyIterator& operator=(const AdjacencyIterator& iBrother) {
+ _internalIterator = iBrother._internalIterator;
+ _restrictToSelection = iBrother._restrictToSelection;
+ _restrictToUnvisited = iBrother._restrictToUnvisited;
+ return *this;
+ }
+ virtual ~AdjacencyIterator(){
+ }
+
+ virtual string getExactTypeName() const {
+ return "AdjacencyIterator";
+ }
+
+ virtual inline bool isEnd() const {
+ return _internalIterator.isEnd();
+ }
+ virtual inline bool isBegin() const {
+ return _internalIterator.isBegin();
+ }
+ /*! Returns true if the current ViewEdge is is coming
+ * towards the iteration vertex. False otherwise.
+ */
+ bool isIncoming() const ;
+
+ /*! Returns a *pointer* to the pointed ViewEdge. */
+ virtual ViewEdge* operator*() ;
+ virtual ViewEdge* operator->() {return operator*();}
+ virtual AdjacencyIterator& operator++() {
+ increment();
+ return *this;
+ }
+ virtual AdjacencyIterator operator++(int) {
+ AdjacencyIterator tmp(*this);
+ increment();
+ return tmp;
+ }
+ virtual int increment();
+
+ virtual int decrement(){
+ cerr << "Warning: method decrement() not implemented" << endl;
+ return 0;
+ }
+
+protected:
+ bool isValid(ViewEdge* edge);
+};
+
+//
+// Base class for Chaining Iterators
+//
+///////////////////////////////////////////////////////////
+
+/*! Base class for chaining iterators.
+ * This class is designed to be overloaded
+ * in order to describe chaining rules.
+ * It makes the works of chaining rules description
+ * easier.
+ * The two main methods that need to overloaded are
+ * traverse() and init().
+ * traverse() tells which ViewEdge to follow, among the adjacent ones.
+ * If you specify restriction rules (such as "Chain only
+ * ViewEdges of the selection"), they will be included
+ * in the adjacency iterator. (i.e, the adjacent iterator
+ * will only stop on "valid" edges).
+ */
+class LIB_STROKE_EXPORT ChainingIterator : public ViewEdgeInternal::ViewEdgeIterator{
+protected:
+ bool _restrictToSelection;
+ bool _restrictToUnvisited;
+ bool _increment; //true if we're currently incrementing, false when decrementing
+
+public:
+
+ ViewEdge *result;
+ PyObject *py_c_it;
+
+ /*! Builds a Chaining Iterator from the first ViewEdge used for iteration
+ * and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained
+ * must be ignored ot not.
+ * \param begin
+ * The ViewEdge from which to start the chain.
+ * \param orientation
+ * The direction to follow to explore the graph. If true,
+ * the direction indicated by the first ViewEdge is used.
+ */
+ ChainingIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = 0, bool orientation = true)
+ : ViewEdgeIterator(begin, orientation) {
+ _restrictToSelection = iRestrictToSelection;
+ _restrictToUnvisited = iRestrictToUnvisited;
+ _increment = true;
+ py_c_it = 0;
+ }
+
+ /*! Copy constructor */
+ ChainingIterator(const ChainingIterator& brother)
+ : ViewEdgeIterator(brother) {
+ _restrictToSelection = brother._restrictToSelection;
+ _restrictToUnvisited = brother._restrictToUnvisited;
+ _increment = brother._increment;
+ py_c_it = brother.py_c_it;
+ }
+
+ /*! Returns the string "ChainingIterator" */
+ virtual string getExactTypeName() const {
+ return "ChainingIterator";
+ }
+
+ /*! Inits the iterator context.
+ * This method is called each time
+ * a new chain is started.
+ * It can be used to reset some
+ * history information that you
+ * might want to keep.
+ */
+ virtual int init() {
+ return Director_BPy_ChainingIterator_init( this );
+ }
+
+ /*! This method iterates over the potential next
+ * ViewEdges and returns the one that will be
+ * followed next.
+ * returns the next ViewEdge to follow or
+ * 0 when the end of the chain is reached.
+ * \param it
+ * The iterator over the ViewEdges adjacent to
+ * the end vertex of the current ViewEdge.
+ * The Adjacency iterator reflects the restriction
+ * rules by only iterating over the valid ViewEdges.
+ */
+ virtual int traverse(const AdjacencyIterator &it){
+ return Director_BPy_ChainingIterator_traverse( this, const_cast<AdjacencyIterator &>(it) );
+ }
+
+ /* accessors */
+ /*! Returns true if the orientation of the current ViewEdge
+ * corresponds to its natural orientation
+ */
+ //inline bool getOrientation() const {}
+ /*! Returns the vertex which is the next crossing */
+ inline ViewVertex * getVertex() {
+ if(_increment){
+ if(_orientation){
+ return _edge->B();
+ }else{
+ return _edge->A();
+ }
+ }else{
+ if(_orientation){
+ return _edge->A();
+ }else{
+ return _edge->B();
+ }
+ }
+ }
+
+ /*! Returns true if the current iteration is an incrementation */
+ inline bool isIncrementing() const{
+ return _increment;
+ }
+
+ /* increments.*/
+ virtual int increment() ;
+ virtual int decrement() ;
+};
+
+//
+// Chaining iterators definitions
+//
+///////////////////////////////////////////////////////////
+
+/*! A ViewEdge Iterator used to follow ViewEdges the most naturally.
+ * For example, it will follow visible ViewEdges of same nature.
+ * As soon, as the nature or the visibility changes, the iteration
+ * stops (by setting the pointed ViewEdge to 0).
+ * In the case of an iteration over a set of ViewEdge that are both
+ * Silhouette and Crease, there will be a precedence of the silhouette
+ * over the crease criterion.
+ */
+class LIB_STROKE_EXPORT ChainSilhouetteIterator : public ChainingIterator
+{
+public:
+ /*! Builds a ChainSilhouetteIterator from the first ViewEdge used for iteration
+ * and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \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.
+ */
+ ChainSilhouetteIterator(bool iRestrictToSelection = true, ViewEdge* begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, true, begin, orientation) {}
+
+ /*! Copy constructor */
+ ChainSilhouetteIterator(const ChainSilhouetteIterator& brother)
+ : ChainingIterator(brother) {}
+
+ /*! Returns the string "ChainSilhouetteIterator" */
+ virtual string getExactTypeName() const {
+ return "ChainSilhouetteIterator";
+ }
+
+ /*! This method iterates over the potential next
+ * ViewEdges and returns the one that will be
+ * followed next.
+ * When reaching the end of a chain, 0 is returned.
+ */
+ virtual int traverse(const AdjacencyIterator& it);
+
+ /*! Inits the iterator context */
+ virtual int init() {
+ return 0;
+ }
+};
+
+//
+// ChainPredicateIterator
+//
+///////////////////////////////////////////////////////////
+
+/*! A "generic" user-controlled ViewEdge iterator. This iterator
+ * is in particular built from a unary predicate and a binary predicate.
+ * First, the unary predicate is evaluated for all potential next ViewEdges
+ * in order to only keep the ones respecting a certain constraint.
+ * Then, the binary predicate is evaluated on the current ViewEdge
+ * together with each ViewEdge of the previous selection. The first
+ * ViewEdge respecting both the unary predicate and the binary predicate
+ * is kept as the next one. If none of the potential next ViewEdge respects
+ * these 2 predicates, 0 is returned.
+ */
+class LIB_STROKE_EXPORT ChainPredicateIterator : public ChainingIterator
+{
+protected:
+ BinaryPredicate1D *_binary_predicate; // the caller is responsible for the deletion of this object
+ UnaryPredicate1D *_unary_predicate; // the caller is responsible for the deletion of this object
+public:
+
+ /*! Builds a ChainPredicateIterator from a starting ViewEdge and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained
+ * must be ignored ot not.
+ * \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.
+ */
+ ChainPredicateIterator(bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) {
+ _binary_predicate = 0;
+ _unary_predicate = 0;
+ }
+
+ /*! Builds a ChainPredicateIterator from a unary predicate, a binary predicate, a starting ViewEdge and its orientation.
+ * \param iRestrictToSelection
+ * Indicates whether to force the chaining to stay within
+ * the set of selected ViewEdges or not.
+ * \param iRestrictToUnvisited
+ * Indicates whether a ViewEdge that has already been chained
+ * must be ignored ot not.
+ * \param upred
+ * The unary predicate that the next ViewEdge must satisfy.
+ * \param bpred
+ * The binary predicate that the next ViewEdge must satisfy
+ * together with the actual pointed ViewEdge.
+ * \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.
+ */
+ ChainPredicateIterator(UnaryPredicate1D& upred, BinaryPredicate1D& bpred, bool iRestrictToSelection = true, bool iRestrictToUnvisited = true, ViewEdge* begin = NULL, bool orientation = true)
+ : ChainingIterator(iRestrictToSelection, iRestrictToUnvisited, begin, orientation) {
+ _unary_predicate = &upred;
+ _binary_predicate = &bpred;
+ }
+
+ /*! Copy constructor */
+ ChainPredicateIterator(const ChainPredicateIterator& brother)
+ : ChainingIterator(brother){
+ _unary_predicate = brother._unary_predicate;
+ _binary_predicate = brother._binary_predicate;
+ }
+
+ /*! Destructor. */
+ virtual ~ChainPredicateIterator(){
+ _unary_predicate = 0;
+ _binary_predicate = 0;
+ }
+
+ /*! Returns the string "ChainPredicateIterator" */
+ virtual string getExactTypeName() const {
+ return "ChainPredicateIterator";
+ }
+
+ /*! This method iterates over the potential next
+ * ViewEdges and returns the one that will be
+ * followed next.
+ * When reaching the end of a chain, 0 is returned.
+ */
+ virtual int traverse(const AdjacencyIterator &it);
+
+ /*! Inits the iterator context */
+ virtual int init() {
+ return 0;
+ }
+
+};
+
+#endif // CHAININGITERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.cpp b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
new file mode 100755
index 00000000000..b55da1fb0f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.cpp
@@ -0,0 +1,60 @@
+
+//
+// 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 "ContextFunctions.h"
+#include "../view_map/SteerableViewMap.h"
+#include "../system/TimeStamp.h"
+namespace ContextFunctions {
+
+ unsigned GetTimeStampCF(){
+ return TimeStamp::instance()->getTimeStamp();
+ }
+
+ unsigned GetCanvasWidthCF(){
+ return Canvas::getInstance()->width();
+ }
+
+ unsigned GetCanvasHeightCF(){
+ return Canvas::getInstance()->height();
+ }
+ void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels, float iSigma ){
+ return Canvas::getInstance()->loadMap(iFileName, iMapName, iNbLevels,iSigma);
+ }
+
+ float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y){
+ Canvas * canvas = Canvas::getInstance();
+ return canvas->readMapPixel(iMapName, level, x,y);
+ }
+
+ float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y){
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ return svm->readCompleteViewMapPixel(level,x,y);
+ }
+
+ float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y){
+ SteerableViewMap *svm = Canvas::getInstance()->getSteerableViewMap();
+ return svm->readSteerableViewMapPixel(iOrientation, level,x,y);
+ }
+
+ FEdge * GetSelectedFEdgeCF(){
+ return Canvas::getInstance()->selectedFEdge();
+ }
+}
diff --git a/source/blender/freestyle/intern/stroke/ContextFunctions.h b/source/blender/freestyle/intern/stroke/ContextFunctions.h
new file mode 100755
index 00000000000..37c98656fa7
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/ContextFunctions.h
@@ -0,0 +1,124 @@
+//
+// Filename : AdvancedFunctions0D.h
+// Author(s) : Stephane Grabli
+// Purpose : Functions related to context queries
+// Date of creation : 20/12/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 CONTEXT_FUNCTIONS_HPP
+# define CONTEXT_FUNCTIONS_HPP
+
+# include "Canvas.h"
+# include "../image/Image.h"
+# include "../image/GaussianFilter.h"
+
+/*! \file ContextFunctions.h
+ * Interface to access the context related
+ * information.
+ */
+//
+// Context Functions definitions
+//
+///////////////////////////////////////////////////////////
+/*! namespace containing all the Context related functions */
+namespace ContextFunctions {
+
+ // GetTimeStamp
+ LIB_STROKE_EXPORT
+ /*! Returns the system time stamp */
+ unsigned GetTimeStampCF();
+
+ // GetCanvasWidth
+ /*! Returns the canvas width */
+ LIB_STROKE_EXPORT
+ unsigned GetCanvasWidthCF();
+
+ // GetCanvasHeight
+ /*! Returns the canvas width */
+ LIB_STROKE_EXPORT
+ unsigned GetCanvasHeightCF();
+
+ // Load map
+ /*! Loads an image map for further reading */
+ LIB_STROKE_EXPORT
+ void LoadMapCF(const char *iFileName, const char *iMapName, unsigned iNbLevels=4, float iSigma=1.f);
+
+ // ReadMapPixel
+ /*! Reads a pixel in a user-defined map
+ * \return the floating value stored for that pixel
+ * \param iMapName
+ * The name of the map
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ */
+ LIB_STROKE_EXPORT
+ float ReadMapPixelCF(const char *iMapName, int level, unsigned x, unsigned y);
+
+ // ReadCompleteViewMapPixel
+ /*! Reads a pixel in the complete view map
+ * \return the floating value stored for that pixel
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ */
+ LIB_STROKE_EXPORT
+ float ReadCompleteViewMapPixelCF(int level, unsigned x, unsigned y);
+
+ // ReadOrientedViewMapPixel
+ /*! Reads a pixel in one of the oriented view map images
+ * \return the floating value stored for that pixel
+ * \param iOrientation
+ * The number telling which orientation we want to check
+ * \param level
+ * The level of the pyramid in which we wish to read the pixel
+ * \param x
+ * The x-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ * \param y
+ * The y-coordinate of the pixel we wish to read. The origin is
+ * in the lower-left corner.
+ */
+ LIB_STROKE_EXPORT
+ float ReadDirectionalViewMapPixelCF(int iOrientation, int level, unsigned x, unsigned y);
+
+ // DEBUG
+ LIB_STROKE_EXPORT
+ FEdge * GetSelectedFEdgeCF();
+
+} // end of namespace ContextFunctions
+
+#endif // CONTEXT_FUNCTIONS_HPP
+
diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp
new file mode 100755
index 00000000000..f7b255c3ef4
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Curve.cpp
@@ -0,0 +1,818 @@
+
+//
+// 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 "Curve.h"
+#include "CurveIterators.h"
+#include "CurveAdvancedIterators.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* CurvePoint */
+ /* */
+ /* */
+ /**********************************/
+
+CurvePoint::CurvePoint()
+{
+ __A=0;
+ __B=0;
+ _t2d=0;
+}
+
+CurvePoint::CurvePoint(SVertex *iA, SVertex *iB, float t)
+{
+ __A=iA;
+ __B=iB;
+ _t2d=t;
+ if((iA == 0) && (t == 1.f))
+ {
+ _Point2d=__B->point2d();
+ _Point3d=__B->point3d();
+ }
+ else if((iB == 0) && (t == 0.f))
+ {
+ _Point2d=__A->point2d();
+ _Point3d=__A->point3d();
+ }
+ else
+ {
+ _Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d());
+ _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d());
+ }
+}
+
+CurvePoint::CurvePoint(CurvePoint *iA, CurvePoint *iB, float t3)
+{
+ float t1=iA->t2d();
+ float t2=iB->t2d();
+ if((iA->A() == iB->A()) && (iA->B() == iB->B()) && (iA->A() != 0) && (iA->B() != 0) && (iB->A() != 0) && (iB->B() != 0))
+ {
+ __A=iA->A();
+ __B=iB->B();
+ _t2d=t1+t2*t3-t1*t3;
+ }
+ else if((iA->B() == 0) && (iB->B() == 0))
+ {
+ __A = iA->A();
+ __B = iB->A();
+ _t2d = t3;
+ }
+ else if((iA->t2d() == 0) && (iB->t2d() == 0))
+ {
+ __A = iA->A();
+ __B = iB->A();
+ _t2d = t3;
+ }
+ else if(iA->A() == iB->A()){
+ if(iA->t2d() == 0){
+ __A = iB->A();
+ __B = iB->B();
+ _t2d = t3;
+ }else if(iB->t2d() == 0){
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t3;
+ }
+ }else if(iA->B() == iB->B()){
+ if(iA->t2d() == 1){
+ __A = iB->A();
+ __B = iB->B();
+ _t2d = t3;
+ }else if(iB->t2d() == 1){
+ __A = iA->A();
+ __B = iA->B();
+ _t2d = t3;
+ }
+ }
+ else if(iA->B() == iB->A())
+ {
+ if((iA->t2d() != 1.f) && (iB->t2d() == 0.f))
+ {
+ __A = iA->A();
+ __B = iA->B();
+ _t2d=t1+t3-t1*t3;
+ //_t2d = t3;
+ }
+ else if((iA->t2d() == 1.f) && (iB->t2d() != 0.f))
+ {
+ __A = iB->A();
+ __B = iB->B();
+ //_t2d = t3;
+ _t2d=t2*t3;
+ }
+
+ }
+ //_Point2d=__A->point2d()+_t2d*(__B->point2d()-__A->point2d());
+ //_Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d());
+
+ _Point2d= iA->point2d()+t3*(iB->point2d()-iA->point2d());
+ _Point3d=__A->point3d()+_t2d*(__B->point3d()-__A->point3d());
+}
+
+CurvePoint::CurvePoint(const CurvePoint& iBrother)
+{
+ __A=iBrother.__A;
+ __B=iBrother.__B;
+ _t2d=iBrother._t2d;
+ _Point2d=iBrother._Point2d;
+ _Point3d=iBrother._Point3d;
+}
+
+CurvePoint& CurvePoint::operator=(const CurvePoint& iBrother)
+{
+ __A=iBrother.__A;
+ __B=iBrother.__B;
+ _t2d=iBrother._t2d;
+ _Point2d=iBrother._Point2d;
+ _Point3d=iBrother._Point3d;
+ return *this;
+}
+
+
+FEdge *CurvePoint::fedge()
+{
+ if(getNature() & Nature::T_VERTEX)
+ return 0;
+ return __A->fedge();
+}
+
+
+FEdge* CurvePoint::getFEdge(Interface0D& inter)
+{
+ CurvePoint* iVertexB = dynamic_cast<CurvePoint*>(&inter);
+ if (!iVertexB)
+ return 0;
+ if(((__A == iVertexB->__A) && (__B == iVertexB->__B))
+ ||
+ ((__A == iVertexB->__B) && (__B == iVertexB->__A)))
+ return __A->getFEdge(*__B);
+ else if(__B == 0)
+ {
+ if(iVertexB->__B == 0)
+ return __A->getFEdge(*(iVertexB->__A));
+ else if(iVertexB->__A == __A)
+ return __A->getFEdge(*(iVertexB->__B));
+ else if(iVertexB->__B == __A)
+ return __A->getFEdge(*(iVertexB->__A));
+ }
+ else if(iVertexB->__B == 0)
+ {
+ if(iVertexB->__A == __A)
+ return __B->getFEdge(*(iVertexB->__A));
+ else if(iVertexB->__A == __B)
+ return __A->getFEdge(*(iVertexB->__A));
+ }
+ else if(__B == iVertexB->__A)
+ {
+ if((_t2d != 1) && (iVertexB->_t2d == 0))
+ return __A->getFEdge(*__B);
+ if((_t2d == 1) && (iVertexB->_t2d != 0))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ }
+ else if(__B == iVertexB->__B)
+ {
+ if((_t2d != 1) && (iVertexB->_t2d == 1))
+ return __A->getFEdge(*__B);
+ if((_t2d == 1) && (iVertexB->_t2d != 1))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ }
+ else if(__A == iVertexB->__A)
+ {
+ if((_t2d == 0) && (iVertexB->_t2d != 0))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ if((_t2d != 0) && (iVertexB->_t2d == 0))
+ return __A->getFEdge(*__B);
+ }
+ else if(__A == iVertexB->__B)
+ {
+ if((_t2d == 0) && (iVertexB->_t2d != 1))
+ return iVertexB->__A->getFEdge(*(iVertexB->__B));
+ if((_t2d != 0) && (iVertexB->_t2d == 1))
+ return __A->getFEdge(*__B);
+ }
+
+ cerr << "Warning: you should not be there..." << endl;
+
+ return 0;
+}
+
+
+ Vec3r CurvePoint::normal() const
+{
+ if(__B == 0)
+ return __A->normal();
+ if(__A == 0)
+ return __B->normal();
+ Vec3r Na = __A->normal();
+ if(Exception::getException())
+ Na = Vec3r(0,0,0);
+ Vec3r Nb = __B->normal();
+ if(Exception::getException())
+ Nb = Vec3r(0,0,0);
+ // compute t3d:
+ real t3d = SilhouetteGeomEngine::ImageToWorldParameter(__A->getFEdge(*__B),_t2d);
+ return ((1-t3d)*Na+t3d*Nb);
+}
+
+
+ // Material CurvePoint::material() const
+ //{
+ // if(__A == 0)
+ // return __B->material();
+ // return __A->material();
+ //}
+
+
+// Id CurvePoint::shape_id() const
+// {
+// if(__A == 0)
+// return __B->shape_id();
+// return __A->shape_id();
+// }
+
+
+ const SShape * CurvePoint::shape() const
+{
+ if(__A == 0)
+ return __B->shape();
+ return __A->shape();
+}
+
+
+
+// float CurvePoint::shape_importance() const
+// {
+
+// if(__A == 0)
+
+// return __B->shape_importance();
+// return __A->shape_importance();
+// }
+
+
+ // const unsigned CurvePoint::qi() const
+ //{
+ // if(__A == 0)
+ // return __B->qi();
+ // if(__B == 0)
+ // return __A->qi();
+ // return __A->getFEdge(*__B)->qi();
+ //}
+
+
+ occluder_container::const_iterator CurvePoint::occluders_begin() const
+{
+ if(__A == 0)
+ return __B->occluders_begin();
+ if(__B == 0)
+ return __A->occluders_begin();
+ return __A->getFEdge(*__B)->occluders_begin();
+}
+
+ occluder_container::const_iterator CurvePoint::occluders_end() const
+{
+ if(__A == 0)
+ return __B->occluders_end();
+ if(__B == 0)
+ return __A->occluders_end();
+ return __A->getFEdge(*__B)->occluders_end();
+}
+
+ bool CurvePoint::occluders_empty() const
+{
+ if(__A == 0)
+ return __B->occluders_empty();
+ if(__B == 0)
+ return __A->occluders_empty();
+ return __A->getFEdge(*__B)->occluders_empty();
+}
+
+ int CurvePoint::occluders_size() const
+{
+ if(__A == 0)
+ return __B->occluders_size();
+ if(__B == 0)
+ return __A->occluders_size();
+ return __A->getFEdge(*__B)->occluders_size();
+}
+
+ const SShape * CurvePoint::occluded_shape() const
+{
+ if(__A == 0)
+ return __B->occluded_shape();
+ if(__B == 0)
+ return __A->occluded_shape();
+ return __A->getFEdge(*__B)->occluded_shape();
+}
+
+ const Polygon3r& CurvePoint::occludee() const
+{
+ if(__A == 0)
+ return __B->occludee();
+ if(__B == 0)
+ return __A->occludee();
+ return __A->getFEdge(*__B)->occludee();
+}
+
+ const bool CurvePoint::occludee_empty() const
+{
+ if(__A == 0)
+ return __B->occludee_empty();
+ if(__B == 0)
+ return __A->occludee_empty();
+ return __A->getFEdge(*__B)->occludee_empty();
+}
+
+ real CurvePoint::z_discontinuity() const
+{
+ if(__A == 0)
+ return __B->z_discontinuity();
+ if(__B == 0)
+ return __A->z_discontinuity();
+ if(__A->getFEdge(*__B) == 0)
+ return 0.0;
+
+ return __A->getFEdge(*__B)->z_discontinuity();
+}
+//
+// float CurvePoint::local_average_depth() const
+//{
+// return local_average_depth_function<CurvePoint >(this);
+//}
+//
+// float CurvePoint::local_depth_variance() const
+//{
+// return local_depth_variance_function<CurvePoint >(this);
+//}
+//
+// real CurvePoint::local_average_density(float sigma) const
+//{
+// //return local_average_density<CurvePoint >(this);
+//
+// return density_function<CurvePoint >(this);
+//}
+// Vec3r shaded_color() const ;
+//
+// Vec3r CurvePoint::orientation2d() const
+// {
+// if(__A == 0)
+// return __B->orientation2d();
+// if(__B == 0)
+// return __A->orientation2d();
+// return __B->point2d()-__A->point2d();
+// }
+//
+// Vec3r CurvePoint::orientation3d() const
+// {
+// if(__A == 0)
+// return __B->orientation3d();
+// if(__B == 0)
+// return __A->orientation3d();
+// return __B->point3d()-__A->point3d();
+// }
+
+// real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);}
+//
+// Vec3r CurvePoint::curvature2d_as_vector() const
+//{
+// // Vec3r edgeA = (_FEdges[0])->orientation2d().normalize();
+// // Vec3r edgeB = (_FEdges[1])->orientation2d().normalize();
+// // return edgeA+edgeB;
+// //
+// if(__A == 0)
+// return __B->curvature2d_as_vector();
+// if(__B == 0)
+// return __A->curvature2d_as_vector();
+// return ((1-_t2d)*__A->curvature2d_as_vector()+_t2d*__B->curvature2d_as_vector());
+//}
+//
+// real CurvePoint::curvature2d_as_angle() const
+//{
+// // Vec3r edgeA = (_FEdges[0])->orientation2d();
+// // Vec3r edgeB = (_FEdges[1])->orientation2d();
+// // Vec2d N1(-edgeA.y(), edgeA.x());N1.normalize();
+// // Vec2d N2(-edgeB.y(), edgeB.x());N2.normalize();
+// // return acos((N1*N2));
+//
+// if(__A == 0)
+// return __B->curvature2d_as_angle();
+// if(__B == 0)
+// return __A->curvature2d_as_angle();
+// return ((1-_t2d)*__A->curvature2d_as_angle()+_t2d*__B->curvature2d_as_angle());
+//}
+
+
+real CurvePoint::curvatureFredo() const
+{
+ if(__A == 0)
+ return __B->curvatureFredo();
+ if(__B == 0)
+ return __A->curvatureFredo();
+ return ((1-_t2d)*__A->curvatureFredo()+_t2d*__B->curvatureFredo());
+}
+
+Vec2d CurvePoint::directionFredo () const
+{
+ if(__A == 0)
+ return __B->directionFredo();
+ if(__B == 0)
+ return __A->directionFredo();
+ return ((1-_t2d)*__A->directionFredo()+_t2d*__B->directionFredo());
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* Curve */
+ /* */
+ /* */
+ /**********************************/
+
+/* for functions */
+
+
+Curve::~Curve()
+{
+ if(!_Vertices.empty())
+ {
+ for(vertex_container::iterator it=_Vertices.begin(), itend =_Vertices.end();
+ it!=itend;
+ ++it)
+ {
+ delete (*it);
+ }
+ _Vertices.clear();
+ }
+}
+
+/*! iterators access */
+Curve::point_iterator Curve::points_begin(float step)
+{
+ vertex_container::iterator second = _Vertices.begin();++second;
+ return point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f);
+ //return point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f);
+}
+Curve::const_point_iterator Curve::points_begin(float step) const
+{
+ vertex_container::const_iterator second = _Vertices.begin();++second;
+ return const_point_iterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), _nSegments, step, 0.f, 0.f);
+ //return const_point_iterator(_Vertices.begin(), second, _nSegments, step, 0.f, 0.f);
+}
+Curve::point_iterator Curve::points_end(float step)
+{
+ return point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+ //return point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+}
+Curve::const_point_iterator Curve::points_end(float step) const
+{
+ return const_point_iterator(_Vertices.end(), _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+ //return const_point_iterator(_Vertices.end(), _Vertices.end(), _nSegments, step, 1.f, _Length);
+}
+
+// Adavnced Iterators access
+Curve::point_iterator Curve::vertices_begin(){return points_begin(0);}
+Curve::const_point_iterator Curve::vertices_begin() const {return points_begin(0);}
+Curve::point_iterator Curve::vertices_end(){return points_end(0);}
+Curve::const_point_iterator Curve::vertices_end() const {return points_end(0);}
+
+// specialized iterators access
+CurveInternal::CurvePointIterator Curve::curvePointsBegin(float t){
+ vertex_container::iterator second = _Vertices.begin();++second;
+ return CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f);
+}
+
+CurveInternal::CurvePointIterator Curve::curvePointsEnd(float t){
+ vertex_container::iterator last = _Vertices.end();--last;
+ return CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length);
+}
+
+CurveInternal::CurvePointIterator Curve::curveVerticesBegin(){
+ return curvePointsBegin(0);
+}
+
+CurveInternal::CurvePointIterator Curve::curveVerticesEnd(){
+ return curvePointsEnd(0);
+}
+
+Interface0DIterator Curve::pointsBegin(float t){
+ vertex_container::iterator second = _Vertices.begin();++second;
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(_Vertices.begin(), second, _Vertices.begin(), _Vertices.end(), 0, _nSegments, _Length, t, 0.f, 0.f));
+ return ret;
+}
+
+Interface0DIterator Curve::pointsEnd(float t){
+ vertex_container::iterator last = _Vertices.end();--last;
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(last, _Vertices.end(), _Vertices.begin(), _Vertices.end(), _nSegments, _nSegments, _Length, t, 0.f, _Length));
+ return ret;
+}
+
+Interface0DIterator Curve::verticesBegin(){
+ return pointsBegin(0);
+}
+
+Interface0DIterator Curve::verticesEnd(){
+ return pointsEnd(0);
+}
+
+
+// Vec3r shaded_color(int iCombination = 0) const ;
+//
+// Vec3r Curve::orientation2d(point_iterator it) const
+//{
+// return (*it)->orientation2d();
+//}
+/* template <class BaseVertex> */
+/* Vec3r Curve::orientation2d(int iCombination) const */
+/* { */
+/* return edge_orientation2d_function<Curve >(this, iCombination); */
+/* } */
+//
+// Vec3r Curve::orientation3d(point_iterator it) const
+//{
+// return (*it)->orientation3d();
+//}
+/* */
+/* Vec3r Curve::orientation3d(int iCombination) const */
+/* { */
+/* return edge_orientation3d_function<Curve >(this, iCombination); */
+/* } */
+// real curvature2d(point_iterator it) const {return (*it)->curvature2d();}
+// real curvature2d(int iCombination = 0) const ;
+
+// Material Curve::material() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const Material& mat = (*v)->material();
+// for(;v!=vend;++v)
+// {
+// if((*v)->material() != mat)
+// Exception::raiseException();
+// }
+// return mat;
+//}
+
+// int Curve::qi() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// int qi_= (*v)->qi();
+// for(;v!=vend;++v)
+// {
+// if((*v)->qi() != qi_)
+// Exception::raiseException();
+// }
+// return qi_;
+//}
+// occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();}
+// occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();}
+
+//int Curve::occluders_size() const
+//{
+// return qi();
+//}
+
+// bool Curve::occluders_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occluders_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluders_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+// const Polygon3r& occludee() const {return *(_FEdgeA->aFace());}
+
+// const SShape * Curve::occluded_shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->occluded_shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluded_shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+
+
+// const bool Curve::occludee_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occludee_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occludee_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+/* */
+/* real Curve::z_discontinuity(int iCombination) const */
+/* { */
+/* return z_discontinuity_edge_function<Curve >(this, iCombination); */
+/* } */
+
+// int Curve::shape_id() const
+// {
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// Id id = (*v)->shape_id();
+// for(;v!=vend;++v)
+// {
+// if((*v)->shape_id() != id)
+// Exception::raiseException();
+// }
+// return id.first;
+// }
+
+
+// const SShape * Curve::shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+
+
+// occluder_container::const_iterator Curve::occluders_begin() const
+//{
+// const_vertex_iterator v=vertices_begin();
+// return (*v)->occluders_begin();
+//}
+//
+//
+// occluder_container::const_iterator Curve::occluders_end() const
+//{
+// const_vertex_iterator v=vertices_end();
+// return (*v)->occluders_end();
+//}
+
+/* */
+/* Vec3r Curve::curvature2d_as_vector(int iCombination) const */
+/* { */
+/* return curvature2d_as_vector_edge_function<Curve >(this, iCombination); */
+/* } */
+/* */
+/* real Curve::curvature2d_as_angle(int iCombination) const */
+/* { */
+/* return curvature2d_as_angle_edge_function<Curve >(this, iCombination); */
+/* } */
+
+/* */
+/* float Curve::shape_importance(int iCombination) const */
+/* { */
+/* return shape_importance_edge_function<Curve >(this, iCombination); */
+/* } */
+
+/* */
+/* float Curve::local_average_depth(int iCombination) const */
+/* { */
+/* return local_average_depth_edge_function<Curve >(this, iCombination); */
+/* } */
+/* */
+/* float Curve::local_depth_variance(int iCombination ) const */
+/* { */
+/* return local_depth_variance_edge_function<Curve >(this, iCombination); */
+/* // local_depth_variance_functor<Point> functor; */
+/* // float result; */
+/* // Evaluate<float, local_depth_variance_functor<Point> >(&functor, iCombination, result); */
+/* // return result; */
+/* } */
+
+/* */
+/* real Curve::local_average_density(float sigma, int iCombination ) const */
+/* { */
+/* return density_edge_function<Curve >(this, iCombination); */
+/* // density_functor<Point> functor; */
+/* // real result; */
+/* // Evaluate<real, density_functor<Point> >(&functor, iCombination, result); */
+/* // return result; */
+/* } */
+
+#define EPS_CURVA_DIR 0.01
+
+
+void Curve::computeCurvatureAndOrientation ()
+{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end(), v2, prevV, v0;
+// Vec2d p0, p1, p2;
+// Vec3r p;
+
+// p=(*v)->point2d();
+// p0=Vec2d(p[0], p[1]);
+// prevV=v; ++v;
+// p=(*v)->point2d();
+// p1=Vec2d(p[0], p[1]);
+// Vec2d prevDir(p1-p0);
+
+// for(;v!=vend;++v)
+// {
+// v2=v; ++v2;
+// if (v2==vend) break;
+// Vec3r p2=(*v2)->point2d();
+
+// Vec2d BA=p0-p1;
+// Vec2d BC=p2-p1;
+// real lba=BA.norm(), lbc=BC.norm();
+// BA.normalizeSafe();
+// BC.normalizeSafe();
+// Vec2d normalCurvature=BA+BC;
+// Vec2d dir=Vec2d(BC-BA);
+// Vec2d normal=Vec2d(-dir[1], dir[0]);
+
+// normal.normalizeSafe();
+// real curvature=normalCurvature*normal;
+// if (lba+lbc > MY_EPSILON)
+// curvature/=(0.5*lba+lbc);
+// if (dir.norm() < MY_EPSILON)
+// dir=0.1*prevDir;
+// (*v)->setCurvatureFredo(curvature);
+// (*v)->setDirectionFredo(dir);
+
+// prevV=v; p0=p1; p1=p2; prevDir=dir; prevDir.normalize();
+// }
+// (*v)->setCurvatureFredo((*prevV)->curvatureFredo());
+// (*v)->setDirectionFredo((*v)->point2d()-(*prevV)->point2d());
+// v0=vertices_begin(); v2=v0; ++v2;
+// (*v0)->setCurvatureFredo((*v2)->curvatureFredo());
+// (*v0)->setDirectionFredo((*v2)->point2d()-(*v0)->point2d());
+
+// //closed curve case one day...
+
+// //
+// return;
+
+// //numerical degeneracy verification.. we'll see later
+// const_vertex_iterator vLastReliable=vertices_begin();
+
+// v=vertices_begin();
+// p=(*v)->point2d();
+// p0=Vec2d(p[0], p[1]);
+// prevV=v; ++v;
+// p=(*v)->point2d();
+// p1=Vec2d(p[0], p[1]);
+// bool isReliable=false;
+// if ((p1-p0).norm>EPS_CURVA)
+// {
+// vLastReliable=v;
+// isReliable=true;
+// }
+
+// for(;v!=vend;++v)
+// {
+// v2=v; ++v2;
+// if (v2==vend) break;
+// Vec3r p2=(*v2)->point2d();
+
+// Vec2d BA=p0-p1;
+// Vec2d BC=p2-p1;
+// real lba=BA.norm(), lbc=BC.norm();
+
+// if ((lba+lbc)<EPS_CURVA)
+// {
+// isReliable=false;
+// cerr<<"/";
+// }
+// else
+// {
+// if (!isReliable)//previous points were not reliable
+// {
+// const_vertex_iterator vfix=vLastReliable;
+// vfix++;
+// for (; vfix!=v; ++vfix)
+// {
+// (*vfix)->setCurvatureFredo((*v)->curvatureFredo());
+// (*vfix)->setDirectionFredo((*v)->directionFredo());
+// }
+// }
+// isReliable=true;
+// vLastReliable=v;
+// }
+// prevV=v; p0=p1; p1=p2;
+// }
+
+}
diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h
new file mode 100755
index 00000000000..60bc9815cb4
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Curve.h
@@ -0,0 +1,467 @@
+//
+// Filename : Curve.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define a container for curves
+// Date of creation : 11/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 CURVE_H
+# define CURVE_H
+
+# include "../view_map/Silhouette.h"
+# include <deque>
+# include "../system/BaseIterator.h"
+# include "../geometry/Geom.h"
+//# include "../scene_graph/FrsMaterial.h"
+# include "../view_map/SilhouetteGeomEngine.h"
+# include "../view_map/Interface0D.h"
+# include "../view_map/Interface1D.h"
+
+using namespace std;
+using namespace Geometry;
+
+ /**********************************/
+ /* */
+ /* */
+ /* CurvePoint */
+ /* */
+ /* */
+ /**********************************/
+
+/*! Class to represent a point of a curve.
+ * A CurvePoint can be any point of a 1D curve
+ * (it doesn't have to be a vertex of the curve).
+ * Any Interface1D is built upon ViewEdges, themselves
+ * built upon FEdges. Therefore, a curve is basically
+ * a polyline made of a list SVertex.
+ * Thus, a CurvePoint is built by lineraly interpolating
+ * two SVertex.
+ * CurvePoint can be used as virtual points while
+ * querying 0D information along a curve at a given resolution.
+ */
+class LIB_STROKE_EXPORT CurvePoint : public Interface0D
+{
+public: // Implementation of Interface0D
+ /*! Returns the string "CurvePoint"*/
+ virtual string getExactTypeName() const {
+ return "CurvePoint";
+ }
+
+ // Data access methods
+ /*! Returns the 3D X coordinate of the point */
+ virtual real getX() const {
+ return _Point3d.x();
+ }
+ /*! Returns the 3D Y coordinate of the point */
+ virtual real getY() const {
+ return _Point3d.y();
+ }
+ /*! Returns the 3D Z coordinate of the point */
+ 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 point */
+ virtual real getProjectedX() const {
+ return _Point2d.x();
+ }
+ /*! Returns the projected 3D Y coordinate of the point */
+ virtual real getProjectedY() const {
+ return _Point2d.y();
+ }
+ /*! Returns the projected 3D Z coordinate of the point */
+ virtual real getProjectedZ() const {
+ return _Point2d.z();
+ }
+ /*! Returns the 2D point. */
+ virtual Vec2f getPoint2D() const {
+ return Vec2f((float)_Point2d.x(),(float)_Point2d.y());
+ }
+
+ virtual FEdge* getFEdge(Interface0D& inter);
+ /*! Returns the CurvePoint's Id */
+ virtual Id getId() const {
+ Id id;
+ if(_t2d == 0)
+ return __A->getId();
+ else if(_t2d == 1)
+ return __B->getId();
+ return id;
+ }
+ /*! Returns the CurvePoint's Nature */
+ virtual Nature::VertexNature getNature() const {
+ Nature::VertexNature nature = Nature::POINT;
+ if(_t2d == 0)
+ nature |= __A->getNature();
+ else if(_t2d == 1)
+ nature |= __B->getNature();
+ return nature;
+ }
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ if(_t2d == 0)
+ return __A;
+ else if(_t2d == 1)
+ return __B;
+ return Interface0D::castToSVertex();
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ if(_t2d == 0)
+ return __A->castToViewVertex();
+ else if(_t2d == 1)
+ return __B->castToViewVertex();
+ return Interface0D::castToViewVertex();
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ if(_t2d == 0)
+ return __A->castToNonTVertex();
+ else if(_t2d == 1)
+ return __B->castToNonTVertex();
+ return Interface0D::castToNonTVertex();
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ if(_t2d == 0)
+ return __A->castToTVertex();
+ else if(_t2d == 1)
+ return __B->castToTVertex();
+ return Interface0D::castToTVertex();
+ }
+public:
+ typedef SVertex vertex_type;
+protected:
+ SVertex *__A;
+ SVertex *__B;
+ float _t2d;
+ //float _t3d;
+ Vec3r _Point2d;
+ Vec3r _Point3d;
+public:
+ /*! Defult Constructor. */
+ CurvePoint();
+ /*! Builds a CurvePoint from two SVertex and an interpolation
+ * parameter.
+ * \param iA
+ * The first SVertex
+ * \param iB
+ * The second SVertex
+ * \param t2d
+ * A 2D interpolation parameter
+ * used to linearly interpolate \a iA and \a iB
+ */
+ CurvePoint(SVertex *iA, SVertex *iB, float t2d) ;
+ /*! Builds a CurvePoint from two CurvePoint and an interpolation parameter.
+ * \param iA
+ * The first CurvePoint
+ * \param iB
+ * The second CurvePoint
+ * \param t2d
+ * The 2D interpolation parameter used
+ * to linearly interpolate \a iA and \a iB.
+ */
+ CurvePoint(CurvePoint *iA, CurvePoint *iB, float t2d) ;
+ // CurvePoint(SVertex *iA, SVertex *iB, float t2d, float t3d) ;
+ /*! Copy Constructor. */
+ CurvePoint(const CurvePoint& iBrother) ;
+ /*! Operator = */
+ CurvePoint& operator=(const CurvePoint& iBrother) ;
+ /*! Destructor */
+ virtual ~CurvePoint() {}
+ /*! Operator == */
+ bool operator==(const CurvePoint& b){
+ return ((__A==b.__A) && (__B==b.__B) && (_t2d==b._t2d));
+ }
+
+ /* accessors */
+ /*! Returns the first SVertex upon which
+ * the CurvePoint is built. */
+ inline SVertex * A() {return __A;}
+ /*! Returns the second SVertex upon which
+ * the CurvePoint is built. */
+ inline SVertex * B() {return __B;}
+ /*! Returns the interpolation parameter. */
+ inline float t2d() const {return _t2d;}
+ //inline const float t3d() const {return _t3d;}
+
+ /* modifiers */
+ /*! Sets the first SVertex upon which to build
+ * the CurvePoint.
+ */
+ inline void setA(SVertex *iA) {__A = iA;}
+ /*! Sets the second SVertex upon which to build
+ * the CurvePoint.
+ */
+ inline void setB(SVertex *iB) {__B = iB;}
+ /*! Sets the 2D interpolation parameter to use.
+ */
+ inline void setT2d(float t) {_t2d = t;}
+ //inline void SetT3d(float t) {_t3d = t;}
+
+ /* Information access interface */
+
+ FEdge *fedge() ;
+ inline const Vec3r& point2d() const {return _Point2d;}
+ inline const Vec3r& point3d() const {return _Point3d;}
+ Vec3r normal() const ;
+ //FrsMaterial material() const ;
+ // Id shape_id() const ;
+ const SShape * shape() const ;
+ // float shape_importance() const ;
+
+ //const unsigned 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 ;
+ // float local_average_depth() const ;
+ // float local_depth_variance() const ;
+ // real local_average_density(float sigma = 2.3f) const ;
+ // Vec3r shaded_color() const ;
+// Vec3r orientation2d() const ;
+// Vec3r orientation3d() const ;
+ // // real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);}
+ // Vec3r curvature2d_as_vector() const ;
+ // /*! angle in radians */
+ // real curvature2d_as_angle() const ;
+
+ real curvatureFredo () const;
+ Vec2d directionFredo () const;
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* Curve */
+ /* */
+ /* */
+ /**********************************/
+
+namespace CurveInternal {
+ class CurvePoint_const_traits;
+ class CurvePoint_nonconst_traits;
+ template<class Traits> class __point_iterator;
+ class CurvePointIterator;
+} // end of namespace CurveInternal
+
+/*! Base class for curves made of CurvePoints.
+ * SVertex is the type of the initial curve vertices.
+ * A Chain is a specialization of a Curve.
+ */
+class LIB_STROKE_EXPORT Curve : public Interface1D
+{
+public:
+ typedef CurvePoint Vertex;
+ typedef CurvePoint Point;
+ typedef Point point_type;
+ typedef Vertex vertex_type;
+ typedef deque<Vertex*> vertex_container;
+
+ /* Iterator to iterate over a vertex edges */
+
+ typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_nonconst_traits > point_iterator;
+ typedef CurveInternal::__point_iterator<CurveInternal::CurvePoint_const_traits > const_point_iterator;
+ typedef point_iterator vertex_iterator ;
+ typedef const_point_iterator const_vertex_iterator ;
+
+protected:
+ vertex_container _Vertices;
+ double _Length;
+ Id _Id;
+ unsigned _nSegments; // number of segments
+
+public:
+ /*! Default Constructor. */
+ Curve() {_Length = 0;_Id = 0;_nSegments=0;}
+ /*! Builds a Curve from its id */
+ Curve(const Id& id) {_Length = 0;_Id = id;_nSegments=0;}
+ /*! Copy Constructor. */
+ Curve(const Curve& iBrother) {_Length = iBrother._Length;_Vertices = iBrother._Vertices;_Id=iBrother._Id;_nSegments=0;}
+ /*! Destructor. */
+ virtual ~Curve() ;
+ /*! Returns the string "Curve" */
+ virtual string getExactTypeName() const {
+ return "Curve";
+ }
+
+ /*
+ fredo's curvature storage
+ */
+ void computeCurvatureAndOrientation ();
+
+ /*! Adds a single vertex (CurvePoint) at the end of the Curve */
+ inline void push_vertex_back(Vertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex * new_vertex = new Vertex(*iVertex);
+ _Vertices.push_back(new_vertex);
+ }
+ /*! Adds a single vertex (SVertex) at the end of the Curve */
+ inline void push_vertex_back(SVertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.back()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(iVertex, 0,0);
+ _Vertices.push_back(new_vertex);
+ }
+ /*! Adds a single vertex (CurvePoint) at the front of the Curve */
+ inline void push_vertex_front(Vertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex * new_vertex = new Vertex(*iVertex);
+ _Vertices.push_front(new_vertex);
+ }
+ /*! Adds a single vertex (SVertex) at the front of the Curve */
+ inline void push_vertex_front(SVertex *iVertex)
+ {
+ if(!_Vertices.empty())
+ {
+ Vec3r vec_tmp(iVertex->point2d() - _Vertices.front()->point2d());
+ _Length += vec_tmp.norm();
+ ++_nSegments;
+ }
+ Vertex *new_vertex = new Vertex(iVertex, 0,0);
+ _Vertices.push_front(new_vertex);
+ }
+ /*! Returns true is the Curve doesn't have any Vertex yet. */
+ inline bool empty() const {return _Vertices.empty();}
+ /*! Returns the 2D length of the Curve.*/
+ inline real getLength2D() const {return _Length;}
+ /*! Returns the Id of the 1D element .*/
+ virtual Id getId() const {
+ return _Id;
+ }
+ /*! Returns the number of segments in the
+ * oplyline constituing the Curve.
+ */
+ inline unsigned int nSegments() const {return _nSegments;}
+
+ inline void setId(const Id& id){_Id = id;}
+ /* Information access interface */
+
+
+ //inline Vec3r shaded_color(int iCombination = 0) const ;
+ // inline Vec3r orientation2d(point_iterator it) const ;
+ //Vec3r orientation2d(int iCombination = 0) const ;
+ // Vec3r orientation3d(point_iterator it) const ;
+ //Vec3r orientation3d(int iCombination = 0) const ;
+ // real curvature2d(point_iterator it) const {return (*it)->curvature2d();}
+ // real curvature2d(int iCombination = 0) const ;
+ //FrsMaterial material() const ;
+ //int qi() const ;
+ // occluder_container::const_iterator occluders_begin() const ;
+ // occluder_container::const_iterator occluders_end() const ;
+ //int occluders_size() const;
+ //bool occluders_empty() const ;
+ // const Polygon3r& occludee() const {return *(_FEdgeA->aFace());}
+ //const SShape * occluded_shape() const;
+ //const bool occludee_empty() const ;
+ //real z_discontinuity(int iCombination = 0) const ;
+ // int shape_id() const ;
+ //const SShape * shape() const ;
+ //float shape_importance(int iCombination=0) const ;
+ //float local_average_depth(int iCombination = 0) const;
+ //float local_depth_variance(int iCombination = 0) const ;
+ //real local_average_density(float sigma = 2.3f, int iCombination = 0) const ;
+ //Vec3r curvature2d_as_vector(int iCombination=0) const ;
+ /*! angle in radians */
+ //real curvature2d_as_angle(int iCombination=0) const ;
+
+ /* advanced iterators access */
+ point_iterator points_begin(float step = 0);
+ const_point_iterator points_begin(float step = 0) const;
+ point_iterator points_end(float step = 0);
+ const_point_iterator points_end(float step = 0) const;
+
+ // methods given for convenience */
+ point_iterator vertices_begin();
+ const_point_iterator vertices_begin() const;
+ point_iterator vertices_end();
+ const_point_iterator vertices_end() const;
+
+ // specialized iterators access
+ CurveInternal::CurvePointIterator curvePointsBegin(float t=0.f);
+ CurveInternal::CurvePointIterator curvePointsEnd(float t=0.f);
+
+ CurveInternal::CurvePointIterator curveVerticesBegin();
+ CurveInternal::CurvePointIterator curveVerticesEnd();
+
+ // Iterators access
+ /*! Returns an Interface0DIterator pointing onto
+ * the first vertex of the Curve and that can iterate
+ * over the \a vertices of the Curve.
+ */
+ virtual Interface0DIterator verticesBegin();
+ /*! Returns an Interface0DIterator pointing after
+ * the last vertex of the Curve and that can iterate
+ * over the \a vertices of the Curve.
+ */
+ virtual Interface0DIterator verticesEnd();
+ /*! Returns an Interface0DIterator pointing onto
+ * the first point of the Curve and that can iterate
+ * over the \a points of the Curve at any resolution.
+ * At each iteration a virtual temporary CurvePoint
+ * is created.
+ */
+ virtual Interface0DIterator pointsBegin(float t=0.f);
+ /*! Returns an Interface0DIterator pointing after
+ * the last point of the Curve and that can iterate
+ * over the \a points of the Curve at any resolution.
+ * At each iteration a virtual temporary CurvePoint
+ * is created.
+ */
+ virtual Interface0DIterator pointsEnd(float t=0.f);
+};
+
+
+
+#endif
diff --git a/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h
new file mode 100755
index 00000000000..dfc9f2719f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/CurveAdvancedIterators.h
@@ -0,0 +1,378 @@
+//
+// Filename : CurveAdvancedIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Curve
+// Can't be used in python
+// Date of creation : 01/08/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 ADVANCEDCURVEITERATORS_H
+# define ADVANCEDCURVEITERATORS_H
+
+# include "Stroke.h"
+
+namespace CurveInternal {
+
+ class CurvePoint_const_traits : public Const_traits<CurvePoint*> {
+ public:
+ typedef deque<CurvePoint*> vertex_container;
+ typedef vertex_container::const_iterator vertex_container_iterator;
+ typedef SVertex vertex_type;
+ };
+
+ class CurvePoint_nonconst_traits : public Nonconst_traits<CurvePoint*> {
+ public:
+ typedef deque<CurvePoint*> vertex_container;
+ typedef vertex_container::iterator vertex_container_iterator ;
+ typedef SVertex vertex_type;
+ };
+
+ /**********************************/
+ /* */
+ /* */
+ /* CurvePoint Iterator */
+ /* */
+ /* */
+ /**********************************/
+
+
+ /*! iterator on a curve. Allows an iterating outside
+ * initial vertices. A CurvePoint is instanciated an returned
+ * when the iterator is dereferenced.
+ */
+
+ template<class Traits>
+ class __point_iterator : public IteratorBase<Traits, BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef __point_iterator <Traits> Self;
+ typedef typename Traits::vertex_container_iterator vertex_container_iterator;
+ typedef typename Traits::vertex_type vertex_type;
+ typedef CurvePoint Point;
+ typedef Point point_type;
+
+ typedef __point_iterator<CurvePoint_nonconst_traits > iterator;
+ typedef __point_iterator<CurvePoint_const_traits > const_iterator;
+
+ // public:
+ // typedef Vertex vertex_type ;
+ // typedef vertex_container_iterator vertex_iterator_type;
+ // typedef CurvePoint<Vertex> Point;
+ // typedef Point point_type;
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ //# if defined(__GNUC__) && (__GNUC__ < 3)
+ // typedef bidirectional_iterator<CurvePoint<Vertex>,ptrdiff_t> bidirectional_point_iterator;
+ //# else
+ // typedef iterator<bidirectional_iterator_tag, CurvePoint<Vertex>,ptrdiff_t> bidirectional_point_iterator;
+ //# endif
+ friend class Curve;
+ //friend class Curve::vertex_iterator;
+ //friend class __point_iterator<CurvePoint_nonconst_traits >;
+ //friend class iterator;
+ //protected:
+ public:
+ float _CurvilinearLength;
+ float _step;
+ vertex_container_iterator __A;
+ vertex_container_iterator __B;
+ vertex_container_iterator _begin;
+ vertex_container_iterator _end;
+ int _n;
+ int _currentn;
+ float _t;
+ mutable Point *_Point;
+
+ public:
+
+ public:
+ inline __point_iterator(float step = 0.f)
+ : parent_class()
+ {
+ _step = step;
+ _CurvilinearLength = 0.f;
+ _t = 0.f;
+ _Point = 0;
+ _n = 0;
+ _currentn = 0;
+ }
+
+ inline __point_iterator(const iterator& iBrother)
+ : parent_class()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if(iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ }
+ inline __point_iterator(const const_iterator& iBrother)
+ : parent_class()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if(iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ }
+ inline Self& operator=(const Self& iBrother)
+ {
+ //((bidirectional_point_iterator*)this)->operator=(iBrother);
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ if(iBrother._Point == 0)
+ _Point = 0;
+ else
+ _Point = new Point(*(iBrother._Point));
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ return *this;
+ }
+ virtual ~__point_iterator()
+ {
+ if(_Point != 0)
+ delete _Point;
+ }
+ //protected://FIXME
+ public:
+ inline __point_iterator(vertex_container_iterator iA,
+ vertex_container_iterator iB,
+ vertex_container_iterator ibegin,
+ vertex_container_iterator iend,
+ int currentn,
+ int n,
+ float step, float t=0.f, float iCurvilinearLength = 0.f)
+ : parent_class()
+ {
+ __A = iA;
+ __B = iB;
+ _begin = ibegin;
+ _end = iend;
+ _CurvilinearLength = iCurvilinearLength;
+ _step = step;
+ _t = t;
+ _Point = 0;
+ _n = n;
+ _currentn = currentn;
+ }
+
+ public:
+
+ // 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 ((__A!=b.__A) || (__B!=b.__B) || (_t != b._t));
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual typename Traits::reference operator*() const
+ {
+ if(_Point != 0)
+ {
+ delete _Point;
+ _Point = 0;
+ }
+ if((_currentn < 0) || (_currentn >= _n))
+ return _Point; // 0 in this case
+ return (_Point = new Point(*__A,*__B,_t));
+ }
+ virtual typename Traits::pointer operator->() const { return &(operator*());}
+
+ public:
+ virtual bool begin() const
+ {
+ if((__A == _begin) && (_t < (float)M_EPSILON))
+ return true;
+ return false;
+ }
+ virtual bool end() const
+ {
+ if((__B == _end))
+ return true;
+ return false;
+ }
+ protected:
+ virtual void increment()
+ {
+ if(_Point != 0)
+ {
+ delete _Point;
+ _Point = 0;
+ }
+ if((_currentn == _n-1) && (_t == 1.f))
+ {
+ // we're setting the iterator to end
+ ++__A;
+ ++__B;
+ ++_currentn;
+ _t = 0.f;
+ return;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength += vec_tmp.norm();
+ if(_currentn == _n-1)
+ {
+ _t = 1.f;
+ return;
+ }
+ ++__B;
+ ++__A;
+ ++_currentn;
+ return;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = vec_tmp2.norm();
+
+ if(normAB > M_EPSILON)
+ {
+ _CurvilinearLength += _step;
+ _t = _t + _step/normAB;
+ }
+ else
+ _t = 1.f; // AB is a null segment, we're directly at its end
+ //if normAB ~= 0, we don't change these values
+ if(_t >= 1)
+ {
+ _CurvilinearLength -= normAB*(_t-1);
+ if(_currentn == _n-1)
+ _t=1.f;
+ else
+ {
+ _t = 0.f;
+ ++_currentn;
+ ++__A;++__B;
+ }
+ }
+ }
+ virtual void decrement()
+ {
+ if(_Point != 0)
+ {
+ delete _Point;
+ _Point = 0;
+ }
+
+ if(_t == 0.f) //we're at the beginning of the edge
+ {
+ _t = 1.f;
+ --_currentn;
+ --__A; --__B;
+ if(_currentn == _n-1)
+ return;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength -= vec_tmp.norm();
+ _t = 0;
+ return;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = vec_tmp2.norm();
+
+ if(normAB >M_EPSILON)
+ {
+ _CurvilinearLength -= _step;
+ _t = _t - _step/normAB;
+ }
+ else
+ _t = -1.f; // We just need a negative value here
+
+ // round value
+ if(fabs(_t) < (float)M_EPSILON)
+ _t = 0.0;
+ if(_t < 0)
+ {
+ if(_currentn == 0)
+ _CurvilinearLength = 0.f;
+ else
+ _CurvilinearLength += normAB*(-_t);
+ _t = 0.f;
+ }
+ }
+ };
+
+
+
+} // end of namespace StrokeInternal
+
+
+#endif // ADVANCEDCURVEITERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/CurveIterators.h b/source/blender/freestyle/intern/stroke/CurveIterators.h
new file mode 100755
index 00000000000..a45ef4bfdaf
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/CurveIterators.h
@@ -0,0 +1,299 @@
+//
+// Filename : CurveIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Curve
+// Date of creation : 01/08/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 CURVEITERATORS_H
+# define CURVEITERATORS_H
+
+#include "Stroke.h"
+#include "Curve.h"
+
+namespace CurveInternal {
+
+ /*! iterator on a curve. Allows an iterating outside
+ * initial vertices. A CurvePoint is instanciated an returned
+ * when the iterator is dereferenced.
+ */
+
+ class CurvePointIterator : public Interface0DIteratorNested
+ {
+ public:
+ friend class ::Curve;
+ public:
+ float _CurvilinearLength;
+ float _step;
+ ::Curve::vertex_container::iterator __A;
+ ::Curve::vertex_container::iterator __B;
+ ::Curve::vertex_container::iterator _begin;
+ ::Curve::vertex_container::iterator _end;
+ int _n;
+ int _currentn;
+ float _t;
+ mutable CurvePoint _Point;
+ float _CurveLength;
+
+ public:
+
+ public:
+ inline CurvePointIterator(float step = 0.f)
+ : Interface0DIteratorNested()
+ {
+ _step = step;
+ _CurvilinearLength = 0.f;
+ _t = 0.f;
+ //_Point = 0;
+ _n = 0;
+ _currentn = 0;
+ _CurveLength=0;
+ }
+
+ inline CurvePointIterator(const CurvePointIterator& iBrother)
+ : Interface0DIteratorNested()
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ _Point = iBrother._Point;
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ _CurveLength = iBrother._CurveLength;
+ }
+ inline CurvePointIterator& operator=(const CurvePointIterator& iBrother)
+ {
+ __A = iBrother.__A;
+ __B = iBrother.__B;
+ _begin = iBrother._begin;
+ _end = iBrother._end;
+ _CurvilinearLength = iBrother._CurvilinearLength;
+ _step = iBrother._step;
+ _t = iBrother._t;
+ _Point = iBrother._Point;
+ _n = iBrother._n;
+ _currentn = iBrother._currentn;
+ _CurveLength = iBrother._CurveLength;
+ return *this;
+ }
+ virtual ~CurvePointIterator()
+ {
+ }
+ protected:
+ inline CurvePointIterator(::Curve::vertex_container::iterator iA,
+ ::Curve::vertex_container::iterator iB,
+ ::Curve::vertex_container::iterator ibegin,
+ ::Curve::vertex_container::iterator iend,
+ int currentn,
+ int n,
+ float iCurveLength,
+ float step, float t=0.f, float iCurvilinearLength = 0.f)
+ : Interface0DIteratorNested()
+ {
+ __A = iA;
+ __B = iB;
+ _begin = ibegin;
+ _end = iend;
+ _CurvilinearLength = iCurvilinearLength;
+ _step = step;
+ _t = t;
+ _n = n;
+ _currentn = currentn;
+ _CurveLength = iCurveLength;
+ }
+
+ public:
+
+ virtual CurvePointIterator* copy() const {
+ return new CurvePointIterator(*this);
+ }
+
+ inline Interface0DIterator castToInterface0DIterator() const{
+ Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this));
+ return ret;
+ }
+ virtual string getExactTypeName() const {
+ return "CurvePointIterator";
+ }
+
+ // operators
+ inline CurvePointIterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+
+ inline CurvePointIterator& operator--() // operator corresponding to ++i
+ {
+ decrement();
+ return *this;
+ }
+
+ // comparibility
+ virtual bool operator==(const Interface0DIteratorNested& b) const
+ {
+ const CurvePointIterator* it_exact = dynamic_cast<const CurvePointIterator*>(&b);
+ if (!it_exact)
+ return false;
+ return ((__A==it_exact->__A) && (__B==it_exact->__B) && (_t == it_exact->_t));
+ }
+
+ // dereferencing
+ virtual CurvePoint& operator*()
+ {
+ return (_Point = CurvePoint(*__A,*__B,_t));
+ }
+ virtual CurvePoint* operator->() { return &(operator*());}
+ public:
+ virtual bool isBegin() const
+ {
+ if((__A == _begin) && (_t < (float)M_EPSILON))
+ return true;
+ return false;
+ }
+ virtual bool isEnd() const
+ {
+ if(__B == _end)
+ return true;
+ return false;
+ }
+
+// protected:
+
+ virtual int increment()
+ {
+ if((_currentn == _n-1) && (_t == 1.f))
+ {
+ // we're setting the iterator to end
+ ++__A;
+ ++__B;
+ ++_currentn;
+ _t = 0.f;
+ return 0;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength += (float)vec_tmp.norm();
+ if(_currentn == _n-1)
+ {
+ _t = 1.f;
+ return 0;
+ }
+ ++__B;
+ ++__A;
+ ++_currentn;
+ return 0;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = (float)vec_tmp2.norm();
+
+ if(normAB > M_EPSILON)
+ {
+ _CurvilinearLength += _step;
+ _t = _t + _step/normAB;
+ }
+ else
+ _t = 1.f; // AB is a null segment, we're directly at its end
+ //if normAB ~= 0, we don't change these values
+ if(_t >= 1)
+ {
+ _CurvilinearLength -= normAB*(_t-1);
+ if(_currentn == _n-1)
+ _t=1.f;
+ else
+ {
+ _t = 0.f;
+ ++_currentn;
+ ++__A;++__B;
+ }
+ }
+ return 0;
+ }
+ virtual int decrement()
+ {
+ if(_t == 0.f) //we're at the beginning of the edge
+ {
+ _t = 1.f;
+ --_currentn;
+ --__A; --__B;
+ if(_currentn == _n-1)
+ return 0;
+ }
+
+ if(0 == _step) // means we iterate over initial vertices
+ {
+ Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
+ _CurvilinearLength -= (float)vec_tmp.norm();
+ _t = 0;
+ return 0;
+ }
+
+ // compute the new position:
+ Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
+ float normAB = (float)vec_tmp2.norm();
+
+ if(normAB >M_EPSILON)
+ {
+ _CurvilinearLength -= _step;
+ _t = _t - _step/normAB;
+ }
+ else
+ _t = -1.f; // We just need a negative value here
+
+ // round value
+ if(fabs(_t) < (float)M_EPSILON)
+ _t = 0.0;
+ if(_t < 0)
+ {
+ if(_currentn == 0)
+ _CurvilinearLength = 0.f;
+ else
+ _CurvilinearLength += normAB*(-_t);
+ _t = 0.f;
+ }
+ return 0;
+ }
+
+ virtual float t() const{
+ return _CurvilinearLength;
+ }
+ virtual float u() const{
+ return _CurvilinearLength/_CurveLength;
+ }
+ };
+
+
+
+} // end of namespace StrokeInternal
+
+#endif // CURVEITERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/Modifiers.h b/source/blender/freestyle/intern/stroke/Modifiers.h
new file mode 100755
index 00000000000..21bebebc6f8
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Modifiers.h
@@ -0,0 +1,71 @@
+//
+// Filename : Modifiers.h
+// Author : Stephane Grabli
+// Purpose : modifiers...
+// Date of creation : 05/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 MODIFIERS_H
+# define MODIFIERS_H
+
+# include "TimeStamp.h"
+
+/* ----------------------------------------- *
+ * *
+ * modifiers *
+ * *
+ * ----------------------------------------- */
+/*! Base class for modifiers.
+ * Modifiers are used in the
+ * Operators in order to "mark"
+ * the processed Interface1D.
+ */
+template<class Edge>
+struct EdgeModifier : public unary_function<Edge,void>
+{
+ /*! Default construction */
+ EdgeModifier() : unary_function<Edge,void>() {}
+ /*! the () operator */
+ virtual void operator()(Edge& iEdge) {}
+};
+
+/*! Modifier that sets the time stamp
+ * of an Interface1D to the time stamp
+ * of the system.
+ */
+template<class Edge>
+struct TimestampModifier : public EdgeModifier<Edge>
+{
+ /*! Default constructor */
+ TimestampModifier() : EdgeModifier<Edge>() {}
+ /*! The () operator. */
+ virtual void operator()(Edge& iEdge)
+ {
+ TimeStamp *timestamp = TimeStamp::instance();
+ iEdge.setTimeStamp(timestamp->getTimeStamp());
+ }
+};
+
+#endif // MODIFIERS_H
diff --git a/source/blender/freestyle/intern/stroke/Module.h b/source/blender/freestyle/intern/stroke/Module.h
new file mode 100755
index 00000000000..591bb157392
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Module.h
@@ -0,0 +1,72 @@
+//
+// Filename : Module.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Set the type of the module
+// 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 MODULE_H
+# define MODULE_H
+
+# include "Canvas.h"
+# include "StyleModule.h"
+
+class Module
+{
+public:
+
+ static void setAlwaysRefresh(bool b = true) {
+ getCurrentStyleModule()->setAlwaysRefresh(b);
+ }
+
+ static void setCausal(bool b = true) {
+ getCurrentStyleModule()->setCausal(b);
+ }
+
+ static void setDrawable(bool b = true) {
+ getCurrentStyleModule()->setDrawable(b);
+ }
+
+ static bool getAlwaysRefresh() {
+ return getCurrentStyleModule()->getAlwaysRefresh();
+ }
+
+ static bool getCausal() {
+ return getCurrentStyleModule()->getCausal();
+ }
+
+ static bool getDrawable() {
+ return getCurrentStyleModule()->getDrawable();
+ }
+
+private:
+
+ static StyleModule* getCurrentStyleModule() {
+ Canvas* canvas = Canvas::getInstance();
+ return canvas->getCurrentStyleModule();
+ }
+};
+
+#endif // MODULE_H
diff --git a/source/blender/freestyle/intern/stroke/Operators.cpp b/source/blender/freestyle/intern/stroke/Operators.cpp
new file mode 100755
index 00000000000..ef1b2662998
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Operators.cpp
@@ -0,0 +1,1024 @@
+
+//
+// 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 "Operators.h"
+#include <algorithm>
+#include <stdexcept>
+#include "Canvas.h"
+#include "Stroke.h"
+
+LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_view_edges_set;
+LIB_STROKE_EXPORT Operators::I1DContainer Operators::_current_chains_set;
+LIB_STROKE_EXPORT Operators::I1DContainer* Operators::_current_set = NULL;
+LIB_STROKE_EXPORT Operators::StrokesContainer Operators::_current_strokes_set;
+
+int Operators::select(UnaryPredicate1D& pred) {
+ if (!_current_set)
+ return 0;
+ if(_current_set->empty())
+ return 0;
+ I1DContainer new_set;
+ I1DContainer rejected;
+ Functions1D::ChainingTimeStampF1D cts;
+ Functions1D::TimeStampF1D ts;
+ I1DContainer::iterator it = _current_set->begin();
+ I1DContainer::iterator itbegin = it;
+ while (it != _current_set->end()) {
+ Interface1D * i1d = *it;
+ cts(*i1d); // mark everyone's chaining time stamp anyway
+ if(pred(*i1d) < 0){
+ new_set.clear();
+ rejected.clear();
+ return -1;
+ }
+ if(pred.result){
+ new_set.push_back(i1d);
+ ts(*i1d);
+ }else{
+ rejected.push_back(i1d);
+ }
+ ++it;
+ }
+ if((*itbegin)->getExactTypeName() != "ViewEdge"){
+ for (it = rejected.begin();
+ it != rejected.end();
+ ++it)
+ delete *it;
+ }
+ rejected.clear();
+ _current_set->clear();
+ *_current_set = new_set;
+ return 0;
+}
+
+
+int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred,
+ UnaryFunction1D_void& modifier) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ ViewEdge* edge;
+ //soc unused - Chain* new_chain;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred(**it_edge) < 0)
+ return -1;
+ if (pred.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain* new_chain = new Chain(id);++id;
+ for (;;) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ if (modifier(**it) < 0) {
+ delete new_chain;
+ return -1;
+ }
+ ++it;
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ return -1;
+ }
+ if (pred.result)
+ break;
+ }
+
+ _current_chains_set.push_back(new_chain);
+ }
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+
+int Operators::chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+
+ ViewEdge* edge;
+ //soc Chain* new_chain;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred(**it_edge) < 0)
+ return -1;
+ if (pred.result)
+ continue;
+ if (pred_ts(**it_edge) < 0)
+ return -1;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+
+ Chain* new_chain = new Chain(id);++id;
+ for (;;) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ ++it;
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ return -1;
+ }
+ if (pred.result)
+ break;
+ if (pred_ts(**it) < 0) {
+ delete new_chain;
+ return -1;
+ }
+ if (pred_ts.result)
+ break;
+ }
+
+ _current_chains_set.push_back(new_chain);
+ }
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+
+//void Operators::bidirectionalChain(ViewEdgeIterator& it,
+// UnaryPredicate1D& pred,
+// UnaryFunction1D_void& modifier) {
+// if (_current_view_edges_set.empty())
+// return;
+//
+// unsigned id = 0;
+// ViewEdge* edge;
+// Chain* new_chain;
+//
+// for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+// it_edge != _current_view_edges_set.end();
+// ++it_edge) {
+// if (pred(**it_edge))
+// continue;
+//
+// edge = dynamic_cast<ViewEdge*>(*it_edge);
+// it.setBegin(edge);
+// it.setCurrentEdge(edge);
+//
+// Chain* new_chain = new Chain(id);++id;
+// //ViewEdgeIterator it_back(it);--it_back; // FIXME
+// do {
+// new_chain->push_viewedge_back(*it, it.getOrientation());
+// modifier(**it);
+// ++it;
+// } while (!it.isEnd() && !pred(**it));
+// it.setBegin(edge);
+// it.setCurrentEdge(edge);
+// --it;
+// while (!it.isEnd() && !pred(**it)) {
+// new_chain->push_viewedge_front(*it, it.getOrientation());
+// modifier(**it);
+// --it;
+// }
+//
+// _current_chains_set.push_back(new_chain);
+// }
+//
+// if (!_current_chains_set.empty())
+// _current_set = &_current_chains_set;
+//}
+//
+//void Operators::bidirectionalChain(ViewEdgeIterator& it,
+// UnaryPredicate1D& pred) {
+// if (_current_view_edges_set.empty())
+// return;
+//
+// unsigned id = 0;
+// Functions1D::IncrementChainingTimeStampF1D ts;
+// Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+//
+// ViewEdge* edge;
+// Chain* new_chain;
+//
+// for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+// it_edge != _current_view_edges_set.end();
+// ++it_edge) {
+// if (pred(**it_edge) || pred_ts(**it_edge))
+// continue;
+//
+// edge = dynamic_cast<ViewEdge*>(*it_edge);
+// it.setBegin(edge);
+// it.setCurrentEdge(edge);
+ //
+ // Chain* new_chain = new Chain(id);++id;
+ // //ViewEdgeIterator it_back(it);--it_back;//FIXME
+ // do {
+ // new_chain->push_viewedge_back(*it, it.getOrientation());
+ // ts(**it);
+ // ++it;
+ // } while (!it.isEnd() && !pred(**it) && !pred_ts(**it));
+ // it.setBegin(edge);
+ // it.setCurrentEdge(edge);
+ // --it;
+ // while (!it.isEnd() && !pred(**it) && !pred_ts(**it)) {
+ // new_chain->push_viewedge_front(*it, it.getOrientation());
+ // ts(**it);
+ // --it;
+ // }
+ //
+ // _current_chains_set.push_back(new_chain);
+ // }
+ //
+ // if (!_current_chains_set.empty())
+ // _current_set = &_current_chains_set;
+ //}
+
+int Operators::bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+
+ ViewEdge* edge;
+ //soc unused - Chain* new_chain;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred(**it_edge) < 0)
+ return -1;
+ if (pred.result)
+ continue;
+ if (pred_ts(**it_edge) < 0)
+ return -1;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ // re-init iterator
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.init() < 0)
+ return -1;
+
+ Chain* new_chain = new Chain(id);++id;
+ //ViewEdgeIterator it_back(it);--it_back;//FIXME
+ for (;;) {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ if (it.increment() < 0) { // FIXME
+ delete new_chain;
+ return -1;
+ }
+ if (it.isEnd())
+ break;
+ if (pred(**it) < 0) {
+ delete new_chain;
+ return -1;
+ }
+ if (pred.result)
+ break;
+ }
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ return -1;
+ }
+ while (!it.isEnd()) {
+ if (pred(**it) < 0) {
+ delete new_chain;
+ return -1;
+ }
+ if (pred.result)
+ break;
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ return -1;
+ }
+ }
+ _current_chains_set.push_back(new_chain);
+ }
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+int Operators::bidirectionalChain(ChainingIterator& it) {
+ if (_current_view_edges_set.empty())
+ return 0;
+
+ unsigned id = 0;
+ Functions1D::IncrementChainingTimeStampF1D ts;
+ Predicates1D::EqualToChainingTimeStampUP1D pred_ts(TimeStamp::instance()->getTimeStamp()+1);
+
+ ViewEdge* edge;
+ //soc unused - Chain* new_chain;
+
+ for (I1DContainer::iterator it_edge = _current_view_edges_set.begin();
+ it_edge != _current_view_edges_set.end();
+ ++it_edge) {
+ if (pred_ts(**it_edge) < 0)
+ return -1;
+ if (pred_ts.result)
+ continue;
+
+ edge = dynamic_cast<ViewEdge*>(*it_edge);
+ // re-init iterator
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.init() < 0)
+ return -1;
+
+ Chain* new_chain = new Chain(id);++id;
+ //ViewEdgeIterator it_back(it);--it_back;//FIXME
+ do {
+ new_chain->push_viewedge_back(*it, it.getOrientation());
+ ts(**it);
+ if (it.increment() < 0) { // FIXME
+ delete new_chain;
+ return -1;
+ }
+ } while (!it.isEnd());
+ it.setBegin(edge);
+ it.setCurrentEdge(edge);
+ it.setOrientation(true);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ return -1;
+ }
+ while (!it.isEnd()) {
+ new_chain->push_viewedge_front(*it, it.getOrientation());
+ ts(**it);
+ if (it.decrement() < 0) { // FIXME
+ delete new_chain;
+ return -1;
+ }
+ }
+ _current_chains_set.push_back(new_chain);
+ }
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+int Operators::sequentialSplit(UnaryPredicate0D& pred,
+ float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ CurvePoint *point;
+ Chain * new_curve;
+ I1DContainer splitted_chains;
+ Interface0DIterator first;
+ Interface0DIterator end;
+ Interface0DIterator last;
+ Interface0DIterator it;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+
+ Id currentId = (*cit)->getId();
+ new_curve = new Chain(currentId);
+ first = (*cit)->pointsBegin(sampling);
+ end = (*cit)->pointsEnd(sampling);
+ last = end;--last;
+ it = first;
+
+ point = dynamic_cast<CurvePoint*>(&(*it));
+ new_curve->push_vertex_back(point);++it;
+ for(; it!= end; ++it)
+ {
+ point = dynamic_cast<CurvePoint*>(&(*it));
+ new_curve->push_vertex_back(point);
+ if(pred(it) < 0)
+ {
+ delete new_curve;
+ goto error;
+ }
+ if(pred.result && (it!=last))
+ {
+ splitted_chains.push_back(new_curve);
+ currentId.setSecond(currentId.getSecond()+1);
+ new_curve = new Chain(currentId);
+ new_curve->push_vertex_back(point);
+ }
+ }
+ if(new_curve->nSegments() == 0){
+ delete new_curve;
+ return 0;
+ }
+
+ splitted_chains.push_back(new_curve);
+ }
+
+ // Update the current set of chains:
+ cit = _current_chains_set.begin();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ _current_chains_set.clear();
+ _current_chains_set = splitted_chains;
+ splitted_chains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+
+error:
+ cit = splitted_chains.begin();
+ citend = splitted_chains.end();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ return -1;
+}
+
+int Operators::sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred,
+ float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ CurvePoint *point;
+ Chain * new_curve;
+ I1DContainer splitted_chains;
+ Interface0DIterator first;
+ Interface0DIterator end;
+ Interface0DIterator last;
+ Interface0DIterator itStart;
+ Interface0DIterator itStop;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+ Id currentId = (*cit)->getId();
+ first = (*cit)->pointsBegin(sampling);
+ end = (*cit)->pointsEnd(sampling);
+ last = end;--last;
+ itStart = first;
+ do{
+ itStop = itStart;++itStop;
+
+ new_curve = new Chain(currentId);
+ currentId.setSecond(currentId.getSecond()+1);
+
+ point = dynamic_cast<CurvePoint*>(&(*itStart));
+ new_curve->push_vertex_back(point);
+ do{
+ point = dynamic_cast<CurvePoint*>(&(*itStop));
+ new_curve->push_vertex_back(point);
+ ++itStop;
+ if(itStop == end)
+ break;
+ if(stoppingPred(itStop) < 0){
+ delete new_curve;
+ goto error;
+ }
+ }while(!stoppingPred.result);
+ if(itStop!=end){
+ point = dynamic_cast<CurvePoint*>(&(*itStop));
+ new_curve->push_vertex_back(point);
+ }
+ if(new_curve->nSegments() == 0){
+ delete new_curve;
+ }else{
+ splitted_chains.push_back(new_curve);
+ }
+ // find next start
+ do{
+ ++itStart;
+ if(itStart == end)
+ break;
+ if(startingPred(itStart) < 0)
+ goto error;
+ }while(!startingPred.result);
+ }while((itStart!=end) && (itStart!=last));
+ }
+
+ // Update the current set of chains:
+ cit = _current_chains_set.begin();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ _current_chains_set.clear();
+ _current_chains_set = splitted_chains;
+ splitted_chains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+
+error:
+ cit = splitted_chains.begin();
+ citend = splitted_chains.end();
+ for(;
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ return -1;
+}
+
+#include "CurveIterators.h"
+
+// Internal function
+int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling,
+ Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
+{
+ if(((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)){
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
+ CurveInternal::CurvePointIterator second = first; ++second;
+ CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling);
+ CurveInternal::CurvePointIterator it = second;
+ CurveInternal::CurvePointIterator split = second;
+ Interface0DIterator it0d = it.castToInterface0DIterator();
+ real _min = FLT_MAX;++it;//func(it0d);++it;
+ CurveInternal::CurvePointIterator next = it;++next;
+
+ bool bsplit = false;
+ for(; ((it != end) && (next != end)); ++it,++next){
+ it0d = it.castToInterface0DIterator();
+ if (func(it0d) < 0)
+ return -1;
+ if(func.result < _min){
+ _min = func.result;
+ split = it;
+ bsplit = true;
+ }
+ }
+
+ if(!bsplit){ // we didn't find any minimum
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ // retrieves the current splitting id
+ Id * newId = _curve->getSplittingId();
+ if(newId == 0){
+ newId = new Id(_curve->getId());
+ _curve->setSplittingId(newId);
+ }
+
+ Chain *new_curve_a = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_a->setSplittingId(newId);
+ Chain *new_curve_b = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_b->setSplittingId(newId);
+
+ CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend=_curve->curveVerticesEnd();
+ CurveInternal::CurvePointIterator vnext = vit; ++vnext;
+
+
+ for(; (vit!=vitend)&&(vnext!=vitend)&&(split._CurvilinearLength-vit._CurvilinearLength> 0.001); ++vit,++vnext){
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+ if((vit==vitend) || (vnext == vitend)){
+ cout << "The split takes place in bad location" << endl;
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+
+ // build the two resulting chains
+ if(fabs(vit._CurvilinearLength-split._CurvilinearLength) > 0.001){
+ new_curve_a->push_vertex_back(&(*split));
+ new_curve_b->push_vertex_back(&(*split));
+ }
+ else{
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+
+ for(;vit!=vitend;++vit)
+ new_curve_b->push_vertex_back(&(*vit));
+
+ // let's check whether one or two of the two new curves
+ // satisfy the stopping condition or not.
+ // (if one of them satisfies it, we don't split)
+ if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
+ delete new_curve_a;
+ delete new_curve_b;
+ return -1;
+ }
+ if(pred.result){
+ // we don't actually create these two chains
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+ // here we know we'll split _curve:
+ splitted_chains.push_back(_curve);
+
+ __recursiveSplit(new_curve_a, func, pred, sampling, newChains, splitted_chains);
+ __recursiveSplit(new_curve_b, func, pred, sampling, newChains, splitted_chains);
+ return 0;
+}
+
+int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+
+ Chain *currentChain = 0;
+ I1DContainer splitted_chains;
+ I1DContainer newChains;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+ currentChain = dynamic_cast<Chain*>(*cit);
+ if(!currentChain)
+ continue;
+ // let's check the first one:
+ if (pred(*currentChain) < 0)
+ return -1;
+ if(!pred.result){
+ __recursiveSplit(currentChain, func, pred, sampling, newChains, splitted_chains);
+ }else{
+ newChains.push_back(currentChain);
+ }
+ }
+ // Update the current set of chains:
+ if(!splitted_chains.empty()){
+ for(cit = splitted_chains.begin(), citend = splitted_chains.end();
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ }
+
+ _current_chains_set.clear();
+ _current_chains_set = newChains;
+ newChains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+
+
+// recursive split with pred 0D
+int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling,
+ Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
+{
+ if(((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)){
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ CurveInternal::CurvePointIterator first = _curve->curvePointsBegin(sampling);
+ CurveInternal::CurvePointIterator second = first; ++second;
+ CurveInternal::CurvePointIterator end = _curve->curvePointsEnd(sampling);
+ CurveInternal::CurvePointIterator it = second;
+ CurveInternal::CurvePointIterator split = second;
+ Interface0DIterator it0d = it.castToInterface0DIterator();
+ //real _min = func(it0d);++it;
+ real _min = FLT_MAX;++it;
+ real mean = 0.f;
+ //soc unused - real variance = 0.f;
+ unsigned count = 0;
+ CurveInternal::CurvePointIterator next = it;++next;
+
+ bool bsplit = false;
+ for(; ((it != end) && (next != end)); ++it,++next){
+ ++count;
+ it0d = it.castToInterface0DIterator();
+ if(pred0d(it0d) < 0)
+ return -1;
+ if(!pred0d.result)
+ continue;
+ if(func(it0d) < 0)
+ return -1;
+ mean += func.result;
+ if(func.result < _min){
+ _min = func.result;
+ split = it;
+ bsplit = true;
+ }
+ }
+ mean /= (float)count;
+
+ //if((!bsplit) || (mean-_min>mean)){ // we didn't find any minimum
+ if(!bsplit){ // we didn't find any minimum
+ newChains.push_back(_curve);
+ return 0;
+ }
+
+ // retrieves the current splitting id
+ Id * newId = _curve->getSplittingId();
+ if(newId == 0){
+ newId = new Id(_curve->getId());
+ _curve->setSplittingId(newId);
+ }
+
+ Chain *new_curve_a = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_a->setSplittingId(newId);
+ Chain *new_curve_b = new Chain(*newId);
+ newId->setSecond(newId->getSecond()+1);
+ new_curve_b->setSplittingId(newId);
+
+ CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend=_curve->curveVerticesEnd();
+ CurveInternal::CurvePointIterator vnext = vit; ++vnext;
+
+
+ for(; (vit!=vitend)&&(vnext!=vitend)&&(split._CurvilinearLength-vit._CurvilinearLength> 0.001); ++vit,++vnext){
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+ if((vit==vitend) || (vnext == vitend)){
+ cout << "The split takes place in bad location" << endl;
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+
+ // build the two resulting chains
+ if(fabs(vit._CurvilinearLength-split._CurvilinearLength) > 0.001){
+ new_curve_a->push_vertex_back(&(*split));
+ new_curve_b->push_vertex_back(&(*split));
+ }
+ else{
+ new_curve_a->push_vertex_back(&(*vit));
+ }
+
+ for(;vit!=vitend;++vit)
+ new_curve_b->push_vertex_back(&(*vit));
+
+ // let's check whether one or two of the two new curves
+ // satisfy the stopping condition or not.
+ // (if one of them satisfies it, we don't split)
+ if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
+ delete new_curve_a;
+ delete new_curve_b;
+ return -1;
+ }
+ if(pred.result){
+ // we don't actually create these two chains
+ newChains.push_back(_curve);
+ delete new_curve_a;
+ delete new_curve_b;
+ return 0;
+ }
+ // here we know we'll split _curve:
+ splitted_chains.push_back(_curve);
+
+ __recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains);
+ __recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains);
+ return 0;
+}
+
+int Operators::recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling)
+{
+ if (_current_chains_set.empty()) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+
+ Chain *currentChain = 0;
+ I1DContainer splitted_chains;
+ I1DContainer newChains;
+ I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
+ for (;
+ cit != citend;
+ ++cit) {
+ currentChain = dynamic_cast<Chain*>(*cit);
+ if(!currentChain)
+ continue;
+ // let's check the first one:
+ if(pred(*currentChain) < 0)
+ return -1;
+ if(!pred.result){
+ __recursiveSplit(currentChain, func, pred0d, pred, sampling, newChains, splitted_chains);
+ }else{
+ newChains.push_back(currentChain);
+ }
+ }
+ // Update the current set of chains:
+ if(!splitted_chains.empty()){
+ for(cit = splitted_chains.begin(), citend = splitted_chains.end();
+ cit != citend;
+ ++cit){
+ delete (*cit);
+ }
+ splitted_chains.clear();
+ }
+
+ _current_chains_set.clear();
+ _current_chains_set = newChains;
+ newChains.clear();
+
+ if (!_current_chains_set.empty())
+ _current_set = &_current_chains_set;
+ return 0;
+}
+// Internal class
+class PredicateWrapper
+{
+public:
+
+ inline PredicateWrapper(BinaryPredicate1D& pred) {
+ _pred = &pred;
+ }
+
+ inline bool operator()(Interface1D* i1, Interface1D* i2) {
+ if ((*_pred)(*i1, *i2) < 0)
+ throw std::runtime_error("comparison failed");
+ return _pred->result;
+ }
+
+private:
+
+ BinaryPredicate1D* _pred;
+};
+
+int Operators::sort(BinaryPredicate1D& pred) {
+ if (!_current_set)
+ return 0;
+ PredicateWrapper wrapper(pred);
+ try {
+ std::sort(_current_set->begin(), _current_set->end(), wrapper);
+ }
+ catch (std::runtime_error &e) {
+ cerr << "Warning: Operator.sort(): " << e.what() << endl;
+ return -1;
+ }
+ return 0;
+}
+
+Stroke* createStroke(Interface1D& inter) {
+ Stroke* stroke = new Stroke;
+ stroke->setId(inter.getId());
+
+ float currentCurvilignAbscissa = 0.f;
+
+ Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd();
+ Interface0DIterator itfirst = it;
+
+ Vec3r current(it->getProjectedX(), it->getProjectedY(), it->getProjectedZ());
+ Vec3r previous = current;
+ SVertex* sv;
+ CurvePoint* cp;
+ StrokeVertex* stroke_vertex = NULL;
+
+ do {
+ cp = dynamic_cast<CurvePoint*>(&(*it));
+ if (!cp) {
+ sv = dynamic_cast<SVertex*>(&(*it));
+ if (!sv) {
+ cerr << "Warning: unexpected Vertex type" << endl;
+ continue;
+ }
+ stroke_vertex = new StrokeVertex(sv);
+ }
+ else
+ stroke_vertex = new StrokeVertex(cp);
+ current = stroke_vertex->point2d();
+ Vec3r vec_tmp(current - previous);
+ currentCurvilignAbscissa += vec_tmp.norm();
+ stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
+ stroke->push_back(stroke_vertex);
+ previous = current;
+ ++it;
+ } while((it != itend) && (it != itfirst));
+
+ if (it == itfirst) {
+ // Add last vertex:
+ cp = dynamic_cast<CurvePoint*>(&(*it));
+ if (!cp) {
+ sv = dynamic_cast<SVertex*>(&(*it));
+ if (!sv)
+ cerr << "Warning: unexpected Vertex type" << endl;
+ else
+ stroke_vertex = new StrokeVertex(sv);
+ }
+ else
+ stroke_vertex = new StrokeVertex(cp);
+ current = stroke_vertex->point2d();
+ Vec3r vec_tmp(current - previous);
+ currentCurvilignAbscissa += vec_tmp.norm();
+ stroke_vertex->setCurvilinearAbscissa(currentCurvilignAbscissa);
+ stroke->push_back(stroke_vertex);
+ }
+ stroke->setLength(currentCurvilignAbscissa);
+ return stroke;
+}
+
+
+inline int applyShading(Stroke& stroke, vector<StrokeShader*>& shaders) {
+ for (vector<StrokeShader*>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
+ if ((*it)->shade(stroke) < 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+int Operators::create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders) {
+ //Canvas* canvas = Canvas::getInstance();
+ if (!_current_set) {
+ cerr << "Warning: current set empty" << endl;
+ return 0;
+ }
+ for (Operators::I1DContainer::iterator it = _current_set->begin();
+ it != _current_set->end();
+ ++it) {
+ if (pred(**it) < 0)
+ return -1;
+ if (!pred.result)
+ continue;
+
+ Stroke* stroke = createStroke(**it);
+ if (stroke) {
+ if (applyShading(*stroke, shaders) < 0)
+ return -1;
+ //canvas->RenderStroke(stroke);
+ _current_strokes_set.push_back(stroke);
+ }
+ }
+ return 0;
+}
+
+
+void Operators::reset() {
+ ViewMap* vm = ViewMap::getInstance();
+ if (!vm) {
+ cerr << "Error: no ViewMap computed yet" << endl;
+ return;
+ }
+ _current_view_edges_set.clear();
+ for (I1DContainer::iterator it = _current_chains_set.begin();
+ it != _current_chains_set.end();
+ ++it)
+ delete *it;
+ _current_chains_set.clear();
+ _current_view_edges_set.insert(_current_view_edges_set.begin(),
+ vm->ViewEdges().begin(),
+ vm->ViewEdges().end());
+ _current_set = &_current_view_edges_set;
+ _current_strokes_set.clear();
+}
diff --git a/source/blender/freestyle/intern/stroke/Operators.h b/source/blender/freestyle/intern/stroke/Operators.h
new file mode 100755
index 00000000000..d705d5af5b2
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Operators.h
@@ -0,0 +1,311 @@
+//
+// Filename : Operators.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class gathering stroke creation algorithms
+// 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 OPERATORS_H
+# define OPERATORS_H
+
+# include "../view_map/Interface1D.h"
+# include <vector>
+# include <iostream>
+# include "Predicates1D.h"
+# include "Predicates0D.h"
+# include "../view_map/ViewMap.h"
+# include "Chain.h"
+# include "ChainingIterators.h"
+# include "../system/TimeStamp.h"
+# include "StrokeShader.h"
+
+/*! Class defining the operators used in a style module.
+ * There are 4 classes of operators: Selection, Chaining,
+ * Splitting and Creating. All these operators are user controlled
+ * in the scripting language through Functors, Predicates and Shaders
+ * that are taken as arguments.
+ */
+class LIB_STROKE_EXPORT Operators {
+
+public:
+
+ typedef vector<Interface1D*> I1DContainer;
+ typedef vector<Stroke*> StrokesContainer;
+
+
+ //
+ // Operators
+ //
+ ////////////////////////////////////////////////
+
+ /*! Selects the ViewEdges of the ViewMap verifying
+ * a specified condition.
+ * \param pred The predicate expressing this condition
+ */
+ static int select(UnaryPredicate1D& pred);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator only iterates using the increment operator and is
+ * therefore unidirectional.
+ * \param it
+ * The iterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping
+ * condition.
+ * \param modifier
+ * A function that takes a ViewEdge as argument and that
+ * is used to modify the processed ViewEdge state (the timestamp
+ * incrementation is a typical illustration of such a modifier)
+ */
+ static int chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred,
+ UnaryFunction1D_void& modifier);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator only iterates using the increment operator and is
+ * therefore unidirectional.
+ * This chaining operator is different from the previous one because
+ * it doesn't take any modifier as argument. Indeed, the time stamp (insuring
+ * that a ViewEdge is processed one time) is automatically managed in this case.
+ * \param it
+ * The iterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping
+ * condition.
+ */
+ static int chain(ViewEdgeInternal::ViewEdgeIterator& it,
+ UnaryPredicate1D& pred);
+
+ /*! Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list potentially starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator iterates both using the increment and decrement operators and is
+ * therefore bidirectional.
+ * This operator works with a ChainingIterator which contains the
+ * chaining rules. It is this last one which can be told
+ * to chain only edges that belong to the selection or not to
+ * process twice a ViewEdge during the chaining.
+ * Each time a ViewEdge is added to a chain, its chaining time stamp
+ * is incremented. This allows you to keep track of
+ * the number of chains to which a ViewEdge belongs to.
+ * \param it
+ * The ChainingIterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ * \param pred
+ * The predicate on the ViewEdge that expresses the stopping
+ * condition.
+ */
+ static int bidirectionalChain(ChainingIterator& it, UnaryPredicate1D& pred);
+
+ /*! The only difference with the above bidirectional chaining algorithm is
+ * that we don't need to pass a stopping criterion. This might be desirable
+ * when the stopping criterion is already contained in the iterator
+ * definition.
+ * Builds a set of chains from the current set of ViewEdges.
+ * Each ViewEdge of the current list potentially starts a new chain. The chaining
+ * operator then iterates over the ViewEdges of the ViewMap using the
+ * user specified iterator.
+ * This operator iterates both using the increment and decrement operators and is
+ * therefore bidirectional.
+ * This operator works with a ChainingIterator which contains the
+ * chaining rules. It is this last one which can be told
+ * to chain only edges that belong to the selection or not to
+ * process twice a ViewEdge during the chaining.
+ * Each time a ViewEdge is added to a chain, its chaining time stamp
+ * is incremented. This allows you to keep track of
+ * the number of chains to which a ViewEdge belongs to.
+ * \param it
+ * The ChainingIterator on the ViewEdges of the ViewMap. It contains
+ * the chaining rule.
+ */
+ static int bidirectionalChain(ChainingIterator& it);
+
+ /*! Splits each chain of the current set of chains in a sequential way.
+ * The points of each chain are processed (with a specified sampling) sequentially.
+ * Each time a user specified starting condition is verified, a new chain begins and
+ * ends as soon as a user-defined stopping predicate is verified.
+ * This allows chains overlapping rather than chains partitioning.
+ * The first point of the initial chain is the first point of one of the
+ * resulting chains.
+ * The splitting ends when no more chain can start.
+ * \param startingPred
+ * The predicate on a point that expresses the starting
+ * condition
+ * \param stoppingPred
+ * The predicate on a point that expresses the stopping
+ * condition
+ * \param sampling
+ * The resolution used to sample the chain for the predicates
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ */
+ static int sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred,
+ float sampling = 0.f);
+
+ /*! Splits each chain of the current set of chains in a sequential way.
+ * The points of each chain are processed (with a specified sampling) sequentially
+ * and each time a user specified condition is verified, the chain is split into two chains.
+ * The resulting set of chains is a partition of the initial chain
+ * \param pred
+ * The predicate on a point that expresses the splitting
+ * condition
+ * \param sampling
+ * The resolution used to sample the chain for the predicate
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ */
+ static int sequentialSplit(UnaryPredicate0D& pred,
+ float sampling = 0.f);
+
+ /*! Splits the current set of chains in a recursive way.
+ * We process the points of each chain (with a specified sampling) to find
+ * the point minimizing a specified function. The chain is split in two at this
+ * point and the two new chains are processed in the same way.
+ * The recursivity level is controlled through a predicate 1D that expresses a stopping condition
+ * on the chain that is about to be processed.
+ * \param func
+ * The Unary Function evaluated at each point of the chain.
+ * The splitting point is the point minimizing this function
+ * \param pred
+ * The Unary Predicate ex pressing the recursivity stopping condition.
+ * This predicate is evaluated for each curve before it actually gets
+ * split. If pred(chain) is true, the curve won't be split anymore.
+ * \param sampling
+ * The resolution used to sample the chain for the predicates
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ */
+ static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate1D& pred, float sampling = 0);
+
+ /*! Splits the current set of chains in a recursive way.
+ * We process the points of each chain (with a specified sampling) to find
+ * the point minimizing a specified function. The chain is split in two at this
+ * point and the two new chains are processed in the same way.
+ * The user can specify a 0D predicate to make a first selection
+ * on the points that can potentially be split.
+ * A point that doesn't verify the 0D predicate won't be candidate
+ * in realizing the min.
+ * The recursivity level is controlled through a predicate 1D that expresses a stopping condition
+ * on the chain that is about to be processed.
+ * \param func
+ * The Unary Function evaluated at each point of the chain.
+ * The splitting point is the point minimizing this function
+ * \param pred0d
+ * The Unary Predicate 0D used to select the candidate points
+ * where the split can occur.
+ * For example, it is very likely that would rather have
+ * your chain splitting around its middle point than around
+ * one of its extremities. A 0D predicate working on
+ * the curvilinear abscissa allows to add this kind of constraints.
+ * \param pred
+ * The Unary Predicate ex pressing the recursivity stopping condition.
+ * This predicate is evaluated for each curve before it actually gets
+ * split. If pred(chain) is true, the curve won't be split anymore.
+ * \param sampling
+ * The resolution used to sample the chain for the predicates
+ * evaluation. (The chain is not actually resampled, a virtual point
+ * only progresses along the curve using this resolution)
+ *
+ */
+ static int recursiveSplit(UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d, UnaryPredicate1D& pred, float sampling = 0);
+
+ /*! Sorts the current set of chains (or viewedges) according to the
+ * comparison predicate given as argument.
+ * \param pred
+ * The binary predicate used for the comparison
+ */
+ static int sort(BinaryPredicate1D& pred);
+
+ /*! Creates and shades the strokes from the current set of chains.
+ * A predicate can be specified to make a selection pass on the
+ * chains.
+ * \param pred
+ * The predicate that a chain must verify in order to
+ * be transform as a stroke
+ * \param shaders
+ * The list of shaders used to shade the strokes
+ */
+ static int create(UnaryPredicate1D& pred, vector<StrokeShader*> shaders);
+
+ //
+ // Data access
+ //
+ ////////////////////////////////////////////////
+
+ static ViewEdge* getViewEdgeFromIndex(unsigned i) {
+ return dynamic_cast<ViewEdge*>(_current_view_edges_set[i]);
+ }
+
+ static Chain* getChainFromIndex(unsigned i) {
+ return dynamic_cast<Chain*>(_current_chains_set[i]);
+ }
+
+ static Stroke* getStrokeFromIndex(unsigned i) {
+ return _current_strokes_set[i];
+ }
+
+ static unsigned getViewEdgesSize() {
+ return _current_view_edges_set.size();
+ }
+
+ static unsigned getChainsSize() {
+ return _current_chains_set.size();
+ }
+
+ static unsigned getStrokesSize() {
+ return _current_strokes_set.size();
+ }
+
+ //
+ // Not exported in Python
+ //
+ //////////////////////////////////////////////////
+
+ static StrokesContainer* getStrokesSet() {
+ return &_current_strokes_set;
+ }
+
+ static void reset();
+
+private:
+
+ Operators() {}
+
+ static I1DContainer _current_view_edges_set;
+ static I1DContainer _current_chains_set;
+ static I1DContainer* _current_set;
+ static StrokesContainer _current_strokes_set;
+};
+
+#endif // OPERATORS_H
diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
new file mode 100755
index 00000000000..dc9c94e0e11
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.cpp
@@ -0,0 +1,89 @@
+
+//
+// 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 "PSStrokeRenderer.h"
+# include "Canvas.h"
+
+PSStrokeRenderer::PSStrokeRenderer(const char* iFileName)
+:StrokeRenderer(){
+ if(!iFileName)
+ iFileName = "freestyle.ps";
+ // open the stream:
+ _ofstream.open(iFileName, ios::out);
+ if(!_ofstream.is_open()){
+ cerr << "couldn't open the output file " << iFileName << endl;
+ }
+ _ofstream << "%!PS-Adobe-2.0 EPSF-2.0" << endl;
+ _ofstream << "%%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl;
+ _ofstream << "%%BoundingBox: " << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << endl;
+ _ofstream << "%%EndComments" << endl;
+}
+
+PSStrokeRenderer::~PSStrokeRenderer(){
+ Close();
+}
+
+void PSStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void PSStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
+ vector<Strip*>& strips = iStrokeRep->getStrips();
+ Strip::vertex_container::iterator v[3];
+ StrokeVertexRep *svRep[3];
+ Vec3r color[3];
+ for(vector<Strip*>::iterator s=strips.begin(), send=strips.end();
+ s!=send;
+ ++s){
+ Strip::vertex_container& vertices = (*s)->vertices();
+ v[0] = vertices.begin();
+ v[1] = v[0];++(v[1]);
+ v[2] = v[1]; ++(v[2]);
+
+ while(v[2]!=vertices.end()){
+ svRep[0] = *(v[0]);
+ svRep[1] = *(v[1]);
+ svRep[2] = *(v[2]);
+
+ color[0] = svRep[0]->color();
+ //color[1] = svRep[1]->color();
+ //color[2] = svRep[2]->color();
+
+ _ofstream << "newpath" << endl;
+ _ofstream << (color[0])[0] << " " << (color[0])[1] << " " << (color[0])[2] << " setrgbcolor" <<endl;
+ _ofstream << svRep[0]->point2d()[0] << " " <<svRep[0]->point2d()[1] << " moveto" << endl;
+ _ofstream << svRep[1]->point2d()[0] << " " <<svRep[1]->point2d()[1] << " lineto" << endl;
+ _ofstream << svRep[2]->point2d()[0] << " " <<svRep[2]->point2d()[1] << " lineto" << endl;
+ _ofstream << "closepath" << endl;
+ _ofstream << "fill" << endl;
+
+ ++v[0];
+ ++v[1];
+ ++v[2];
+ }
+ }
+}
+
+void PSStrokeRenderer::Close(){
+ if(_ofstream.is_open())
+ _ofstream.close();
+}
+
diff --git a/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h
new file mode 100755
index 00000000000..b30949845ab
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/PSStrokeRenderer.h
@@ -0,0 +1,63 @@
+//
+// Filename : PSStrokeRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the Postscript rendering of a stroke
+// Date of creation : 10/26/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 PSSTROKERENDERER_H
+# define PSSTROKERENDERER_H
+
+# include "StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+# include <fstream>
+
+/**********************************/
+/* */
+/* */
+/* PSStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_STROKE_EXPORT PSStrokeRenderer : public StrokeRenderer
+{
+public:
+ PSStrokeRenderer(const char * iFileName = 0);
+ virtual ~PSStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ /*! Closes the output PS file */
+ void Close();
+
+protected:
+ mutable ofstream _ofstream;
+};
+
+#endif // PSSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/stroke/Predicates0D.h b/source/blender/freestyle/intern/stroke/Predicates0D.h
new file mode 100755
index 00000000000..2f5d9551b3a
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Predicates0D.h
@@ -0,0 +1,172 @@
+//
+// Filename : Predicates0D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class gathering stroke creation algorithms
+// 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 PREDICATES0D_H
+# define PREDICATES0D_H
+
+# include "../view_map/Functions0D.h"
+
+# include "../python/Director.h"
+
+//
+// UnaryPredicate0D (base class for predicates in 0D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Unary Predicates that work
+ * on Interface0DIterator.
+ * A UnaryPredicate0D is a functor that evaluates
+ * a condition on a Interface0DIterator and returns
+ * true or false depending on whether this condition is
+ * satisfied or not.
+ * The UnaryPredicate0D is used by calling its () operator.
+ * Any inherited class must overload the () operator.
+ */
+class UnaryPredicate0D
+{
+public:
+
+ bool result;
+ PyObject *py_up0D;
+
+ /*! Default constructor. */
+ UnaryPredicate0D() { py_up0D = 0; }
+ /*! Destructor. */
+ virtual ~UnaryPredicate0D() {}
+ /*! Returns the string of the name
+ * of the UnaryPredicate0D.
+ */
+ virtual string getName() const {
+ return "UnaryPredicate0D";
+ }
+ /*! The () operator. Must be overload
+ * by inherited classes.
+ * \param it
+ * The Interface0DIterator pointing onto the
+ * Interface0D at which we wish to evaluate
+ * the predicate.
+ * \return true if the condition is satisfied,
+ * false otherwise.
+ */
+ virtual int operator()(Interface0DIterator& it) {
+ return Director_BPy_UnaryPredicate0D___call__(this, it);
+ }
+
+};
+
+
+//
+// BinaryPredicate0D (base class for predicates in 0D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Binary Predicates working on Interface0D.
+ * A BinaryPredicate0D is typically an ordering relation
+ * between two Interface0D.
+ * It evaluates a relation between 2 Interface0D and
+ * returns true or false.
+ * It is used by calling the () operator.
+ */
+class BinaryPredicate0D
+{
+public:
+
+ bool result;
+ PyObject *py_bp0D;
+
+ /*! Default constructor. */
+ BinaryPredicate0D() { py_bp0D = 0; }
+ /*! Destructor. */
+ virtual ~BinaryPredicate0D() {}
+ /*! Returns the string of the name of the
+ * binary predicate.
+ */
+ virtual string getName() const {
+ return "BinaryPredicate0D";
+ }
+
+ /*! The () operator. Must be overload by inherited classes.
+ * It evaluates a relation between 2 Interface0D.
+ * \param inter1
+ * The first Interface0D.
+ * \param inter2
+ * The second Interface0D.
+ * \return true or false.
+ */
+ virtual int operator()(Interface0D& inter1, Interface0D& inter2) {
+ return Director_BPy_BinaryPredicate0D___call__(this, inter1, inter2);
+ }
+
+};
+
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates0D {
+
+ // TrueUP0D
+ /*! Returns true any time */
+ class TrueUP0D : public UnaryPredicate0D
+ {
+ public:
+ /*! Default constructor. */
+ TrueUP0D() {}
+ /*! Returns the string "TrueUP0D"*/
+ string getName() const {
+ return "TrueUP0D";
+ }
+ /*! The () operator. */
+ int operator()(Interface0DIterator&) {
+ result = true;
+ return 0;
+ }
+ };
+
+ // FalseUP0D
+ /*! Returns false any time */
+ class FalseUP0D : public UnaryPredicate0D
+ {
+ public:
+ /*! Default constructor. */
+ FalseUP0D() {}
+ /*! Returns the string "FalseUP0D"*/
+ string getName() const {
+ return "FalseUP0D";
+ }
+ /*! The () operator. */
+ int operator()(Interface0DIterator&) {
+ result = false;
+ return 0;
+ }
+ };
+
+} // end of namespace Predicates0D
+
+#endif // PREDICATES0D_H
diff --git a/source/blender/freestyle/intern/stroke/Predicates1D.h b/source/blender/freestyle/intern/stroke/Predicates1D.h
new file mode 100755
index 00000000000..6461f6428ab
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Predicates1D.h
@@ -0,0 +1,483 @@
+//
+// Filename : Predicates1D.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class gathering stroke creation algorithms
+// 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 PREDICATES1D_H
+# define PREDICATES1D_H
+
+# include <string>
+# include "../system/TimeStamp.h"
+# include "../view_map/Interface1D.h"
+# include "../view_map/Functions1D.h"
+# include "AdvancedFunctions1D.h"
+
+# include "../python/Director.h"
+
+//
+// UnaryPredicate1D (base class for predicates in 1D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Unary Predicates that work
+ * on Interface1D.
+ * A UnaryPredicate1D is a functor that evaluates
+ * a condition on a Interface1D and returns
+ * true or false depending on whether this condition is
+ * satisfied or not.
+ * The UnaryPredicate1D is used by calling its () operator.
+ * Any inherited class must overload the () operator.
+ */
+class UnaryPredicate1D
+{
+public:
+
+ bool result;
+ PyObject *py_up1D;
+
+ /*! Default constructor. */
+ UnaryPredicate1D() { py_up1D = 0; }
+ /*! Destructor. */
+ virtual ~UnaryPredicate1D() {}
+ /*! Returns the string of the name
+ * of the UnaryPredicate1D.
+ */
+ virtual string getName() const {
+ return "UnaryPredicate1D";
+ }
+ /*! The () operator. Must be overload
+ * by inherited classes.
+ * \param inter
+ * The Interface1D on which we wish to evaluate
+ * the predicate.
+ * \return true if the condition is satisfied,
+ * false otherwise.
+ */
+ virtual int operator()(Interface1D& inter) {
+ return Director_BPy_UnaryPredicate1D___call__(this, inter);
+ }
+
+};
+
+
+//
+// BinaryPredicate1D (base class for predicates in 1D)
+//
+///////////////////////////////////////////////////////////
+/*! Base class for Binary Predicates working on Interface1D.
+ * A BinaryPredicate1D is typically an ordering relation
+ * between two Interface1D.
+ * It evaluates a relation between 2 Interface1D and
+ * returns true or false.
+ * It is used by calling the () operator.
+ */
+class BinaryPredicate1D
+{
+public:
+
+ bool result;
+ PyObject *py_bp1D;
+
+ /*! Default constructor. */
+ BinaryPredicate1D() { py_bp1D = 0; }
+ /*! Destructor. */
+ virtual ~BinaryPredicate1D() {}
+ /*! Returns the string of the name of the
+ * binary predicate.
+ */
+ virtual string getName() const {
+ return "BinaryPredicate1D";
+ }
+ /*! The () operator. Must be overload by inherited classes.
+ * It evaluates a relation between 2 Interface1D.
+ * \param inter1
+ * The first Interface1D.
+ * \param inter2
+ * The second Interface1D.
+ * \return true or false.
+ */
+ virtual int operator()(Interface1D& inter1, Interface1D& inter2) {
+ return Director_BPy_BinaryPredicate1D___call__(this, inter1, inter2);
+ }
+
+};
+
+
+//
+// Predicates definitions
+//
+///////////////////////////////////////////////////////////
+
+namespace Predicates1D {
+
+ // TrueUP1D
+ /*! Returns true */
+ class TrueUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Constructor */
+ TrueUP1D() {}
+ /*! Returns the string "TrueUP1D"*/
+ string getName() const {
+ return "TrueUP1D";
+ }
+ /*! the () operator */
+ int operator()(Interface1D&) {
+ result = true;
+ return 0;
+ }
+ };
+
+ // FalseUP1D
+ /*! Returns false */
+ class FalseUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Constructor */
+ FalseUP1D() {}
+ /*! Returns the string "FalseUP1D"*/
+ string getName() const {
+ return "FalseUP1D";
+ }
+ /*! the () operator */
+ int operator()(Interface1D&) {
+ result = false;
+ return 0;
+ }
+ };
+
+ // QuantitativeInvisibilityUP1D
+ /*! Returns true if the Quantitative Invisibility evaluated
+ * at an Interface1D, using the QuantitativeInvisibilityF1D
+ * functor, equals a certain user-defined value.
+ */
+ class QuantitativeInvisibilityUP1D : public UnaryPredicate1D
+ {
+ public:
+ /*! Builds the Predicate.
+ * \param qi
+ * The Quantitative Invisibility you want
+ * the Interface1D to have
+ */
+ QuantitativeInvisibilityUP1D(unsigned qi = 0) : _qi(qi) {}
+ /*! Returns the string "QuantitativeInvisibilityUP1D"*/
+ string getName() const {
+ return "QuantitativeInvisibilityUP1D";
+ }
+ /*! the () operator */
+ int operator()(Interface1D& inter) {
+ Functions1D::QuantitativeInvisibilityF1D func;
+ if (func(inter) < 0)
+ return -1;
+ result = (func.result == _qi);
+ return 0;
+ }
+ private:
+ unsigned _qi;
+ };
+
+ // ContourUP1D
+ /*! Returns true if the Interface1D is a contour.
+ * An Interface1D is a contour if it is borded
+ * by a different shape on each of its sides.
+ */
+ class ContourUP1D : public UnaryPredicate1D
+ {
+ private:
+ Functions1D::CurveNatureF1D _getNature;
+ public:
+ /*! Returns the string "ContourUP1D"*/
+ string getName() const {
+ return "ContourUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ if (_getNature(inter) < 0)
+ return -1;
+ if((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)){
+ Interface0DIterator it=inter.verticesBegin();
+ for(; !it.isEnd(); ++it){
+ if(Functions0D::getOccludeeF0D(it) != Functions0D::getShapeF0D(it)) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // ExternalContourUP1D
+ /*! Returns true if the Interface1D is an external contour.
+ * An Interface1D is an external contour if it is borded
+ * by no shape on one of its sides.
+ */
+ class ExternalContourUP1D : public UnaryPredicate1D
+ {
+ private:
+ Functions1D::CurveNatureF1D _getNature;
+ public:
+ /*! Returns the string "ExternalContourUP1D"*/
+ string getName() const {
+ return "ExternalContourUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ if (_getNature(inter) < 0)
+ return -1;
+ if((_getNature.result & Nature::SILHOUETTE) || (_getNature.result & Nature::BORDER)){
+ set<ViewShape*> occluded;
+ Functions1D::getOccludeeF1D(inter, occluded);
+ for(set<ViewShape*>::iterator os=occluded.begin(), osend=occluded.end();
+ os!=osend;
+ ++os){
+ if((*os) == 0) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // EqualToTimeStampUP1D
+ /*! Returns true if the Interface1D's time stamp
+ * is equal to a certain user-defined value.
+ */
+ class EqualToTimeStampUP1D : public UnaryPredicate1D
+ {
+ protected:
+ unsigned _timeStamp;
+ public:
+ EqualToTimeStampUP1D(unsigned ts) : UnaryPredicate1D(){
+ _timeStamp = ts;
+ }
+ /*! Returns the string "EqualToTimeStampUP1D"*/
+ string getName() const {
+ return "EqualToTimeStampUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ result = (inter.getTimeStamp() == _timeStamp);
+ return 0;
+ }
+ };
+
+ // EqualToChainingTimeStampUP1D
+ /*! Returns true if the Interface1D's time stamp
+ * is equal to a certain user-defined value.
+ */
+ class EqualToChainingTimeStampUP1D : public UnaryPredicate1D
+ {
+ protected:
+ unsigned _timeStamp;
+ public:
+ EqualToChainingTimeStampUP1D(unsigned ts) : UnaryPredicate1D(){
+ _timeStamp = ts;
+ }
+ /*! Returns the string "EqualToChainingTimeStampUP1D"*/
+ string getName() const {
+ return "EqualToChainingTimeStampUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ ViewEdge* edge = dynamic_cast<ViewEdge*>(&inter);
+ if (!edge) {
+ result = false;
+ return 0;
+ }
+ result = (edge->getChainingTimeStamp() >= _timeStamp);
+ return 0;
+ }
+ };
+
+ // ShapeUP1D
+ /*! Returns true if the shape to which the Interface1D
+ * belongs to has the same Id as the one specified by the
+ * user.
+ */
+ class ShapeUP1D: public UnaryPredicate1D
+ {
+ private:
+ Id _id;
+ public:
+ /*! Builds the Predicate.
+ * \param idFirst
+ * The first Id component.
+ * \param idSecond
+ * The second Id component.
+ */
+ ShapeUP1D(unsigned idFirst, unsigned idSecond=0)
+ : UnaryPredicate1D(){
+ _id = Id(idFirst, idSecond);
+ }
+ /*! Returns the string "ShapeUP1D"*/
+ string getName() const {
+ return "ShapeUP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& inter) {
+ set<ViewShape*> shapes;
+ Functions1D::getShapeF1D(inter, shapes);
+ for(set<ViewShape*>::iterator s=shapes.begin(), send=shapes.end();
+ s!=send;
+ ++s){
+ if((*s)->getId() == _id) {
+ result = true;
+ return 0;
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ //
+ // Binary Predicates definitions
+ //
+ ///////////////////////////////////////////////////////////
+
+ // TrueBP1D
+ /*! Returns true. */
+ class TrueBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "TrueBP1D"*/
+ string getName() const {
+ return "TrueBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ result = true;
+ return 0;
+ }
+ };
+
+ // FalseBP1D
+ /*! Returns false. */
+ class FalseBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "FalseBP1D"*/
+ string getName() const {
+ return "FalseBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ result = false;
+ return 0;
+ }
+ };
+
+ // Length2DBP1D
+ /*! Returns true if the 2D length of the Interface1D i1
+ * is less than the 2D length of the Interface1D i2.
+ */
+ class Length2DBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "Length2DBP1D"*/
+ string getName() const {
+ return "Length2DBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ result = (i1.getLength2D() > i2.getLength2D());
+ return 0;
+ }
+ };
+
+ // SameShapeIdBP1D
+ /*! Returns true if the Interface1D i1 and i2 belong
+ * to the same shape.
+ */
+ class SameShapeIdBP1D : public BinaryPredicate1D
+ {
+ public:
+ /*! Returns the string "SameShapeIdBP1D"*/
+ string getName() const {
+ return "SameShapeIdBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ set<ViewShape*> shapes1;
+ Functions1D::getShapeF1D(i1, shapes1);
+ set<ViewShape*> shapes2;
+ Functions1D::getShapeF1D(i2, shapes2);
+ // FIXME:// n2 algo, can do better...
+ for(set<ViewShape*>::iterator s=shapes1.begin(), send=shapes1.end();
+ s!=send;
+ ++s){
+ Id current = (*s)->getId();
+ for(set<ViewShape*>::iterator s2=shapes2.begin(), s2end=shapes2.end();
+ s2!=s2end;
+ ++s2){
+ if((*s2)->getId() == current) {
+ result = true;
+ return 0;
+ }
+ }
+ }
+ result = false;
+ return 0;
+ }
+ };
+
+ // ViewMapGradientNormBP1D
+ /*! Returns true if the evaluation of the
+ * Gradient norm Function is higher for Interface1D i1
+ * than for i2.
+ */
+ class ViewMapGradientNormBP1D : public BinaryPredicate1D
+ {
+ private:
+ Functions1D::GetViewMapGradientNormF1D _func;
+ public:
+ ViewMapGradientNormBP1D(int level, IntegrationType iType=MEAN, float sampling=2.0)
+ : BinaryPredicate1D(), _func(level, iType, sampling) {
+ }
+ /*! Returns the string "ViewMapGradientNormBP1D"*/
+ string getName() const {
+ return "ViewMapGradientNormBP1D";
+ }
+ /*! The () operator. */
+ int operator()(Interface1D& i1, Interface1D& i2) {
+ if (_func(i1) < 0)
+ return -1;
+ real n1 = _func.result;
+ if (_func(i2) < 0)
+ return -1;
+ real n2 = _func.result;
+ result = (n1 > n2);
+ return 0;
+ }
+ };
+} // end of namespace Predicates1D
+
+#endif // PREDICATES1D_H
diff --git a/source/blender/freestyle/intern/stroke/QInformationMap.h b/source/blender/freestyle/intern/stroke/QInformationMap.h
new file mode 100755
index 00000000000..ef068f15061
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/QInformationMap.h
@@ -0,0 +1,58 @@
+//
+// Filename : QInformationMap.h
+// Author : Stephane Grabli
+// Purpose : Class defining an information map using a QImage
+// Date of creation : 04/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 QINFORMATIONMAP_H
+# define QINFORMATIONMAP_H
+
+# include <qimage.h>
+# include "InformationMap.h"
+
+class QInformationMap : public InformationMap
+{
+private:
+ QImage _map; // the image or a piece of image
+
+public:
+ QInformationMap();
+ QInformationMap(const QImage&);
+ QInformationMap(const QInformationMap&);
+ QInformationMap& operator=(const QInformationMap&);
+
+ //float getSmoothedPixel(int x, int y, float sigma = 0.2f)
+ virtual float getMean(int x, int y) ;
+ virtual void retrieveMeanAndVariance(int x, int y, float &oMean, float &oVariance) ;
+
+ inline const QImage& map() const {return _map;}
+ inline void setMap(const QImage& iMap, float iw, float ih) {_map = iMap.copy();_w=iw;_h=ih;}
+
+protected:
+ virtual float computeGaussian(int x, int y);
+};
+
+#endif // QINFORMATIONMAP_H
diff --git a/source/blender/freestyle/intern/stroke/Stroke.cpp b/source/blender/freestyle/intern/stroke/Stroke.cpp
new file mode 100755
index 00000000000..f6cefdfee34
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Stroke.cpp
@@ -0,0 +1,953 @@
+
+//
+// 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 "Stroke.h"
+#include "StrokeRenderer.h"
+#include "StrokeIterators.h"
+#include "StrokeAdvancedIterators.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* StrokeAttribute */
+ /* */
+ /* */
+ /**********************************/
+
+StrokeAttribute::StrokeAttribute()
+{
+ int i;
+ _alpha = 1.f;
+ _thickness[0] = 1.f;
+ _thickness[1] = 1.f;
+ for(i=0; i<3; ++i)
+ _color[i] = 0.2f;
+ _color[0]=0.8;
+ _userAttributesReal = 0;
+ _userAttributesVec2f = 0;
+ _userAttributesVec3f = 0;
+ _visible = true;
+}
+StrokeAttribute::StrokeAttribute(const StrokeAttribute& iBrother)
+{
+ _alpha = iBrother._alpha;
+ _thickness[0] = iBrother._thickness[0];
+ _thickness[1] = iBrother._thickness[1];
+ for(int i=0; i<3; ++i)
+ _color[i] = iBrother._color[i];
+ _visible = iBrother._visible;
+ if(iBrother._userAttributesReal)
+ _userAttributesReal = new realMap(*iBrother._userAttributesReal);
+ else
+ _userAttributesReal = 0;
+ if(iBrother._userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f);
+ else
+ _userAttributesVec2f = 0;
+ if(iBrother._userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f);
+ else
+ _userAttributesVec3f = 0;
+}
+StrokeAttribute::StrokeAttribute( float iRColor, float iGColor, float iBColor,
+ float iAlpha,
+ float iRThickness, float iLThickness)
+{
+ _color[0] = iRColor;
+ _color[1] = iGColor;
+ _color[2] = iBColor;
+
+ _alpha = iAlpha;
+
+ _thickness[0] = iRThickness;
+ _thickness[1] = iLThickness;
+
+ _visible = true;
+
+ _userAttributesReal = 0;
+ _userAttributesVec2f = 0;
+ _userAttributesVec3f = 0;
+}
+StrokeAttribute::StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t)
+
+{
+
+ _alpha = (1-t)*a1._alpha + t*a2._alpha;
+ _thickness[0] = (1-t)*a1._thickness[0] + t*a2._thickness[0];
+ _thickness[1] = (1-t)*a1._thickness[1] + t*a2._thickness[1];
+ for(int i=0; i<3; ++i)
+ _color[i] = (1-t)*a1._color[i] + t*a2._color[i];
+
+ _visible = true;
+
+ // FIXME: a verifier (et a ameliorer)
+ if((a1._userAttributesReal) && (a2._userAttributesReal)){
+ if(a1._userAttributesReal->size() == a2._userAttributesReal->size()){
+ _userAttributesReal = new realMap;
+ realMap::iterator it1=a1._userAttributesReal->begin(), it1end=a1._userAttributesReal->end();
+ realMap::iterator it2=a2._userAttributesReal->begin(), it2end=a2._userAttributesReal->end();
+ for(; (it1!=it1end); ++it1){
+ (*_userAttributesReal)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second);
+ }
+ }
+ }else{
+ _userAttributesReal = 0;
+ }
+ if((a1._userAttributesVec2f) && (a2._userAttributesVec2f)){
+ if(a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()){
+ _userAttributesVec2f = new Vec2fMap;
+ Vec2fMap::iterator it1=a1._userAttributesVec2f->begin(), it1end=a1._userAttributesVec2f->end();
+ Vec2fMap::iterator it2=a2._userAttributesVec2f->begin(), it2end=a2._userAttributesVec2f->end();
+ for(; (it1!=it1end); ++it1){
+ (*_userAttributesVec2f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second);
+ }
+ }
+ }else{
+ _userAttributesVec2f = 0;
+ }
+ if((a1._userAttributesVec3f) && (a2._userAttributesVec3f)){
+ if(a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()){
+ _userAttributesVec3f = new Vec3fMap;
+ Vec3fMap::iterator it1=a1._userAttributesVec3f->begin(), it1end=a1._userAttributesVec3f->end();
+ Vec3fMap::iterator it2=a2._userAttributesVec3f->begin(), it2end=a2._userAttributesVec3f->end();
+ for(; (it1!=it1end); ++it1){
+ (*_userAttributesVec3f)[(*it1).first] = ((1-t)*(*it1).second+t*(*it2).second);
+ }
+ }
+ }else{
+ _userAttributesVec3f = 0;
+ }
+}
+
+StrokeAttribute::~StrokeAttribute()
+{
+ if(_userAttributesReal){
+ _userAttributesReal->clear();
+ delete _userAttributesReal;
+ }
+ if(_userAttributesVec2f){
+ _userAttributesVec2f->clear();
+ delete _userAttributesVec2f;
+ }
+ if(_userAttributesVec3f){
+ _userAttributesVec3f->clear();
+ delete _userAttributesVec3f;
+ }
+}
+
+StrokeAttribute& StrokeAttribute::operator=(const StrokeAttribute& iBrother)
+{
+ int i;
+ _alpha = iBrother._alpha;
+ _thickness[0] = iBrother._thickness[0];
+ _thickness[1] = iBrother._thickness[1];
+ for(i=0; i<3; ++i)
+ _color[i] = iBrother._color[i];
+ _visible = iBrother._visible;
+ if(iBrother._userAttributesReal){
+ if(!_userAttributesReal)
+ _userAttributesReal = new realMap;
+ _userAttributesReal = new realMap(*(iBrother._userAttributesReal));
+ }else{
+ _userAttributesReal = 0;
+ }
+ if(iBrother._userAttributesVec2f){
+ if(!_userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap;
+ _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f));
+ }else{
+ _userAttributesVec2f = 0;
+ }
+ if(iBrother._userAttributesVec3f){
+ if(!_userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap;
+ _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f));
+ }else{
+ _userAttributesVec3f = 0;
+ }
+ return *this;
+}
+
+float StrokeAttribute::getAttributeReal(const char *iName) const{
+ if(!_userAttributesReal){
+ cout << "StrokeAttribute warning: no real attribute was defined"<< endl;
+ return 0;
+ }
+ realMap::iterator a = _userAttributesReal->find(iName);
+ if(a ==_userAttributesReal->end()){
+ cout << "StrokeAttribute warning: no real attribute was added with the name " << iName << endl;
+ return 0;
+ }
+ return (*a).second;
+}
+Vec2f StrokeAttribute::getAttributeVec2f(const char *iName) const{
+ if(!_userAttributesVec2f){
+ cout << "StrokeAttribute warning: no Vec2f attribute was defined "<< endl;
+ return 0;
+ }
+ Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
+ if(a ==_userAttributesVec2f->end()){
+ cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName << endl;
+ return 0;
+ }
+ return (*a).second;
+}
+Vec3f StrokeAttribute::getAttributeVec3f(const char *iName) const{
+ if(!_userAttributesVec3f){
+ cout << "StrokeAttribute warning: no Vec3f attribute was defined"<< endl;
+ return 0;
+ }
+ Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
+ if(a ==_userAttributesVec3f->end()){
+ cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName << endl;
+ return 0;
+ }
+ return (*a).second;
+}
+bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const{
+ if(!_userAttributesReal){
+ return false;
+ }
+ realMap::iterator a = _userAttributesReal->find(iName);
+ if(a ==_userAttributesReal->end()){
+ return false;
+ }
+ return true;
+}
+bool StrokeAttribute::isAttributeAvailableVec2f(const char *iName) const{
+ if(!_userAttributesVec2f){
+ return false;
+ }
+ Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
+ if(a ==_userAttributesVec2f->end()){
+ return false;
+ }
+ return true;
+}
+bool StrokeAttribute::isAttributeAvailableVec3f(const char *iName) const{
+ if(!_userAttributesVec3f){
+ return false;
+ }
+ Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
+ if(a ==_userAttributesVec3f->end()){
+ return false;
+ }
+ return true;
+}
+void StrokeAttribute::setAttributeReal(const char *iName, float att){
+ if(!_userAttributesReal)
+ _userAttributesReal = new realMap;
+ (*_userAttributesReal)[iName] = att;
+}
+void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f& att){
+ if(!_userAttributesVec2f)
+ _userAttributesVec2f = new Vec2fMap;
+ (*_userAttributesVec2f)[iName] = att;
+}
+void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f& att){
+ if(!_userAttributesVec3f)
+ _userAttributesVec3f = new Vec3fMap;
+ (*_userAttributesVec3f)[iName] = att;
+}
+ /**********************************/
+ /* */
+ /* */
+ /* StrokeVertex */
+ /* */
+ /* */
+ /**********************************/
+
+StrokeVertex::StrokeVertex()
+
+:CurvePoint()
+{
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+}
+
+
+
+StrokeVertex::StrokeVertex(const StrokeVertex& iBrother)
+
+:CurvePoint(iBrother)
+{
+ _Attribute = iBrother._Attribute;
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+}
+StrokeVertex::StrokeVertex(SVertex *iSVertex)
+
+:CurvePoint(iSVertex,0,0.f)
+
+{
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+
+}
+
+
+
+StrokeVertex::StrokeVertex(CurvePoint *iPoint)
+
+:CurvePoint(*iPoint)
+
+{
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+
+}
+
+
+
+StrokeVertex::StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3)
+
+:CurvePoint(iA,iB,t3)
+
+{
+
+ // interpolate attributes:
+
+ _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3);
+ _CurvilignAbscissa = (1-t3)*iA->curvilinearAbscissa()+t3*iB->curvilinearAbscissa();
+ _StrokeLength = iA->strokeLength();
+
+}
+
+
+
+StrokeVertex::StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute)
+
+:CurvePoint(iSVertex,0,0.f)
+
+{
+
+ _Attribute = iAttribute;
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+
+}
+StrokeVertex::~StrokeVertex()
+{
+}
+
+StrokeVertex& StrokeVertex::operator=(const StrokeVertex& iBrother)
+{
+ ((CurvePoint*)this)->operator=(iBrother);
+ _Attribute = iBrother._Attribute;
+
+ _CurvilignAbscissa = 0.f;
+
+ _StrokeLength = 0.f;
+ return *this;
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* Stroke */
+ /* */
+ /* */
+ /**********************************/
+
+Stroke::Stroke()
+{
+ _Length = 0;
+ _id = 0;
+ _sampling = FLT_MAX;
+ //_mediumType = DEFAULT_STROKE;
+ _mediumType = OPAQUE_MEDIUM;
+ _textureId = 0;
+ _tips = false;
+ _rep = 0;
+}
+
+Stroke::Stroke(const Stroke& iBrother)
+{
+ for(vertex_container::const_iterator v=iBrother._Vertices.begin(), vend=iBrother._Vertices.end();
+ v!=vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = 0;
+ _id = iBrother._id;
+ _ViewEdges = iBrother._ViewEdges;
+ _sampling = iBrother._sampling;
+ _mediumType = iBrother._mediumType;
+ _textureId = iBrother._textureId;
+ _tips = iBrother._tips;
+ if(iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ else
+ _rep = 0;
+
+}
+
+Stroke::~Stroke()
+{
+ if(!_Vertices.empty())
+ {
+ for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end();
+ v!=vend;
+ v++)
+ {
+ delete (*v);
+ }
+ _Vertices.clear();
+ }
+
+ _ViewEdges.clear();
+ if(_rep != 0)
+ {
+ delete _rep;
+ _rep = 0;
+ }
+}
+
+Stroke& Stroke::operator=(const Stroke& iBrother)
+{
+ if(!_Vertices.empty())
+ _Vertices.clear();
+
+ for(vertex_container::const_iterator v=iBrother._Vertices.begin(), vend=iBrother._Vertices.end();
+ v!=vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = iBrother._Length;
+ _id = iBrother._id;
+ _ViewEdges = iBrother._ViewEdges;
+ _sampling = iBrother._sampling;
+ if(_rep) delete _rep;
+ if(iBrother._rep)
+ _rep = new StrokeRep(*(iBrother._rep));
+ return *this;
+}
+
+
+void Stroke::setLength(float iLength)
+{
+ _Length = iLength;
+ for(vertex_container::iterator v=_Vertices.begin(), vend=_Vertices.end();
+ v!=vend;
+ ++v)
+ {
+ (*v)->setStrokeLength(iLength);
+ }
+}
+
+float Stroke::ComputeSampling(int iNVertices)
+{
+ if(iNVertices <= (int)_Vertices.size()) //soc
+ return _sampling;
+
+ float sampling = _Length/(float)(iNVertices-_Vertices.size()+1);
+ return sampling;
+}
+
+class StrokeSegment
+{
+public:
+ StrokeInternal::StrokeVertexIterator _begin;
+ StrokeInternal::StrokeVertexIterator _end;
+ float _length;
+ int _n;
+ float _sampling;
+ bool _resampled;
+
+ StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin,
+ StrokeInternal::StrokeVertexIterator iend,
+ float ilength,
+ int in,
+ float isampling)
+ {
+ _begin=ibegin;
+ _end=iend;
+ _length=ilength;
+ _n=in;
+ _sampling = isampling;
+ _resampled = false;
+ }
+};
+
+void Stroke::Resample(int iNPoints)
+{
+ int vertsize = strokeVerticesSize();
+ if(iNPoints <= vertsize)
+ return;
+
+ StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator next = it;++next;
+ StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd();
+
+ vertex_container newVertices;
+ real t=0.f;
+ StrokeVertex * newVertex = 0;
+ vector<StrokeSegment> strokeSegments;
+ int N=0;
+ float meanlength = 0;
+ int nsegments = 0;
+ while(((it!=itend)&&(next!=itend)))
+ {
+ Vec3r a((it)->point2d());
+ Vec3r b((next)->point2d());
+ Vec3r vec_tmp(b - a);
+ real norm_var = vec_tmp.norm();
+ int numberOfPointsToAdd = (int)floor((iNPoints-strokeVerticesSize())*norm_var/_Length);
+ float csampling = norm_var/(float)(numberOfPointsToAdd+1);
+ strokeSegments.push_back(StrokeSegment(it,next,norm_var,numberOfPointsToAdd, csampling));
+ N+=numberOfPointsToAdd;
+ meanlength += norm_var;
+ ++nsegments;
+ ++it; ++next;
+ }
+ meanlength /= (float)nsegments;
+
+ // if we don't have enough points let's resample
+ // finer some segments
+ int NPointsToAdd = iNPoints-vertsize;
+ bool checkEveryone = false;
+ while(N < NPointsToAdd)
+ {
+ for(vector<StrokeSegment>::iterator s=strokeSegments.begin(), send=strokeSegments.end();
+ s!=send;
+ ++s)
+ {
+ if(s->_sampling == 0.f)
+ continue;
+
+ if(s->_resampled == false)
+ {
+ if((!checkEveryone) && (s->_length < meanlength))
+ continue;
+ //resample
+ s->_n = s->_n+1;
+ s->_sampling = s->_length/(float)(s->_n+1);
+ s->_resampled = true;
+ N++;
+ if(N == NPointsToAdd)
+ break;
+ }
+ }
+ checkEveryone = true;
+ }
+ //actually resample:
+ for(vector<StrokeSegment>::iterator s=strokeSegments.begin(), send=strokeSegments.end();
+ s!=send;
+ ++s)
+ {
+ newVertices.push_back(&(*(s->_begin)));
+ if(s->_sampling < _sampling)
+ _sampling = s->_sampling;
+
+ t = s->_sampling/s->_length;
+ for(int i=0; i<s->_n; ++i)
+ {
+ newVertex = new StrokeVertex(&(*(s->_begin)),&(*(s->_end)),t);
+ newVertices.push_back(newVertex);
+ t += s->_sampling/s->_length;
+ }
+ it=s->_begin;
+ next=s->_end;
+ }
+
+ // add last:
+ ++it;++next;
+ if((it != itend) && (next == itend))// && (t == 0.f))
+ newVertices.push_back(&(*it));
+
+ int newsize = newVertices.size();
+ if(newsize != iNPoints)
+ cerr << "Warning: incorrect points number" << endl;
+
+ _Vertices.clear();
+ _Vertices = newVertices;
+ newVertices.clear();
+
+ if(_rep)
+ {
+ delete _rep;
+ _rep = new StrokeRep(this);
+ }
+}
+
+
+void Stroke::Resample(float iSampling)
+{
+ // cerr<<"old size :"<<strokeVerticesSize()<<endl;
+ if(iSampling == 0)
+
+ return;
+ if(iSampling >= _sampling)
+ return ;
+
+ _sampling = iSampling;
+ // Resample...
+ //real curvilinearLength = 0.f;
+ vertex_container newVertices;
+ real t=0.f;
+ StrokeVertex * newVertex = 0;
+ StrokeInternal::StrokeVertexIterator it = strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator next = it;++next;
+ StrokeInternal::StrokeVertexIterator itend = strokeVerticesEnd();
+ while(((it!=itend)&&(next!=itend)))
+ {
+ newVertices.push_back(&(*it));
+ Vec3r a((it)->point2d());
+ Vec3r b((next)->point2d());
+ Vec3r vec_tmp(b - a);
+ real norm_var = vec_tmp.norm();
+ if(norm_var <= _sampling)
+ {
+ //curvilinearLength += norm_var;
+ ++it; ++next;
+ continue;
+ }
+
+ //curvilinearLength += _sampling;
+ t = _sampling/norm_var;
+ float limit = 0.99f;
+ while(t<limit)
+ {
+ newVertex = new StrokeVertex(&(*it),&(*next),t);
+ //newVertex->setCurvilinearAbscissa(curvilinearLength);
+ newVertices.push_back(newVertex);
+ t = t + _sampling/norm_var;
+ }
+ ++it; ++next;
+ }
+ // add last:
+ if((it != itend) && (next == itend))// && (t == 0.f))
+ newVertices.push_back(&(*it));
+
+ _Vertices.clear();
+ _Vertices = newVertices;
+ newVertices.clear();
+
+ if(_rep)
+ {
+ delete _rep;
+ _rep = new StrokeRep(this);
+ }
+}
+
+void Stroke::RemoveVertex(StrokeVertex *iVertex)
+{
+ vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
+ for(;
+ it!=itend;
+ ++it)
+ {
+ if((*it) == iVertex)
+ {
+ delete iVertex;
+ it = _Vertices.erase(it); // it is now the element just after the erased element
+ break;
+ }
+ }
+ // recompute various values (length, curvilign abscissa)
+ float curvabsc = 0.f;
+ it=_Vertices.begin();
+ itend=_Vertices.end();
+ vertex_container::iterator previous=it;
+ for(;
+ (it!=itend);
+ ++it)
+ {
+ if(it != previous)
+ curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm();
+ (*it)->setCurvilinearAbscissa(curvabsc);
+ previous = it;
+ }
+ _Length = curvabsc;
+ it=_Vertices.begin();
+ for(;
+ (it!=itend);
+ ++it)
+ {
+ (*it)->setStrokeLength(_Length);
+ }
+}
+
+void Stroke::InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
+{
+ vertex_container::iterator it=_Vertices.begin(), itend=_Vertices.end();
+
+ vertex_container::iterator itnext = next.getIt();
+ _Vertices.insert(itnext, iVertex);
+ // recompute various values (length, curvilign abscissa)
+ float curvabsc = 0.f;
+ it=_Vertices.begin();
+ itend=_Vertices.end();
+ vertex_container::iterator previous=it;
+ for(;
+ (it!=itend);
+ ++it)
+ {
+ curvabsc += ((*it)->point2d()-(*previous)->point2d()).norm();
+ (*it)->setCurvilinearAbscissa(curvabsc);
+ previous = it;
+ }
+ _Length = curvabsc;
+ for(;
+ (it!=itend);
+ ++it)
+ {
+ (*it)->setStrokeLength(_Length);
+ }
+}
+
+//! embedding vertex iterator
+Stroke::const_vertex_iterator Stroke::vertices_begin() const { return const_vertex_iterator(_Vertices.begin(),_Vertices.begin(), _Vertices.end()); }
+Stroke::const_vertex_iterator Stroke::vertices_end() const { return const_vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); }
+Stroke::vertex_iterator Stroke::vertices_end() { return vertex_iterator(_Vertices.end(),_Vertices.begin(), _Vertices.end()); }
+
+StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesBegin(float t) {
+ if((t!=0) && (t < _sampling))
+ Resample(t);
+ return StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end());
+}
+
+StrokeInternal::StrokeVertexIterator Stroke::strokeVerticesEnd() {
+ return StrokeInternal::StrokeVertexIterator(this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end());
+}
+
+Interface0DIterator Stroke::verticesBegin() {
+ Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.begin(),
+ this->_Vertices.begin(),
+ this->_Vertices.end()));
+ return ret;
+}
+
+Interface0DIterator Stroke::verticesEnd() {
+ Interface0DIterator ret(new StrokeInternal::StrokeVertexIterator(this->_Vertices.end(),
+ this->_Vertices.begin(),
+ this->_Vertices.end()));
+ return ret;
+}
+
+Interface0DIterator Stroke::pointsBegin(float t) {
+ return verticesBegin(); // FIXME
+}
+
+Interface0DIterator Stroke::pointsEnd(float t) {
+ return verticesEnd();
+}
+
+void Stroke::Render(const StrokeRenderer *iRenderer)
+{
+ if(!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRep(_rep);
+}
+
+void Stroke::RenderBasic(const StrokeRenderer *iRenderer)
+{
+ if(!_rep)
+ _rep = new StrokeRep(this);
+ iRenderer->RenderStrokeRepBasic(_rep);
+}
+
+Stroke::vertex_iterator Stroke::vertices_begin(float sampling)
+{
+ // Resample if necessary
+ if((sampling != 0) && (sampling < _sampling))
+ Resample(sampling);
+ return vertex_iterator(_Vertices.begin(),_Vertices.begin(),_Vertices.end());
+ //return _Vertices.begin();
+}
+//
+//Stroke::vertex_iterator Stroke::vertices_last()
+//{
+// vertex_iterator res = vertices_begin();
+// vertex_iterator next = res;++next;
+// while(!next.end())
+// {
+// ++next;
+// ++res;
+// }
+// return res;
+//}
+//
+//Stroke::const_vertex_iterator Stroke::vertices_last() const
+//{
+// const_vertex_iterator res = vertices_begin();
+// const_vertex_iterator next = res;++next;
+// while(!next.end())
+// {
+// ++next;
+// ++res;
+// }
+// return res;
+//}
+
+//Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling)
+//{
+// // Resample if necessary
+// if(sampling < _sampling)
+// Resample(sampling);
+// return _Vertices.rbegin();
+//}
+
+
+//inline Vec3r shaded_color(int iCombination = 0) const ;
+//inline Vec<3,real> Stroke::orientation2d(const_vertex_iterator it) const
+//{
+// return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it);
+//}
+// Vec3r Stroke::orientation2d(int iCombination) const
+// {
+// return edge_orientation2d_function<Stroke>(*this, iCombination);
+// }
+//inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const
+//{
+// return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it);
+//}
+// Vec3r Stroke::orientation3d(int iCombination) const
+// {
+// return edge_orientation3d_function<Stroke>(*this, iCombination);
+// }
+
+//Material Stroke::material() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=strokeVerticesEnd();
+// Material mat = (*v)->material();
+// for(;v!=vend;++v)
+// {
+// if(mat != (*v)->material())
+// Exception::raiseException();
+// }
+// return mat;
+//}
+
+//int Stroke::qi() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// int qi_= (*v)->qi();
+// for(;v!=vend;++v)
+// {
+// if((*v)->qi() != qi_)
+// Exception::raiseException();
+// }
+// return qi_;
+//}
+//inline occluder_container::const_iterator occluders_begin() const {return _FEdgeA->occluders().begin();}
+//inline occluder_container::const_iterator occluders_end() const {return _FEdgeA->occluders().end();}
+
+//int Stroke::occluders_size() const
+//{
+// return qi();
+//}
+//
+//bool Stroke::occluders_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occluders_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluders_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+////inline const polygon3d& occludee() const {return *(_FEdgeA->aFace());}
+//const SShape * Stroke::occluded_shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->occluded_shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occluded_shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+//
+//const bool Stroke::occludee_empty() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// bool empty = (*v)->occludee_empty();
+// for(;v!=vend;++v)
+// {
+// if((*v)->occludee_empty() != empty)
+// Exception::raiseException();
+// }
+// return empty;
+//}
+
+//const SShape * Stroke::shape() const
+//{
+// const_vertex_iterator v=vertices_begin(), vend=vertices_end();
+// const SShape *sshape = (*v)->shape();
+// for(;v!=vend;++v)
+// {
+// if((*v)->shape() != sshape)
+// Exception::raiseException();
+// }
+// return sshape;
+//}
+
+// real Stroke::z_discontinuity(int iCombination) const
+// {
+// return z_discontinuity_edge_function<Stroke>(*this, iCombination);
+// }
+
+// Vec3r Stroke::curvature2d_as_vector(int iCombination) const
+// {
+// return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination);
+// }
+
+// real Stroke::curvature2d_as_angle(int iCombination) const
+// {
+// return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination);
+// }
+
+// float Stroke::shape_importance(int iCombination) const
+// {
+// return shape_importance_edge_function<Stroke>(*this, iCombination);
+// }
+
+
+// float Stroke::local_average_depth(int iCombination ) const
+// {
+// return local_average_depth_edge_function<Stroke >(*this, iCombination);
+// }
+
+// float Stroke::local_depth_variance(int iCombination) const
+// {
+// return local_depth_variance_edge_function<Stroke>(*this, iCombination);
+// }
+
+// real Stroke::local_average_density(float sigma , int iCombination ) const
+// {
+// return density_edge_function<Stroke>(*this, iCombination);
+// }
diff --git a/source/blender/freestyle/intern/stroke/Stroke.h b/source/blender/freestyle/intern/stroke/Stroke.h
new file mode 100755
index 00000000000..5e0974edea7
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/Stroke.h
@@ -0,0 +1,588 @@
+//
+// Filename : Stroke.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a stroke
+// Date of creation : 09/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 STROKE_H
+# define STROKE_H
+
+# include "../view_map/Silhouette.h"
+# include <vector>
+# include <map>
+# include "../system/FreestyleConfig.h"
+# include "Curve.h"
+# include "../view_map/Interface1D.h"
+# include "../system/StringUtils.h"
+
+
+//
+// StrokeAttribute
+//
+////////////////////////////////////////////////////////
+
+/*! Class to define an attribute associated to a Stroke Vertex.
+ * This attribute stores the color, alpha and thickness values
+ * for a Stroke Vertex.
+ */
+class LIB_STROKE_EXPORT StrokeAttribute
+{
+public:
+
+ /*! default constructor */
+ StrokeAttribute();
+ /*! Copy constructor */
+ StrokeAttribute(const StrokeAttribute& iBrother);
+ /*! Builds a stroke vertex attribute from
+ * a set of parameters.
+ * \param iRColor
+ * The Red Component value.
+ * \param iGColor
+ * The Green Component value.
+ * \param iBColor
+ * The Blue Component value.
+ * \param iAlpha
+ * The transparency value
+ * \param iRThickness
+ * The thickness of the stroke on the right
+ * \param iLThickness
+ * The Thickness of the stroke on the left
+ */
+ StrokeAttribute(float iRColor, float iGColor, float iBColor,
+ float iAlpha,
+ float iRThickness, float iLThickness);
+
+ /*! Interpolation constructor.
+ * Builds a StrokeAttribute from two
+ * StrokeAttributes and an interpolation parameter.
+ * \param a1
+ * The first Attribute.
+ * \param a2
+ * The second parameter.
+ * \param t
+ * The interpolation parameter.
+ */
+ StrokeAttribute(const StrokeAttribute& a1, const StrokeAttribute& a2, float t);
+
+ /*! destructor */
+ virtual ~StrokeAttribute();
+
+ /* operators */
+ /*! operator = */
+ StrokeAttribute& operator=(const StrokeAttribute& iBrother);
+
+ /* accessors */
+ /*! Returns the attribute's color.
+ * \return The array of 3 floats containing the R,G,B values
+ * of the attribute's color.
+ */
+ inline const float* getColor() const { return _color; }
+ /*! Returns the R color component. */
+ inline const float getColorR() const { return _color[0]; }
+ /*! Returns the G color component. */
+ inline const float getColorG() const { return _color[1]; }
+ /*! Returns the B color component. */
+ inline const float getColorB() const { return _color[2]; }
+ /*! Returns the RGB color components. */
+ inline Vec3f getColorRGB() const { return Vec3f(_color[0], _color[1], _color[2]); }
+ /*! Returns the alpha color component. */
+ inline float getAlpha() const { return _alpha; }
+ /*! Returns the attribute's thickness.
+ * \return an array of 2 floats. the first value is
+ * the thickness on the right of the vertex when following
+ * the stroke, the second one is the thickness on the left.
+ */
+ inline const float* getThickness() const { return _thickness; }
+ /*! Returns the thickness on the right of the vertex when following the
+ * stroke. */
+ inline const float getThicknessR() const { return _thickness[0]; }
+ /*! Returns the thickness on the left of the vertex when following the
+ * stroke. */
+ inline const float getThicknessL() const { return _thickness[1]; }
+ /*! Returns the thickness on the right and on the left of the vertex when following the
+ * stroke. */
+ inline Vec2f getThicknessRL() const { return Vec2f(_thickness[0], _thickness[1]); }
+
+ /*! Returns true if the strokevertex is visible, false otherwise */
+ inline bool isVisible() const {return _visible;}
+
+ /*! Returns an attribute of type real
+ * \param iName
+ * The name of the attribute
+ */
+ float getAttributeReal(const char *iName) const;
+ /*! Returns an attribute of type Vec2f
+ * \param iName
+ * The name of the attribute
+ */
+ Vec2f getAttributeVec2f(const char *iName) const;
+ /*! Returns an attribute of type Vec3f
+ * \param iName
+ * The name of the attribute
+ */
+ Vec3f getAttributeVec3f(const char *iName) const;
+
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableReal(const char *iName) const ;
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableVec2f(const char *iName) const ;
+ /*! Checks whether the attribute iName is availbale */
+ bool isAttributeAvailableVec3f(const char *iName) const ;
+
+ /* modifiers */
+ /*! sets the attribute's color.
+ * \param r
+ * The new R value.
+ * \param g
+ * The new G value.
+ * \param b
+ * The new B value.
+ */
+ inline void setColor(float r, float g, float b) { _color[0]=r; _color[1]=g; _color[2]=b; }
+ /*! sets the attribute's color.
+ * \param iRGB
+ * The new RGB values.
+ */
+ inline void setColor(const Vec3f& iRGB) { _color[0]=iRGB[0]; _color[1]=iRGB[1]; _color[2]=iRGB[2]; }
+ /*! sets the attribute's alpha value.
+ * \param alpha
+ * The new alpha value.
+ */
+ inline void setAlpha(float alpha) { _alpha = alpha; }
+ /*! sets the attribute's thickness.
+ * \param tr
+ * The thickness on the right of the vertex when following the stroke.
+ * \param tl
+ * The thickness on the left of the vertex when following the stroke.
+ */
+ inline void setThickness(float tr, float tl) { _thickness[0]=tr; _thickness[1]=tl; }
+ /*! sets the attribute's thickness.
+ * \param tRL
+ * The thickness on the right and on the left of the vertex when following the stroke.
+ */
+ inline void setThickness(const Vec2f& tRL) { _thickness[0]=tRL[0]; _thickness[1]=tRL[1]; }
+
+ /*! sets the visible flag. True means visible. */
+ inline void setVisible(bool iVisible){ _visible = iVisible; }
+
+ /*! Adds a user defined attribute of type real
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeReal(const char *iName, float att);
+ /*! Adds a user defined attribute of type Vec2f
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeVec2f(const char *iName, const Vec2f& att);
+ /*! Adds a user defined attribute of type Vec3f
+ * If there is no attribute of name iName, it is added.
+ * Otherwise, the new value replaces the old one.
+ * \param iName
+ * The name of the attribute
+ * \param att
+ * The attribute's value
+ */
+ void setAttributeVec3f(const char *iName, const Vec3f& att);
+
+private:
+
+ typedef std::map<const char*, float, StringUtils::ltstr> realMap ;
+ typedef std::map<const char*, Vec2f, StringUtils::ltstr> Vec2fMap ;
+ typedef std::map<const char*, Vec3f, StringUtils::ltstr> Vec3fMap ;
+
+ float _color[3]; //! the color
+ float _alpha; //! alpha
+ float _thickness[2]; //! the thickness on the right and on the left of the backbone vertex (the stroke is oriented)
+ bool _visible;
+ realMap *_userAttributesReal;
+ Vec2fMap *_userAttributesVec2f;
+ Vec3fMap *_userAttributesVec3f;
+};
+
+
+//
+// StrokeVertex
+//
+////////////////////////////////////////////////////////
+
+/*! Class to define a stroke vertex.
+ */
+class LIB_STROKE_EXPORT StrokeVertex : public CurvePoint
+{
+public: // Implementation of Interface0D
+
+ /*! Returns the string "StrokeVertex"*/
+ virtual string getExactTypeName() const {
+ return "StrokeVertex";
+ }
+
+private:
+
+ StrokeAttribute _Attribute; //! The attribute associated to the vertex
+ float _CurvilignAbscissa; //! the curvilign abscissa
+ float _StrokeLength; // stroke length
+
+public:
+
+ /*! default constructor */
+ StrokeVertex();
+ /*! Copy constructor */
+ StrokeVertex(const StrokeVertex& iBrother);
+ /*! Builds a stroke vertex from a SVertex */
+ StrokeVertex(SVertex *iSVertex);
+ /*! Builds a stroke vertex from a CurvePoint */
+ StrokeVertex(CurvePoint *iPoint);
+ /*! Builds Stroke Vertex from 2 stroke vertices and an interpolation parameter*/
+ StrokeVertex(StrokeVertex *iA, StrokeVertex *iB, float t3);
+ /*! Builds a stroke from a view vertex and an attribute */
+ StrokeVertex(SVertex *iSVertex, const StrokeAttribute& iAttribute);
+ /*! destructor */
+ virtual ~StrokeVertex();
+
+ /* operators */
+ /*! operator = */
+ StrokeVertex& operator=(const StrokeVertex& iBrother);
+
+ /* accessors */
+ /*! Returns the 2D point x coordinate */
+ inline real x() const { return _Point2d[0]; }
+ /*! Returns the 2D point y coordinate */
+ inline real y() const { return _Point2d[1]; }
+ /*! Returns the 2D point coordinates as a Vec2d */
+ Vec2f getPoint () {return Vec2f((float)point2d()[0], (float)point2d()[1]);}
+ /*! Returns the ith 2D point coordinate (i=0 or 1)*/
+ inline real operator[](const int i) const { return _Point2d[i]; }
+ /*! Returns the StrokeAttribute for this StrokeVertex */
+ inline const StrokeAttribute& attribute() const { return _Attribute; }
+ /*! Returns a non-const reference to the StrokeAttribute of this StrokeVertex */
+ inline StrokeAttribute& attribute() {return _Attribute;}
+ /*! Returns the curvilinear abscissa */
+ inline float curvilinearAbscissa() const {return _CurvilignAbscissa;}
+ /*! Returns the length of the Stroke to which this StrokeVertex belongs */
+ inline float strokeLength() const {return _StrokeLength;}
+ /*! Returns the curvilinear abscissa of this StrokeVertex in the Stroke */
+ inline float u() const {return _CurvilignAbscissa/_StrokeLength;}
+
+ /* modifiers */
+ /*! sets the 2D x value */
+ inline void setX(real x) { _Point2d[0]=x; }
+ /*! sets the 2D y value */
+ inline void setY(real y) { _Point2d[1]=y; }
+ /*! sets the 2D x and y values */
+ inline void setPoint(real x, real y) { _Point2d[0]=x; _Point2d[1]=y;}
+ /*! sets the 2D x and y values */
+ inline void setPoint(const Vec2f& p) { _Point2d[0] = p[0];_Point2d[1] = p[1];}
+ /*! Returns a reference to the ith 2D point coordinate (i=0 or 1) */
+ inline real& operator[](const int i) { return _Point2d[i]; }
+ /*! sets the attribute. */
+ inline void setAttribute(const StrokeAttribute& iAttribute) { _Attribute = iAttribute; }
+ /*! sets the curvilinear abscissa of this StrokeVertex in the Stroke */
+ inline void setCurvilinearAbscissa(float iAbscissa) {_CurvilignAbscissa = iAbscissa;}
+ /*! sets the Stroke's length (it's only a value stored by the Stroke Vertex, it won't
+ * change the real Stroke's length.)
+ */
+ inline void setStrokeLength(float iLength) {_StrokeLength = iLength;}
+
+ /* interface definition */
+ /* inherited */
+
+};
+
+
+//
+// Stroke
+//
+////////////////////////////////////////////////////////
+
+class StrokeRenderer;
+class StrokeRep;
+
+namespace StrokeInternal {
+ class vertex_const_traits ;
+ class vertex_nonconst_traits ;
+ template<class Traits> class vertex_iterator_base;
+ class StrokeVertexIterator;
+} // end of namespace StrokeInternal
+
+/*! Class to define a stroke.
+ * A stroke is made of a set of 2D vertices (StrokeVertex), regularly spaced out.
+ * This set of vertices defines the stroke's backbone geometry.
+ * Each of these stroke vertices defines the stroke's shape and appearance
+ * at this vertex position.
+ */
+class LIB_STROKE_EXPORT Stroke : public Interface1D
+{
+public: // Implementation of Interface1D
+
+ /*! Returns the string "Stroke" */
+ virtual string getExactTypeName() const {
+ return "Stroke";
+ }
+
+ // Data access methods
+
+ /*! Returns the Id of the Stroke */
+ virtual Id getId() const {
+ return _id;
+ }
+ /*! The different blending modes
+ * available to similate the interaction
+ * media-medium.
+ */
+ typedef enum{
+ DRY_MEDIUM,/*!< To simulate a dry medium such as Pencil or Charcoal.*/
+ HUMID_MEDIUM,/*!< To simulate ink painting (color substraction blending).*/
+ OPAQUE_MEDIUM, /*!< To simulate an opaque medium (oil, spray...).*/
+ } MediumType;
+
+
+public:
+ typedef std::deque<StrokeVertex*> vertex_container; // the vertices container
+ typedef std::vector<ViewEdge*> viewedge_container; // the viewedges container
+ typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_nonconst_traits > vertex_iterator;
+ typedef StrokeInternal::vertex_iterator_base<StrokeInternal::vertex_const_traits> const_vertex_iterator;
+
+public:
+ //typedef StrokeVertex vertex_type;
+private:
+ vertex_container _Vertices; //! The stroke's backbone vertices
+ Id _id;
+ float _Length; // The stroke length
+ viewedge_container _ViewEdges;
+ float _sampling;
+ StrokeRenderer *_renderer; // mark implementation OpenGL renderer
+ MediumType _mediumType;
+ unsigned int _textureId;
+ bool _tips;
+ Vec2r _extremityOrientations[2]; // the orientations of the first and last extermity
+ StrokeRep *_rep;
+
+public:
+ /*! default constructor */
+ Stroke();
+ /*! copy constructor */
+ Stroke(const Stroke& iBrother);
+ /*! Builds a stroke from a set of StrokeVertex.
+ * This constructor is templated by an iterator type.
+ * This iterator type must allow the vertices parsing
+ * using the ++ operator.
+ * \param iBegin
+ * The iterator pointing to the first vertex.
+ * \param iEnd
+ * The iterator pointing to the end of the vertex list.
+ */
+ template<class InputVertexIterator>
+ Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd);
+
+ /*! Destructor */
+ virtual ~Stroke();
+
+ /* operators */
+ /*! operator = */
+ Stroke& operator=(const Stroke& iBrother);
+
+ /*! Compute the sampling needed to get iNVertices
+ * vertices.
+ * If the specified number of vertices is less than the
+ * actual number of vertices, the actual sampling value is returned.
+ * (To remove Vertices, use the RemoveVertex() method of this class).
+ * \param iNVertices
+ * The number of StrokeVertices we eventually want
+ * in our Stroke.
+ * \return the sampling that must be used in the Resample(float) method.
+ * @see Resample(int)
+ * @see Resample(float)
+ */
+ float ComputeSampling(int iNVertices);
+
+ /*! Resampling method.
+ * Resamples the curve so that it eventually
+ * has iNPoints. That means it is going
+ * to add iNPoints-vertices_size, if vertices_size
+ * is the number of points we already have.
+ * Is vertices_size >= iNPoints, no resampling is done.
+ * \param iNPoints
+ * The number of vertices we eventually want in our stroke.
+ */
+ void Resample(int iNPoints);
+
+ /*! Resampling method.
+ * Resamples the curve with a given sampling.
+ * If this sampling is < to the actual sampling
+ * value, no resampling is done.
+ * \param iSampling
+ * The new sampling value.
+ */
+ void Resample(float iSampling);
+
+ /*! Removes the stroke vertex iVertex
+ * from the stroke.
+ * The length and curvilinear abscissa are updated
+ * consequently.
+ */
+ void RemoveVertex(StrokeVertex *iVertex);
+
+ /*! Inserts the stroke vertex iVertex
+ * in the stroke before next.
+ * The length, curvilinear abscissa are updated
+ * consequently.
+ * \param iVertex
+ * The StrokeVertex to insert in the Stroke.
+ * \param next
+ * A StrokeVertexIterator pointing to the StrokeVeretx before
+ * which iVertex must be inserted.
+ */
+ void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next);
+
+ /* Render method */
+ void Render(const StrokeRenderer *iRenderer );
+ void RenderBasic(const StrokeRenderer *iRenderer );
+
+ /* Iterator definition */
+
+ /* accessors */
+ /*! Returns the 2D length of the Stroke */
+ inline real getLength2D() const {return _Length;}
+ /*! Returns a reference to the time stamp value of the stroke. */
+ /*! Returns the MediumType used for this Stroke. */
+ inline MediumType getMediumType() const {return _mediumType;}
+ /*! Returns the id of the texture used to simulate th marks system
+ * for this Stroke
+ */
+ inline unsigned int getTextureId() {return _textureId;}
+ /*! Returns true if this Stroke uses a texture with tips, false
+ * otherwise.
+ */
+ inline bool hasTips() const {return _tips;}
+ /* these advanced iterators are used only in C++ */
+ inline int vertices_size() const {return _Vertices.size();}
+ inline viewedge_container::const_iterator viewedges_begin() const {return _ViewEdges.begin();}
+ inline viewedge_container::iterator viewedges_begin() {return _ViewEdges.begin();}
+ inline viewedge_container::const_iterator viewedges_end() const {return _ViewEdges.end();}
+ inline viewedge_container::iterator viewedges_end() {return _ViewEdges.end();}
+ inline int viewedges_size() const {return _ViewEdges.size();}
+
+ inline Vec2r getBeginningOrientation() const {return _extremityOrientations[0];}
+ inline real getBeginningOrientationX() const {return _extremityOrientations[0].x();}
+ inline real getBeginningOrientationY() const {return _extremityOrientations[0].y();}
+ inline Vec2r getEndingOrientation() const {return _extremityOrientations[1];}
+ inline real getEndingOrientationX() const {return _extremityOrientations[1].x();}
+ inline real getEndingOrientationY() const {return _extremityOrientations[1].y();}
+
+
+ /* modifiers */
+ /*! sets the Id of the Stroke. */
+ inline void setId(const Id& id) {_id = id;}
+ /*! sets the 2D length of the Stroke. */
+ void setLength(float iLength);
+ /*! sets the medium type that must be used for this Stroke. */
+ inline void setMediumType(MediumType iType) {_mediumType = iType;}
+ /*! sets the texture id to be used to simulate the marks system for this Stroke. */
+ inline void setTextureId(unsigned int id) {_textureId = id;}
+ /*! sets the flag telling whether this stroke is using a texture with
+ * tips or not.
+ */
+ inline void setTips(bool iTips) {_tips = iTips;}
+
+ inline void push_back(StrokeVertex* iVertex) { _Vertices.push_back(iVertex); }
+ inline void push_front(StrokeVertex* iVertex) { _Vertices.push_front(iVertex); }
+ inline void AddViewEdge(ViewEdge *iViewEdge) {_ViewEdges.push_back(iViewEdge);}
+ inline void setBeginningOrientation(const Vec2r& iOrientation) {_extremityOrientations[0] = iOrientation;}
+ inline void setBeginningOrientation(real x, real y) {_extremityOrientations[0] = Vec2r(x,y);}
+ inline void setEndingOrientation(const Vec2r& iOrientation) {_extremityOrientations[1] = iOrientation;}
+ inline void setEndingOrientation(real x, real y) {_extremityOrientations[1] = Vec2r(x,y);}
+
+ /* Information access interface */
+
+ // embedding vertex iterator
+ const_vertex_iterator vertices_begin() const;
+ vertex_iterator vertices_begin(float t=0.f);
+ const_vertex_iterator vertices_end() const;
+ vertex_iterator vertices_end();
+
+ /*! Returns a StrokeVertexIterator pointing on the first StrokeVertex of the
+ * Stroke. One can specifly a sampling value to resample the Stroke
+ * on the fly if needed.
+ * \param t
+ * The resampling value with which we want our Stroke to be resampled.
+ * If 0 is specified, no resampling is done.
+ */
+ StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.f);
+ /*! Returns a StrokeVertexIterator pointing after the last StrokeVertex of the
+ * Stroke.
+ */
+ StrokeInternal::StrokeVertexIterator strokeVerticesEnd();
+ /*! Returns the number of StrokeVertex constituing the Stroke. */
+ inline unsigned int strokeVerticesSize() const {return _Vertices.size();}
+
+ /*! Returns the i-th StrokeVertex constituting the Stroke. */
+ inline StrokeVertex& strokeVerticeAt(unsigned int i) {return *(_Vertices.at(i));}
+
+ // Iterator access (Interface1D)
+ /*! Returns an Interface0DIterator pointing on the first StrokeVertex of the
+ * Stroke.
+ */
+ virtual Interface0DIterator verticesBegin();
+ /*! Returns an Interface0DIterator pointing after the last StrokeVertex of the
+ * Stroke.
+ */
+ virtual Interface0DIterator verticesEnd();
+
+ virtual Interface0DIterator pointsBegin(float t=0.f);
+ virtual Interface0DIterator pointsEnd(float t=0.f);
+};
+
+
+
+//
+// Implementation
+//
+////////////////////////////////////////////////////////
+
+
+template<class InputVertexIterator>
+Stroke::Stroke(InputVertexIterator iBegin, InputVertexIterator iEnd)
+{
+ for(InputVertexIterator v=iBegin, vend=iEnd;
+ v!=vend;
+ v++)
+ {
+ _Vertices.push_back(*v);
+ }
+ _Length = 0;
+ _id = 0;
+}
+
+#endif // STROKE_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
new file mode 100755
index 00000000000..279a0b12089
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeAdvancedIterators.h
@@ -0,0 +1,142 @@
+//
+// Filename : StrokeAdvancedIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Stroke
+// Can't be used in 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 STROKEADVANCEDITERATORS_H
+# define STROKEADVANCEDITERATORS_H
+
+# include "Stroke.h"
+
+namespace StrokeInternal {
+
+ class vertex_const_traits : public Const_traits<StrokeVertex*> {
+ public:
+ typedef std::deque<StrokeVertex*> vertex_container;
+ typedef vertex_container::const_iterator vertex_container_iterator ;
+ };
+ class vertex_nonconst_traits : public Nonconst_traits<StrokeVertex*> {
+ public:
+ typedef std::deque<StrokeVertex*> vertex_container; //! the vertices container
+ typedef vertex_container::iterator vertex_container_iterator ;
+ };
+
+
+ template<class Traits>
+ class vertex_iterator_base : public IteratorBase<Traits,BidirectionalIteratorTag_Traits>
+ {
+ public:
+ typedef vertex_iterator_base<Traits> Self;
+ protected:
+ typedef IteratorBase<Traits,BidirectionalIteratorTag_Traits> parent_class;
+ typedef typename Traits::vertex_container_iterator vertex_container_iterator;
+ typedef vertex_iterator_base<vertex_nonconst_traits> iterator;
+ typedef vertex_iterator_base<vertex_const_traits> const_iterator;
+ //protected:
+ public:
+ vertex_container_iterator _it;
+ vertex_container_iterator _begin;
+ vertex_container_iterator _end;
+ public:
+ friend class Stroke;
+ //friend class vertex_iterator;
+ inline vertex_iterator_base()
+ : parent_class()
+ {}
+ inline vertex_iterator_base(const iterator& iBrother)
+ : parent_class()
+ {_it = iBrother._it;_begin = iBrother._begin;_end = iBrother._end;}
+ inline vertex_iterator_base(const const_iterator& iBrother)
+ : parent_class()
+ {_it = iBrother._it;_begin = iBrother._begin;_end = iBrother._end;}
+ //protected://FIXME
+ public:
+ inline vertex_iterator_base(vertex_container_iterator it, vertex_container_iterator begin, vertex_container_iterator end)
+ : parent_class()
+ {
+ _it = it;
+ _begin = begin;
+ _end = end;
+ }
+
+ public:
+ virtual ~vertex_iterator_base() {}
+
+ virtual bool begin() const {return _it==_begin? true : false;}
+ virtual bool end() const {return _it==_end ? true : false;}
+
+ // operators
+ inline Self& operator++() // operator corresponding to ++i
+ {
+ ++_it;
+ return *(this);
+ }
+ inline Self operator++(int) // opérateur correspondant à i++
+ {
+ Self tmp = *this; // C'est pour cela qu'on stocke la valeur
+ ++_it; // dans un temporaire.
+ return tmp;
+ }
+ inline Self& operator--() // operator corresponding to ++i
+ {
+ --_it;
+ 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
+ --_it; // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const Self& b) const
+ {
+ return (_it != b._it);
+ }
+ virtual bool operator==(const Self& b) const
+ {
+ return !(*this != b);
+ }
+
+ // dereferencing
+ virtual typename Traits::reference operator*() const {return *(_it);}
+ virtual typename Traits::pointer operator->() const { return &(operator*());}
+
+ /*! accessors */
+ inline vertex_container_iterator it() const {return _it;}
+ inline vertex_container_iterator getBegin() const {return _begin;}
+ inline vertex_container_iterator getEnd() const {return _end;}
+ };
+
+} // end of namespace StrokeInternal
+
+
+#endif // STROKEADVANCEDITERATORS_H
+
+
diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.cpp b/source/blender/freestyle/intern/stroke/StrokeIO.cpp
new file mode 100755
index 00000000000..903a198adc2
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIO.cpp
@@ -0,0 +1,55 @@
+//
+// 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 "StrokeIO.h"
+#include "StrokeAdvancedIterators.h"
+
+
+ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute){
+ out << " StrokeAttribute" << endl;
+ out << " color : (" << iStrokeAttribute.getColorR() << "," << iStrokeAttribute.getColorG() << "," << iStrokeAttribute.getColorB() << ")" << endl;
+ out << " alpha : " << iStrokeAttribute.getAlpha() << endl;
+ out << " thickness : " << iStrokeAttribute.getThicknessR() << ", " << iStrokeAttribute.getThicknessL() << endl;
+ out << " visible : " << iStrokeAttribute.isVisible() << endl;
+ return out;
+}
+
+ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex){
+ out << " StrokeVertex" << endl;
+ out << " id : " << iStrokeVertex.getId() << endl;
+ out << " curvilinear length : " << iStrokeVertex.curvilinearAbscissa() << endl;
+ out << " 2d coordinates : (" << iStrokeVertex.getProjectedX() << "," << iStrokeVertex.getProjectedY() << "," << iStrokeVertex.getProjectedZ() << ")" << endl;
+ out << " 3d coordinates : (" << iStrokeVertex.getX() << "," << iStrokeVertex.getY() << "," << iStrokeVertex.getZ() << ")"<< endl;
+ out << iStrokeVertex.attribute() << endl;
+ return out;
+}
+
+ostream& operator<<(ostream& out, const Stroke& iStroke){
+ out << "Stroke" << endl;
+ out << " id : " << iStroke.getId() << endl;
+ out << " length : " << iStroke.getLength2D() << endl;
+ out << " medium type : " << iStroke.getMediumType() << endl;
+ for(Stroke::const_vertex_iterator v=iStroke.vertices_begin(), vend=iStroke.vertices_end();
+ v!=vend;
+ ++v){
+ out << *(*v) << endl;
+ }
+ return out;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeIO.h b/source/blender/freestyle/intern/stroke/StrokeIO.h
new file mode 100755
index 00000000000..150c8340778
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIO.h
@@ -0,0 +1,47 @@
+//
+// Filename : StrokeIO.h
+// Author(s) : Stephane Grabli
+// Purpose : Functions to manage I/O for the stroke
+// Date of creation : 03/02/2004
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 STROKEIO_H
+# define STROKEIO_H
+
+# include "Stroke.h"
+# include <iostream>
+# include "../system/FreestyleConfig.h"
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const StrokeAttribute& iStrokeAttribute);
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const StrokeVertex& iStrokeVertex);
+
+LIB_STROKE_EXPORT
+ostream& operator<<(ostream& out, const Stroke& iStroke);
+
+
+#endif // STROKEIO_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeIterators.h b/source/blender/freestyle/intern/stroke/StrokeIterators.h
new file mode 100755
index 00000000000..b51189f3990
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeIterators.h
@@ -0,0 +1,229 @@
+//
+// Filename : StrokeIterators.h
+// Author(s) : Stephane Grabli
+// Purpose : Iterators used to iterate over the elements of the Stroke
+// 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 STROKEITERATORS_H
+# define STROKEITERATORS_H
+
+# include "Stroke.h"
+
+namespace StrokeInternal {
+
+ //
+ // StrokeVertexIterator
+ //
+ /////////////////////////////////////////////////
+
+ /*! Class defining an iterator designed to iterate over
+ * the StrokeVertex of a Stroke.
+ * An instance of a StrokeVertexIterator can only be obtained
+ * from a Stroke by calling strokeVerticesBegin() or strokeVerticesEnd().
+ * It is iterating over the same vertices as an Interface0DIterator.
+ * The difference resides in the object access. Indeed, an Interface0DIterator
+ * allows only an access to an Interface0D whereas we could need
+ * to access the specialized StrokeVertex type. In this case, one
+ * should use a StrokeVertexIterator.
+ * The castToInterface0DIterator() method is useful to get an Interface0DIterator
+ * from a StrokeVertexIterator in order to call any functions of the
+ * type UnaryFunction0D.
+ * \attention In the scripting language, you must call
+ * \code it2 = StrokeVertexIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 StrokeVertexIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ */
+ class StrokeVertexIterator : public Interface0DIteratorNested
+ {
+ public:
+
+ /*! Default constructor. */
+ StrokeVertexIterator() {}
+
+ /*! Copy constructor. */
+ StrokeVertexIterator(const StrokeVertexIterator& vi) {
+ _it = vi._it;
+ _begin = vi._begin;
+ _end = vi._end;
+ }
+
+ StrokeVertexIterator(const ::Stroke::vertex_container::iterator& it,
+ const ::Stroke::vertex_container::iterator& begin,
+ const ::Stroke::vertex_container::iterator& end) {
+ _it = it;
+ _begin = begin;
+ _end = end;
+ }
+
+ virtual ~StrokeVertexIterator() {}
+
+ /*! Casts this StrokeVertexIterator into an Interface0DIterator.
+ * Useful for any call to a function of the type UnaryFunction0D.
+ */
+ inline Interface0DIterator castToInterface0DIterator() const {
+ Interface0DIterator ret(new StrokeVertexIterator(*this));
+ return ret;
+ }
+ /*! operator=
+ * \attention In the scripting language, you must call
+ * \code it2 = StrokeVertexIterator(it1) \endcode instead of
+ * \code it2 = it1 \endcode
+ * where \a it1 and \a it2 are 2 StrokeVertexIterator.
+ * Otherwise, incrementing \a it1 will also increment \a it2.
+ *
+ */
+ StrokeVertexIterator& operator=(const StrokeVertexIterator& vi) {
+ _it = vi._it;
+ _begin = vi._begin;
+ _end = vi._end;
+ return *this;
+ }
+
+ /*! Returns the string "StrokeVertexIterator". */
+ virtual string getExactTypeName() const {
+ return "StrokeVertexIterator";
+ }
+
+ /*! Returns a reference to the pointed StrokeVertex.
+ * In the scripting language, you must call
+ * "getObject()"instead.
+ */
+ virtual StrokeVertex& operator*() {
+ return **_it;
+ }
+
+ /*! Returns a pointer to the pointed StrokeVertex.
+ * Can't be called in the scripting language.
+ */
+ virtual StrokeVertex* operator->() {
+ return &(operator*());
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual StrokeVertexIterator& operator++() {
+ increment();
+ return *this;
+ }
+
+ /*! Increments. In the scripting language, call
+ * "increment()".
+ */
+ virtual StrokeVertexIterator operator++(int) {
+ StrokeVertexIterator ret(*this);
+ increment();
+ return ret;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual StrokeVertexIterator& operator--() {
+ decrement();
+ return *this;
+ }
+
+ /*! Decrements. In the scripting language, call
+ * "decrement()".
+ */
+ virtual StrokeVertexIterator operator--(int) {
+ StrokeVertexIterator ret(*this);
+ decrement();
+ return ret;
+ }
+
+ /*! Increments. */
+ virtual int increment() {
+ ++_it;
+ return 0;
+ }
+
+ /*! Decrements. */
+ virtual int decrement() {
+ --_it;
+ return 0;
+ }
+
+ /*! Returns true if the pointed StrokeVertex is the
+ * first of the Stroke.
+ */
+ bool isBegin() const {
+ return _it == _begin;
+ }
+
+ /*! Returns true if the pointed StrokeVertex is after the
+ * last StrokeVertex of the Stroke.
+ */
+ bool isEnd() const {
+ return _it == _end;
+ }
+
+ /*! operator == */
+ virtual bool operator==(const Interface0DIteratorNested& it) const {
+ const StrokeVertexIterator* it_exact = dynamic_cast<const StrokeVertexIterator*>(&it);
+ if (!it_exact)
+ return false;
+ return (_it == it_exact->_it);
+ }
+
+ /*! Returns the curvilinear abscissa of the current point */
+ virtual float t() const{
+ return (*_it)->curvilinearAbscissa();
+ }
+ /*! Returns the point's parameter in the stroke */
+ virtual float u() const{
+ return (*_it)->u();
+ }
+
+ /*! Cloning method */
+ virtual StrokeVertexIterator* copy() const {
+ return new StrokeVertexIterator(*this);
+ }
+
+ //
+ // Not exported in Python
+ //
+ //////////////////////////////////////////////////
+
+ const ::Stroke::vertex_container::iterator& getIt() {
+ return _it;
+ }
+
+ private:
+
+ ::Stroke::vertex_container::iterator _it;
+ ::Stroke::vertex_container::iterator _begin;
+ ::Stroke::vertex_container::iterator _end;
+ };
+
+} // end of namespace StrokeInternal
+
+
+#endif // STROKEITERATORS_H
+
+
diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.cpp b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp
new file mode 100755
index 00000000000..d5fc27d3d73
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeLayer.cpp
@@ -0,0 +1,55 @@
+
+//
+// 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 "Stroke.h"
+#include "StrokeLayer.h"
+#include "Canvas.h"
+
+StrokeLayer::~StrokeLayer()
+{
+ clear();
+}
+
+void StrokeLayer::Render(const StrokeRenderer *iRenderer )
+{
+ for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s){
+ (*s)->Render(iRenderer);
+ }
+}
+
+void StrokeLayer::RenderBasic(const StrokeRenderer *iRenderer )
+{
+ for(StrokeLayer::stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s){
+ (*s)->RenderBasic(iRenderer);
+ }
+}
+void StrokeLayer::clear()
+{
+ for(stroke_container::iterator s=_strokes.begin(), send=_strokes.end();
+ s!=send;
+ ++s)
+ delete *s;
+ _strokes.clear();
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeLayer.h b/source/blender/freestyle/intern/stroke/StrokeLayer.h
new file mode 100755
index 00000000000..dbe9ea5a75c
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeLayer.h
@@ -0,0 +1,75 @@
+//
+// Filename : StrokeLayer.h
+// Author : Stephane Grabli
+// Purpose : Class to define a layer of strokes.
+// Date of creation : 18/12/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 STROKELAYER_H
+# define STROKELAYER_H
+
+# include <deque>
+
+class Stroke;
+class StrokeRenderer;
+class StrokeLayer
+{
+public:
+ typedef std::deque<Stroke*> stroke_container;
+
+protected:
+ stroke_container _strokes;
+public:
+ StrokeLayer() {}
+ StrokeLayer(const stroke_container& iStrokes)
+ {
+ _strokes = iStrokes;
+ }
+ StrokeLayer(const StrokeLayer& iBrother)
+ {
+ _strokes = iBrother._strokes;
+ }
+ virtual ~StrokeLayer() ;
+
+ /*! Render method */
+ void Render(const StrokeRenderer *iRenderer );
+ void RenderBasic(const StrokeRenderer *iRenderer );
+
+ /*! clears the layer */
+ void clear() ;
+
+ /*! accessors */
+ inline stroke_container::iterator strokes_begin() {return _strokes.begin();}
+ inline stroke_container::iterator strokes_end() {return _strokes.end();}
+ inline int strokes_size() const {return _strokes.size();}
+ inline bool empty() const {return _strokes.empty();}
+
+ /*! modifiers */
+ inline void setStrokes(stroke_container& iStrokes) {_strokes = iStrokes;}
+ inline void AddStroke(Stroke *iStroke) {_strokes.push_back(iStroke);}
+
+};
+
+#endif // STROKELAYER_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
new file mode 100755
index 00000000000..19e5ba35fed
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.cpp
@@ -0,0 +1,121 @@
+
+//
+// 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 "StrokeRenderer.h"
+#include "../geometry/GeomUtils.h"
+using namespace std;
+
+/**********************************/
+/* */
+/* */
+/* StrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+LIB_STROKE_EXPORT
+TextureManager *StrokeRenderer::_textureManager = 0;
+
+StrokeRenderer::StrokeRenderer ()
+{
+}
+
+StrokeRenderer::~StrokeRenderer ()
+{
+}
+
+bool StrokeRenderer::loadTextures()
+{
+ _textureManager->load();
+ return true;
+}
+
+
+/**********************************/
+/* */
+/* */
+/* TextureManager */
+/* */
+/* */
+/**********************************/
+
+
+LIB_STROKE_EXPORT
+TextureManager* TextureManager::_pInstance = 0;
+
+LIB_STROKE_EXPORT
+string TextureManager::_patterns_path;
+
+LIB_STROKE_EXPORT
+string TextureManager::_brushes_path;
+
+TextureManager::TextureManager ()
+{
+ _hasLoadedTextures=false;
+ _pInstance = this;
+ _defaultTextureId = 0;
+}
+
+TextureManager::~TextureManager ()
+{
+ if(!_brushesMap.empty())
+ _brushesMap.clear();
+ _pInstance = 0;
+}
+
+void TextureManager::load()
+{
+ if(_hasLoadedTextures)
+ return;
+ loadStandardBrushes();
+ _hasLoadedTextures = true;
+}
+
+unsigned TextureManager::getBrushTextureIndex(string name, Stroke::MediumType loadingMode)
+{
+ BrushTexture bt(name,loadingMode);
+ brushesMap::iterator b = _brushesMap.find(bt);
+ if(b == _brushesMap.end()){
+ unsigned texId = loadBrush(name, loadingMode);
+ _brushesMap[bt] = texId;
+ return texId;
+ cout << "brush file " << name << " not found" << endl;
+ return 0;
+ }else{
+ return _brushesMap[bt];
+ }
+}
+
+void TextureManager::Options::setPatternsPath(const string& path) {
+ _patterns_path = path;
+}
+
+string TextureManager::Options::getPatternsPath() {
+ return _patterns_path;
+}
+
+void TextureManager::Options::setBrushesPath(const string& path) {
+ _brushes_path = path;
+}
+
+string TextureManager::Options::getBrushesPath() {
+ return _brushes_path;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeRenderer.h b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
new file mode 100755
index 00000000000..c7c6df635d5
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRenderer.h
@@ -0,0 +1,132 @@
+//
+// Filename : StrokeRenderer.h
+// Author(s) : Fredo Durand
+// Purpose : Classes to render a stroke with OpenGL
+// Date of creation : 09/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 STROKE_RENDERER_H
+# define STROKE_RENDERER_H
+
+# include "Stroke.h"
+# include <vector>
+# include <map>
+# include <utility>
+# include "../system/FreestyleConfig.h"
+# include "StrokeRep.h"
+# include <string.h>
+
+
+/**********************************/
+/* */
+/* */
+/* TextureManager */
+/* */
+/* */
+/**********************************/
+
+
+/*! Class to load textures
+ */
+class LIB_STROKE_EXPORT TextureManager
+{
+public:
+
+ TextureManager ();
+ virtual ~TextureManager ();
+ static TextureManager * getInstance() {return _pInstance;}
+ void load () ;
+ unsigned getBrushTextureIndex(string name, Stroke::MediumType iType = Stroke::OPAQUE_MEDIUM) ;
+
+ inline bool hasLoaded() const {return _hasLoadedTextures;}
+ inline unsigned int getDefaultTextureId() const {return _defaultTextureId;}
+
+ struct LIB_STROKE_EXPORT Options
+ {
+
+ static void setPatternsPath(const string& path);
+ static string getPatternsPath();
+
+ static void setBrushesPath(const string& path);
+ static string getBrushesPath();
+ };
+
+ protected:
+ virtual void loadStandardBrushes() = 0;
+ virtual unsigned loadBrush(string fileName, Stroke::MediumType = Stroke::OPAQUE_MEDIUM) = 0;
+
+ typedef std::pair<string,Stroke::MediumType> BrushTexture;
+ struct cmpBrushTexture{
+ bool operator()(const BrushTexture& bt1, const BrushTexture& bt2) const{
+ int r = strcmp(bt1.first.c_str(), bt2.first.c_str());
+ if(r != 0)
+ return (r<0);
+ else
+ return (bt1.second < bt2.second);
+ }
+ };
+ typedef std::map<BrushTexture, unsigned, cmpBrushTexture> brushesMap;
+
+ static TextureManager * _pInstance;
+ bool _hasLoadedTextures;
+ brushesMap _brushesMap;
+ static string _patterns_path;
+ static string _brushes_path;
+ unsigned int _defaultTextureId;
+};
+
+
+/**********************************/
+/* */
+/* */
+/* StrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+/*! Class to render a stroke.
+ Creates a triangle strip and stores it
+ strip is lazily created at the first rendering
+*/
+class LIB_STROKE_EXPORT StrokeRenderer
+{
+ public:
+ StrokeRenderer();
+ virtual ~StrokeRenderer ();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const = 0;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const = 0;
+
+ // initializes the texture manager
+ // lazy, checks if it has already been done
+ static bool loadTextures() ;
+
+ //static unsigned int getTextureIndex(unsigned int index) ;
+ static TextureManager *_textureManager;
+};
+
+
+#endif // STROKE_RENDERER_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.cpp b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
new file mode 100755
index 00000000000..fbe1273bac0
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.cpp
@@ -0,0 +1,820 @@
+
+//
+// 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 "Stroke.h"
+#include "StrokeRep.h"
+#include "StrokeRenderer.h"
+#include "StrokeAdvancedIterators.h"
+#include "StrokeIterators.h"
+
+using namespace std;
+
+//
+// STROKE VERTEX REP
+/////////////////////////////////////
+StrokeVertexRep::StrokeVertexRep(const StrokeVertexRep& iBrother){
+ _point2d = iBrother._point2d;
+ _texCoord = iBrother._texCoord;
+ _color = iBrother._color;
+ _alpha = iBrother._alpha;
+}
+
+//
+// STRIP
+/////////////////////////////////////
+
+Strip::Strip(const vector<StrokeVertex*>& iStrokeVertices, bool hasTips, bool beginTip, bool endTip){
+ createStrip(iStrokeVertices);
+ if (!hasTips)
+ computeTexCoord (iStrokeVertices);
+ else
+ computeTexCoordWithTips (iStrokeVertices, beginTip, endTip);
+}
+Strip::Strip(const Strip& iBrother){
+ if(!iBrother._vertices.empty()){
+ for(vertex_container::const_iterator v=iBrother._vertices.begin(), vend=iBrother._vertices.end();
+ v!=vend;
+ ++v){
+ _vertices.push_back(new StrokeVertexRep(**v));
+ }
+ }
+ _averageThickness = iBrother._averageThickness;
+}
+
+Strip::~Strip(){
+ if(!_vertices.empty()){
+ for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end();
+ v!=vend;
+ ++v){
+ delete (*v);
+ }
+ _vertices.clear();
+ }
+}
+
+//////////////////////////
+// Strip creation
+//////////////////////////
+#define EPS_SINGULARITY_RENDERER 0.05
+#define ZERO 0.00001
+#define MAX_RATIO_LENGTH_SINGU 2
+#define HUGE_COORD 1e4
+
+bool notValid (Vec2r p)
+{
+ return (p[0]!=p[0]) || (p[1]!=p[1]) || (fabs(p[0])>HUGE_COORD) || (fabs(p[1])>HUGE_COORD)
+ || (p[0] <-HUGE_COORD) || (p[1]<-HUGE_COORD);
+}
+
+real crossP(const Vec2r& A, const Vec2r& B){
+ return A[0]*B[1] - A[1]*B[0];
+}
+
+void
+Strip::createStrip (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ //computeParameterization();
+ if (iStrokeVertices.size() <2)
+ {
+ cerr << "Warning: strip has less than 2 vertices" << endl;
+ return;
+ }
+ _vertices.reserve(2*iStrokeVertices.size());
+ if(!_vertices.empty()){
+ for(vertex_container::iterator v=_vertices.begin(), vend=_vertices.end();
+ v!=vend;
+ ++v){
+ delete (*v);
+ }
+ _vertices.clear();
+ }
+ _averageThickness=0.0;
+
+ vector<StrokeVertex*>::const_iterator v ,vend, v2, vPrev;
+ StrokeVertex *sv, *sv2, *svPrev;
+
+ //special case of first vertex
+ v=iStrokeVertices.begin();
+ sv=*v;
+ vPrev=v; //in case the stroke has only 2 vertices;
+ ++v; sv2=*v;
+ Vec2r dir(sv2->getPoint()-sv->getPoint());
+ Vec2r orthDir(-dir[1], dir[0]);
+ if (orthDir.norm() > ZERO)
+ orthDir.normalize();
+ const float *thickness = sv->attribute().getThickness();
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()+thickness[1]*orthDir));
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()-thickness[0]*orthDir));
+
+ Vec2r stripDir(orthDir);
+ // check whether the orientation
+ // was user defined
+ if(sv->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ Vec2r t(orthDir[1], -orthDir[0]);
+ real dp1 = userDir*orthDir;
+ real dp2 = userDir*t;
+ real h = (thickness[1]+thickness[0])/dp1;
+ real x = fabs(h*dp2/2.0);
+ if(dp1>0){
+ //i'm in the upper part of the unit circle
+ if(dp2>0){
+ //i'm in the upper-right part of the unit circle
+ // i must move vertex 1
+ _vertices[1]->setPoint2d(_vertices[0]->point2d()-userDir*(h));
+ //_vertices[0]->setPoint2d(_vertices[0]->point2d()+t*x);
+ //_vertices[1]->setPoint2d(_vertices[1]->point2d()-t*x);
+ }else{
+ //i'm in the upper-left part of the unit circle
+ // i must move vertex 0
+ _vertices[0]->setPoint2d(_vertices[1]->point2d()+userDir*(h));
+ //_vertices[0]->setPoint2d(_vertices[0]->point2d()-t*x);
+ //_vertices[1]->setPoint2d(_vertices[1]->point2d()+t*x);
+ }
+ }else{
+ //i'm in the lower part of the unit circle
+ if(dp2>0){
+ //i'm in the lower-right part of the unit circle
+ // i must move vertex 0
+ //_vertices[0]->setPoint2d(_vertices[1]->point2d()-userDir*(h));
+ _vertices[0]->setPoint2d(_vertices[0]->point2d()-t*x);
+ //_vertices[1]->setPoint2d(_vertices[1]->point2d()+t*x);
+ }else{
+ //i'm in the lower-left part of the unit circle
+ // i must move vertex 1
+ _vertices[1]->setPoint2d(_vertices[0]->point2d()+userDir*(h));
+ //_vertices[0]->setPoint2d(_vertices[0]->point2d()-t*x);
+ //_vertices[1]->setPoint2d(_vertices[1]->point2d()-t*x);
+ }
+ }
+ }
+
+
+ // Vec2r userDir = _stroke->getBeginningOrientation();
+ // if(userDir != Vec2r(0,0)){
+ // userDir.normalize();
+ // real o1 = (orthDir*userDir);
+ // real o2 = crossP(orthDir,userDir);
+ // real orientation = o1 * o2;
+ // if(orientation > 0){
+ // // then the vertex to move is v0
+ // if(o1 > 0)
+ // _vertex[0]=_vertex[1]+userDir;
+ // else
+ // _vertex[0]=_vertex[1]-userDir;
+ // }
+ // if(orientation < 0){
+ // // then we must move v1
+ // if(o1 < 0)
+ // _vertex[1]=_vertex[0]+userDir;
+ // else
+ // _vertex[1]=_vertex[0]-userDir;
+ // }
+ // }
+
+ int i=2; //2 because we have already processed the first vertex
+
+ for(vend=iStrokeVertices.end();
+ v!=vend;
+ v++){
+ v2=v; ++v2;
+ if (v2==vend) break;
+ sv= (*v); sv2 = (*v2); svPrev=(*vPrev);
+ Vec2r p(sv->getPoint()), p2(sv2->getPoint()), pPrev(svPrev->getPoint());
+
+ //direction and orthogonal vector to the next segment
+ Vec2r dir(p2-p);
+ float dirNorm=dir.norm();
+ dir.normalize();
+ Vec2r orthDir(-dir[1], dir[0]);
+ Vec2r stripDir = orthDir;
+ if(sv->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir*orthDir;
+ if(dp<0)
+ userDir = userDir*(-1.f);
+ stripDir = userDir;
+ }
+
+ //direction and orthogonal vector to the previous segment
+ Vec2r dirPrev(p-pPrev);
+ float dirPrevNorm=dirPrev.norm();
+ dirPrev.normalize();
+ Vec2r orthDirPrev(-dirPrev[1], dirPrev[0]);
+ Vec2r stripDirPrev = orthDirPrev;
+ if(svPrev->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = svPrev->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ real dp = userDir*orthDir;
+ if(dp<0)
+ userDir = userDir*(-1.f);
+ stripDirPrev = userDir;
+ }
+
+ const float *thickness = sv->attribute().getThickness();
+ _averageThickness+=thickness[0]+thickness[1];
+ Vec2r pInter;
+ int interResult;
+
+ interResult=GeomUtils::intersect2dLine2dLine(Vec2r(pPrev+thickness[1]*stripDirPrev), Vec2r(p+thickness[1]*stripDirPrev),
+ Vec2r(p+thickness[1]*stripDir), Vec2r(p2+thickness[1]*stripDir),
+ pInter);
+
+ if (interResult==GeomUtils::DO_INTERSECT)
+ _vertices.push_back(new StrokeVertexRep(pInter));
+ else
+ _vertices.push_back(new StrokeVertexRep(p+thickness[1]*stripDir));
+ ++i;
+
+ interResult=GeomUtils::intersect2dLine2dLine(Vec2r(pPrev-thickness[0]*stripDirPrev), Vec2r(p-thickness[0]*stripDirPrev),
+ Vec2r(p-thickness[0]*stripDir), Vec2r(p2-thickness[0]*stripDir),
+ pInter);
+ if (interResult==GeomUtils::DO_INTERSECT)
+ _vertices.push_back(new StrokeVertexRep(pInter));
+ else
+ _vertices.push_back(new StrokeVertexRep(p-thickness[0]*stripDir));
+ ++i;
+
+ // if the angle is obtuse, we simply average the directions to avoid the singularity
+ stripDir=stripDir+stripDirPrev;
+ if ((dirNorm<ZERO) || (dirPrevNorm<ZERO) || (stripDir.norm() < ZERO)) {
+ stripDir[0] = 0;
+ stripDir[1] = 0;
+ }else
+ stripDir.normalize();
+
+ Vec2r vec_tmp(_vertices[i-2]->point2d()-p);
+ if ((vec_tmp.norm() > thickness[1]*MAX_RATIO_LENGTH_SINGU) ||
+ (dirNorm<ZERO) || (dirPrevNorm<ZERO) ||
+ notValid(_vertices[i-2]->point2d())
+ || (fabs(stripDir * dir) < EPS_SINGULARITY_RENDERER))
+ _vertices[i-2]->setPoint2d(p+thickness[1]*stripDir);
+
+ vec_tmp = _vertices[i-1]->point2d()-p;
+ if ((vec_tmp.norm() > thickness[1]*MAX_RATIO_LENGTH_SINGU) ||
+ (dirNorm<ZERO) || (dirPrevNorm<ZERO) ||
+ notValid(_vertices[i-1]->point2d())
+ || (fabs(stripDir * dir)<EPS_SINGULARITY_RENDERER))
+ _vertices[i-1]->setPoint2d(p-thickness[0]*stripDir);
+
+ vPrev=v;
+ } // end of for
+
+ //special case of last vertex
+ sv=*v;
+ sv2=*vPrev;
+ dir=Vec2r (sv->getPoint()-sv2->getPoint());
+ orthDir=Vec2r(-dir[1], dir[0]);
+ if (orthDir.norm() > ZERO)
+ orthDir.normalize();
+ const float *thicknessLast = sv->attribute().getThickness();
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()+thicknessLast[1]*orthDir));
+ ++i;
+ _vertices.push_back(new StrokeVertexRep(sv->getPoint()-thicknessLast[0]*orthDir));
+ int n = i;
+ ++i;
+
+ // check whether the orientation
+ // was user defined
+ if(sv->attribute().isAttributeAvailableVec2f("orientation")){
+ Vec2r userDir = sv->attribute().getAttributeVec2f("orientation");
+ userDir.normalize();
+ Vec2r t(orthDir[1], -orthDir[0]);
+ real dp1 = userDir*orthDir;
+ real dp2 = userDir*t;
+ real h = (thicknessLast[1]+thicknessLast[0])/dp1;
+ //soc unused - real x = fabs(h*dp2/2.0);
+ if(dp1>0){
+ //i'm in the upper part of the unit circle
+ if(dp2>0){
+ //i'm in the upper-right part of the unit circle
+ // i must move vertex n-1
+ _vertices[n-1]->setPoint2d(_vertices[n]->point2d()-userDir*(h));
+ //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()+t*x);
+ //_vertices[n]->setPoint2d(_vertices[n]->point2d()-t*x);
+ }else{
+ //i'm in the upper-left part of the unit circle
+ // i must move vertex n
+ _vertices[n]->setPoint2d(_vertices[n-1]->point2d()+userDir*(h));
+ //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()-t*x);
+ //_vertices[n]->setPoint2d(_vertices[n]->point2d()+t*x);
+ }
+ }else{
+ //i'm in the lower part of the unit circle
+ if(dp2>0){
+ //i'm in the lower-right part of the unit circle
+ // i must move vertex n
+ _vertices[n]->setPoint2d(_vertices[n-1]->point2d()-userDir*(h));
+ //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()-t*x);
+ //_vertices[n]->setPoint2d(_vertices[n]->point2d()+t*x);
+ }else{
+ //i'm in the lower-left part of the unit circle
+ // i must move vertex n-1
+ _vertices[n-1]->setPoint2d(_vertices[n]->point2d()+userDir*(h));
+ //_vertices[n-1]->setPoint2d(_vertices[n-1]->point2d()+t*x);
+ //_vertices[n]->setPoint2d(_vertices[n]->point2d()-t*x);
+ }
+ }
+ }
+
+
+ // check whether the orientation of the extremity
+ // was user defined
+ // userDir = _stroke->getEndingOrientation();
+ // if(userDir != Vec2r(0,0)){
+ // userDir.normalize();
+ // real o1 = (orthDir*userDir);
+ // real o2 = crossP(orthDir,userDir);
+ // real orientation = o1 * o2;
+ // if(orientation > 0){
+ // // then the vertex to move is vn
+ // if(o1 < 0)
+ // _vertex[n]=_vertex[n-1]+userDir;
+ // else
+ // _vertex[n]=_vertex[n-1]-userDir;
+ // }
+ // if(orientation < 0){
+ // // then we must move vn-1
+ // if(o1 > 0)
+ // _vertex[n-1]=_vertex[n]+userDir;
+ // else
+ // _vertex[n-1]=_vertex[n]-userDir;
+ // }
+ // }
+
+ _averageThickness/=float(iStrokeVertices.size()-2);
+ //I did not use the first and last vertex for the average
+ if (iStrokeVertices.size()<3)
+ _averageThickness=0.5*(thicknessLast[1]+thicknessLast[0]+thickness[0]+thickness[1]);
+
+ if (i != 2*(int)iStrokeVertices.size())
+ cerr << "Warning: problem with stripe size\n";
+
+ cleanUpSingularities (iStrokeVertices);
+}
+
+// CLEAN UP
+/////////////////////////
+
+void
+Strip::cleanUpSingularities (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ int k;
+ int sizeStrip = _vertices.size();
+
+ for (k=0; k<sizeStrip; k++)
+ if (notValid(_vertices[k]->point2d()))
+ {
+ cerr << "Warning: strip vertex " << k << " non valid" << endl;
+ return;
+ }
+
+ //return;
+ if (iStrokeVertices.size()<2) return;
+ int i=0, j;
+ vector<StrokeVertex*>::const_iterator v ,vend, v2, vPrev;
+StrokeVertex *sv, *sv2; //soc unused - *svPrev;
+
+ bool singu1=false, singu2=false;
+ int timeSinceSingu1=0, timeSinceSingu2=0;
+
+ //special case of first vertex
+ v=iStrokeVertices.begin();
+ for(vend=iStrokeVertices.end();
+ v!=vend;
+ v++)
+ {
+ v2=v; ++v2;
+ if (v2==vend) break;
+ sv= (*v); sv2 = (*v2);
+ Vec2r p(sv->getPoint()), p2(sv2->getPoint());
+
+ Vec2r dir(p2-p);
+ if (dir.norm() > ZERO)
+ dir.normalize();
+ Vec2r dir1, dir2;
+ dir1=_vertices[2*i+2]->point2d()-_vertices[2*i]->point2d();
+ dir2=_vertices[2*i+3]->point2d()-_vertices[2*i+1]->point2d();
+
+ if ((dir1 * dir) < -ZERO)
+ {
+ singu1=true;
+ timeSinceSingu1++;
+ }
+ else
+ {
+ if (singu1)
+ {
+ int toto=i-timeSinceSingu1;
+ if (toto<0)
+ cerr << "Stephane dit \"Toto\"" << endl;
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu1; j<i+1; j++)
+ avP=Vec2r(avP+_vertices[2*j]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu1+1)*avP);
+ for (j=i-timeSinceSingu1; j<i+1; j++)
+ _vertices[2*j]->setPoint2d(avP);
+ //_vertex[2*j]=_vertex[2*i];
+ singu1=false; timeSinceSingu1=0;
+ }
+ }
+ if ((dir2 * dir) < -ZERO)
+ {
+ singu2=true;
+ timeSinceSingu2++;
+ }
+ else
+ {
+ if (singu2)
+ {
+ int toto=i-timeSinceSingu2;
+ if (toto<0)
+ cerr << "Stephane dit \"Toto\"" << endl;
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu2; j<i+1; j++)
+ avP=Vec2r(avP+_vertices[2*j+1]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu2+1)*avP);
+ for (j=i-timeSinceSingu2; j<i+1; j++)
+ _vertices[2*j+1]->setPoint2d(avP);
+ //_vertex[2*j+1]=_vertex[2*i+1];
+ singu2=false; timeSinceSingu2=0;
+ }
+ }
+ i++;
+ }
+
+ if (singu1)
+ {
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu1; j<i; j++)
+ avP=Vec2r(avP+_vertices[2*j]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu1)*avP);
+ for (j=i-timeSinceSingu1; j<i; j++)
+ _vertices[2*j]->setPoint2d(avP);
+ }
+ if (singu2)
+ {
+ //traverse all the vertices of the singularity and average them
+ Vec2r avP(0.0,0.0);
+ for (j=i-timeSinceSingu2; j<i; j++)
+ avP=Vec2r(avP+_vertices[2*j+1]->point2d());
+ avP=Vec2r(1.0/float(timeSinceSingu2)*avP);
+ for (j=i-timeSinceSingu2; j<i; j++)
+ _vertices[2*j+1]->setPoint2d(avP);
+ }
+
+
+ for (k=0; k<sizeStrip; k++)
+ if (notValid(_vertices[k]->point2d()))
+ {
+ cerr << "Warning: strip vertex " << k << " non valid after cleanup"<<endl;
+ return;
+ }
+}
+
+
+// Texture coordinates
+////////////////////////////////
+
+void
+Strip::computeTexCoord (const vector<StrokeVertex*>& iStrokeVertices)
+{
+ vector<StrokeVertex*>::const_iterator v ,vend;
+ StrokeVertex *sv;
+ int i=0;
+ for(v=iStrokeVertices.begin(), vend=iStrokeVertices.end();
+ v!=vend; v++)
+ {
+ sv= (*v);
+ _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),0));
+ _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ _vertices[i]->setAlpha(sv->attribute().getAlpha());
+ i++;
+ _vertices[i]->setTexCoord(Vec2r((real)(sv->curvilinearAbscissa() / _averageThickness),1));
+ _vertices[i]->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ _vertices[i]->setAlpha(sv->attribute().getAlpha());
+ i++;
+ // cerr<<"col=("<<sv->attribute().getColor()[0]<<", "
+ // <<sv->attribute().getColor()[1]<<", "<<sv->attribute().getColor()[2]<<")"<<endl;
+ }
+}
+
+void
+Strip::computeTexCoordWithTips (const vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd)
+{
+ //soc unused - unsigned int sizeStrip = _vertices.size()+8; //for the transition between the tip and the body
+ vector<StrokeVertex*>::const_iterator v ,vend;
+ StrokeVertex *sv = 0;
+
+ v=iStrokeVertices.begin();
+ vend=iStrokeVertices.end();
+ float l=(*v)->strokeLength()/_averageThickness;
+ int tiles=int(l);
+ float fact=(float(tiles)+0.5)/l;
+ //soc unused - float uTip2=float(tiles)+0.25;
+ float u=0;
+ float uPrev=0;
+ int i=0;
+ float t;
+ StrokeVertexRep *tvRep1, *tvRep2;
+
+ // cerr<<"l="<<l<<" tiles="<<tiles<<" _averageThicnkess="
+ // <<_averageThickness<<" strokeLength="<<(*v)->strokeLength()<<endl;
+ //
+ vector<StrokeVertexRep*>::iterator currentSV = _vertices.begin();
+ StrokeVertexRep *svRep;
+ if(tipBegin){
+ for(;v!=vend; v++)
+ {
+ sv= (*v);
+ svRep = *currentSV;
+ u=sv->curvilinearAbscissa()/_averageThickness*fact;
+ if (u>0.25) break;
+
+
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 1));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+ uPrev=u;
+ }
+ //first transition vertex
+
+ if (fabs(u-uPrev)>ZERO)
+ t= (0.25-uPrev)/(u-uPrev);
+ else t=0;
+ //if (!tiles) t=0.5;
+ tvRep1 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep1->setTexCoord(Vec2r(0.25,0.5));
+ tvRep1->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep1->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep2->setTexCoord(Vec2r(0.25,1));
+ tvRep2->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep2->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //copy the vertices with different texture coordinates
+ tvRep1 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep1->setTexCoord(Vec2r(0.25,0));
+ tvRep1->setColor(_vertices[i-2]->color());
+ tvRep1->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep2->setTexCoord(Vec2r(0.25,0.5));
+ tvRep2->setColor(_vertices[i-2]->color());
+ tvRep2->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+ }
+ uPrev=0;
+
+ //body of the stroke
+ for(;v!=vend; v++)
+ {
+ sv= (*v);
+ svRep = *currentSV;
+ u=sv->curvilinearAbscissa()/_averageThickness*fact-0.25;
+ if (u>tiles) break;
+
+ svRep->setTexCoord(Vec2r((real)u, 0));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ uPrev=u;
+ }
+ if(tipEnd){
+ //second transition vertex
+ if ((fabs(u-uPrev)>ZERO))
+ t= (float(tiles)-uPrev)/(u-uPrev);
+ else t=0;
+
+ tvRep1 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep1->setTexCoord(Vec2r((real)tiles,0));
+ tvRep1->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep1->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(Vec2r((1-t)*_vertices[i-2]->point2d()+t*_vertices[i]->point2d()));
+ tvRep2->setTexCoord(Vec2r((real)tiles,0.5));
+ tvRep2->setColor(Vec3r((1-t)*_vertices[i-2]->color()+
+ t*Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2])));
+ tvRep2->setAlpha((1-t)*_vertices[i-2]->alpha()+t*sv->attribute().getAlpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //copy the vertices with different texture coordinates
+ tvRep1 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep1->setTexCoord(Vec2r(0.75,0.5));
+ tvRep1->setColor(_vertices[i-2]->color());
+ tvRep1->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ tvRep2 = new StrokeVertexRep(_vertices[i-2]->point2d());
+ tvRep2->setTexCoord(Vec2r(0.75,1));
+ tvRep2->setColor(_vertices[i-2]->color());
+ tvRep2->setAlpha(_vertices[i-2]->alpha());
+ i++;
+
+ currentSV = _vertices.insert(currentSV, tvRep1);
+ ++currentSV;
+ currentSV = _vertices.insert(currentSV, tvRep2);
+ ++currentSV;
+
+ //end tip
+ for(;v!=vend; v++)
+ {
+ sv= (*v);
+ svRep = *currentSV;
+ u=0.75+sv->curvilinearAbscissa()/_averageThickness*fact-float(tiles)-0.25;
+
+ svRep->setTexCoord(Vec2r((real)u, 0.5));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+
+ svRep = *currentSV;
+ svRep->setTexCoord(Vec2r((real)u, 1));
+ svRep->setColor(Vec3r(sv->attribute().getColor()[0],sv->attribute().getColor()[1],sv->attribute().getColor()[2]));
+ svRep->setAlpha(sv->attribute().getAlpha());
+ i++;
+ ++currentSV;
+ }
+ }
+ //cerr<<"u="<<u<<" i="<<i<<"/"<<_sizeStrip<<endl;;
+
+ // for (i=0; i<_sizeStrip; i++)
+ // _alpha[i]=1.0;
+
+ // for (i=0; i<_sizeStrip; i++)
+ // cerr<<"("<<_texCoord[i][0]<<", "<<_texCoord[i][1]<<") ";
+ // cerr<<endl;
+
+
+ // Vec2r vec_tmp;
+ // for (i=0; i<_sizeStrip/2; i++)
+ // vec_tmp = _vertex[2*i] - _vertex[2*i+1];
+ // if (vec_tmp.norm() > 4*_averageThickness)
+ // cerr << "Warning (from Fredo): There is a pb in the texture coordinates computation" << endl;
+}
+
+//
+// StrokeRep
+/////////////////////////////////////
+
+StrokeRep::StrokeRep()
+{
+ _stroke = 0;
+ _strokeType=Stroke::OPAQUE_MEDIUM;
+ TextureManager * ptm = TextureManager::getInstance();
+ if(ptm)
+ _textureId = ptm->getDefaultTextureId();
+ // _averageTextureAlpha=0.5; //default value
+ // if (_strokeType==OIL_STROKE)
+ // _averageTextureAlpha=0.75;
+ // if (_strokeType>=NO_BLEND_STROKE)
+ // _averageTextureAlpha=1.0
+}
+
+StrokeRep::StrokeRep(Stroke *iStroke)
+{
+ _stroke = iStroke;
+ _strokeType = iStroke->getMediumType();
+ _textureId = iStroke->getTextureId();
+ if(_textureId == 0){
+ TextureManager * ptm = TextureManager::getInstance();
+ if(ptm)
+ _textureId = ptm->getDefaultTextureId();
+ }
+
+ // _averageTextureAlpha=0.5; //default value
+ // if (_strokeType==OIL_STROKE)
+ // _averageTextureAlpha=0.75;
+ // if (_strokeType>=NO_BLEND_STROKE)
+ // _averageTextureAlpha=1.0;
+ create();
+}
+
+StrokeRep::StrokeRep(const StrokeRep& iBrother)
+{
+ //soc unused - int i=0;
+ _stroke = iBrother._stroke;
+ _strokeType=iBrother._strokeType;
+ _textureId = iBrother._textureId;
+ for(vector<Strip*>::const_iterator s=iBrother._strips.begin(), send=iBrother._strips.end();
+ s!=send;
+ ++s){
+ _strips.push_back(new Strip(**s));
+ }
+}
+
+
+StrokeRep::~StrokeRep()
+{
+ if(!_strips.empty()){
+ for(vector<Strip*>::iterator s=_strips.begin(), send=_strips.end();
+ s!=send;
+ ++s){
+ delete (*s);
+ }
+ _strips.clear();
+ }
+}
+
+void StrokeRep::create(){
+ vector<StrokeVertex*> strip;
+ StrokeInternal::StrokeVertexIterator v = _stroke->strokeVerticesBegin();
+ StrokeInternal::StrokeVertexIterator vend = _stroke->strokeVerticesEnd();
+
+ bool first=true;
+ bool end=false;
+ while(v!=vend){
+ while((v!=vend) && (!(*v).attribute().isVisible())){
+ ++v;
+ first = false;
+ }
+ while( (v!=vend) && ((*v).attribute().isVisible()) ) {
+ strip.push_back(&(*v));
+ ++v;
+ }
+ if(v!=vend){
+ // add the last vertex and create
+ strip.push_back(&(*v));
+ }else{
+ end=true;
+ }
+ if((!strip.empty()) && (strip.size()>1) ){
+ _strips.push_back(new Strip(strip, _stroke->hasTips(), first, end));
+ strip.clear();
+ }
+ first = false;
+ }
+}
+
+void StrokeRep::Render(const StrokeRenderer *iRenderer)
+{
+ iRenderer->RenderStrokeRep(this);
+}
+
+
+
diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h
new file mode 100755
index 00000000000..d8a8dc2d609
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeRep.h
@@ -0,0 +1,138 @@
+//
+// Filename : StrokeRep.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the representation of a stroke
+// (for display purpose)
+// Date of creation : 05/03/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 STROKEREP_H
+# define STROKEREP_H
+
+# include "../geometry/Geom.h"
+using namespace Geometry;
+
+//symbolic constant to call the appropriate renderers and textures
+// # define NO_TEXTURE_WITH_BLEND_STROKE -2
+// # define NO_TEXTURE_STROKE -1
+// # define PSEUDO_CHARCOAL_STROKE 0
+// # define WASH_BRUSH_STROKE 1
+// # define OIL_STROKE 2
+// # define NO_BLEND_STROKE 3
+// # define CHARCOAL_MIN_STROKE 4
+// # define BRUSH_MIN_STROKE 5
+// # define OPAQUE_DRY_STROKE 6
+// # define OPAQUE_STROKE 7
+//
+// # define DEFAULT_STROKE 0
+//
+// # define NUMBER_STROKE_RENDERER 8
+
+#include "Stroke.h"
+
+class StrokeVertexRep{
+public:
+ StrokeVertexRep(){}
+ StrokeVertexRep(const Vec2r& iPoint2d){_point2d=iPoint2d;}
+ StrokeVertexRep(const StrokeVertexRep& iBrother);
+ virtual ~StrokeVertexRep(){}
+
+ inline Vec2r& point2d() {return _point2d;}
+ inline Vec2r& texCoord() {return _texCoord;}
+ inline Vec3r& color() {return _color;}
+ inline float alpha() {return _alpha;}
+
+ inline void setPoint2d(const Vec2r& p){_point2d = p;}
+ inline void setTexCoord(const Vec2r& p){_texCoord = p;}
+ inline void setColor(const Vec3r& p){_color = p;}
+ inline void setAlpha(float a){_alpha = a;}
+protected:
+ Vec2r _point2d;
+ Vec2r _texCoord;
+ Vec3r _color;
+ float _alpha;
+};
+
+class Strip{
+public:
+ typedef std::vector<StrokeVertexRep*> vertex_container;
+protected:
+ vertex_container _vertices;
+ float _averageThickness;
+
+
+public:
+ Strip(const std::vector<StrokeVertex*>& iStrokeVertices, bool hasTips=false, bool tipBegin=false, bool tipEnd=false) ;
+ Strip(const Strip& iBrother);
+ virtual ~Strip() ;
+
+protected:
+ void createStrip(const std::vector<StrokeVertex*>& iStrokeVertices);
+ void cleanUpSingularities(const std::vector<StrokeVertex*>& iStrokeVertices);
+ void computeTexCoord (const std::vector<StrokeVertex*>& iStrokeVertices);
+ void computeTexCoordWithTips (const std::vector<StrokeVertex*>& iStrokeVertices, bool tipBegin, bool tipEnd);
+public:
+ inline int sizeStrip() const {return _vertices.size();}
+ inline vertex_container& vertices() {return _vertices;}
+};
+
+class StrokeRep
+{
+protected:
+ Stroke *_stroke;
+ vector<Strip*> _strips;
+ Stroke::MediumType _strokeType;
+ unsigned int _textureId;
+
+ // float _averageTextureAlpha;
+
+
+public:
+ StrokeRep();
+ StrokeRep(const StrokeRep&);
+ StrokeRep(Stroke *iStroke);
+ virtual ~StrokeRep();
+
+ /*! Creates the strips */
+ virtual void create() ;
+
+ /*! Renders the stroke using a Renderer */
+ virtual void Render(const StrokeRenderer *iRenderer) ;
+
+ /*! accessors */
+ inline Stroke::MediumType getMediumType() const {return _strokeType;}
+ inline unsigned getTextureId() const {return _textureId;}
+ inline vector<Strip*>& getStrips() {return _strips;}
+ inline unsigned int getNumberOfStrips() const {return _strips.size();}
+ inline Stroke * getStroke() {return _stroke;}
+
+ /*! modifiers */
+ inline void setMediumType(Stroke::MediumType itype) {_strokeType=itype;}
+ inline void setTextureId(unsigned textureId) {_textureId = textureId;}
+
+
+};
+
+#endif // STROKEREP_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h
new file mode 100755
index 00000000000..63185438e91
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeShader.h
@@ -0,0 +1,124 @@
+//
+// Filename : StrokeShader.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class defining StrokeShader
+// 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 SHADERS_H
+# define SHADERS_H
+
+# include <iostream>
+# include <vector>
+
+# include "../python/Director.h"
+
+//
+// StrokeShader base class
+//
+//////////////////////////////////////////////////////
+
+class Stroke;
+/*! Base class for Stroke Shaders.
+ * Any Stroke Shader must inherit from
+ * this class and overload the shade() method.
+ * A StrokeShader is designed to modify any
+ * Stroke's attribute such as Thickness, Color,
+ * Geometry, Texture, Blending mode...
+ * The basic way to achieve this operation consists
+ * in iterating over the StrokeVertices of the Stroke
+ * and to modify each one's StrokeAttribute.
+ * Here is a python code example of such an iteration:
+ * \code
+ * it = ioStroke.strokeVerticesBegin()
+ * while it.isEnd() == 0:
+ * att = it.getObject().attribute()
+ * ## perform here any attribute modification
+ * it.increment()
+ * \endcode
+ * Here is a C++ code example of such an iteration:
+ * \code
+ * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+ * v!=vend;
+ * ++v){
+ * StrokeAttribute& att = v->attribute();
+ * // perform any attribute modification here...
+ * }
+ * \endcode
+ */
+class LIB_STROKE_EXPORT StrokeShader
+{
+public:
+
+ PyObject *py_ss;
+
+ /*! Default constructor. */
+ StrokeShader() { py_ss = 0; }
+ /*! Destructor. */
+ virtual ~StrokeShader() {}
+ /*! Returns the string corresponding to the
+ * shader's name.
+ */
+ virtual string getName() const {
+ return "StrokeShader";
+ }
+ /*! The shading method. This method must
+ * be overloaded by inherited classes.
+ * The shading method is designed to modify any
+ * Stroke's attribute such as Thickness, Color,
+ * Geometry, Texture, Blending mode...
+ * The basic way to achieve this operation consists
+ * in iterating over the StrokeVertices of the Stroke
+ * and to modify each one's StrokeAttribute.
+ * Here is a python code example of such an iteration:
+ * \code
+ * it = ioStroke.strokeVerticesBegin()
+ * while it.isEnd() == 0:
+ * att = it.getObject().attribute()
+ * ## perform here any attribute modification
+ * it.increment()
+ * \endcode
+ * Here is a C++ code example of such an iteration:
+ * \code
+ * for(StrokeInternal::StrokeVertexIterator v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
+ * v!=vend;
+ * ++v){
+ * StrokeAttribute& att = v->attribute();
+ * // perform any attribute modification here...
+ * }
+ * \endcode
+ * \param ioStroke
+ * The stroke we wish to shade. this Stroke
+ * is modified by the Shader (which typically
+ * modifies the Stroke's attribute's values such
+ * as Color, Thickness, Geometry...)
+ */
+ virtual int shade(Stroke& ioStroke) const {
+ return Director_BPy_StrokeShader_shade( const_cast<StrokeShader *>(this), ioStroke );
+ }
+
+};
+
+# endif // SHADERS_H
diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp
new file mode 100755
index 00000000000..a8b71f9f3c3
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.cpp
@@ -0,0 +1,88 @@
+
+//
+// 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 "StrokeTesselator.h"
+#include "../scene_graph/OrientedLineRep.h"
+#include "../scene_graph/NodeGroup.h"
+#include "../scene_graph/NodeShape.h"
+#include "StrokeAdvancedIterators.h"
+
+LineRep* StrokeTesselator::Tesselate(Stroke *iStroke)
+{
+ if(0 == iStroke)
+ return 0;
+
+ LineRep* line;
+ line = new OrientedLineRep();
+
+ Stroke::vertex_iterator v,vend;
+ if(2 == iStroke->vertices_size())
+ {
+ line->setStyle(LineRep::LINES);
+ v = iStroke->vertices_begin();
+ StrokeVertex *svA= (*v);
+ v++;
+ StrokeVertex *svB = (*v);
+ Vec3r A((*svA)[0], (*svA)[1], 0);
+ Vec3r B((*svB)[0], (*svB)[1], 0);
+ line->AddVertex(A);
+ line->AddVertex(B);
+ }
+ else
+ {
+ if(_overloadFrsMaterial)
+ line->setFrsMaterial(_FrsMaterial);
+
+ line->setStyle(LineRep::LINE_STRIP);
+
+ for(v=iStroke->vertices_begin(), vend=iStroke->vertices_end();
+ v!=vend;
+ v++)
+ {
+ StrokeVertex *sv= (*v);
+ Vec3r V((*sv)[0], (*sv)[1], 0);
+ line->AddVertex(V);
+ }
+ }
+ line->setId(iStroke->getId());
+ line->ComputeBBox();
+
+ return line;
+}
+
+template<class StrokeVertexIterator>
+NodeGroup* StrokeTesselator::Tesselate(StrokeVertexIterator begin, StrokeVertexIterator end)
+{
+ NodeGroup *group = new NodeGroup;
+ NodeShape *tshape = new NodeShape;
+ group->AddChild(tshape);
+ //tshape->material().setDiffuse(0.f, 0.f, 0.f, 1.f);
+ tshape->setFrsMaterial(_FrsMaterial);
+
+ for(StrokeVertexIterator c=begin, cend=end;
+ c!=cend;
+ c++)
+ {
+ tshape->AddRep(Tesselate((*c)));
+ }
+
+ return group;
+}
diff --git a/source/blender/freestyle/intern/stroke/StrokeTesselator.h b/source/blender/freestyle/intern/stroke/StrokeTesselator.h
new file mode 100755
index 00000000000..671df00ef84
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StrokeTesselator.h
@@ -0,0 +1,67 @@
+//
+// Filename : StrokeTesselator.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to build a Node Tree designed to be displayed
+// from a set of strokes 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 STROKETESSELATOR_H
+# define STROKETESSELATOR_H
+
+# include "Stroke.h"
+# include "../scene_graph/LineRep.h"
+
+class StrokeTesselator
+{
+public:
+
+ inline StrokeTesselator() {_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=false;}
+ virtual ~StrokeTesselator() {}
+
+ /*! Builds a line rep contained from a Stroke
+ */
+ LineRep* Tesselate(Stroke* iStroke) ;
+
+ /*! Builds a set of lines rep contained under a
+ * a NodeShape, itself contained under a NodeGroup from a
+ * set of strokes
+ */
+ template<class StrokeIterator>
+ NodeGroup* Tesselate(StrokeIterator begin, StrokeIterator end) ;
+
+
+
+ inline void setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;}
+ inline const FrsMaterial& frs_material() const {return _FrsMaterial;}
+
+private:
+
+ FrsMaterial _FrsMaterial;
+ bool _overloadFrsMaterial;
+};
+
+#endif // STROKETESSELATOR_H
+
diff --git a/source/blender/freestyle/intern/stroke/StyleModule.h b/source/blender/freestyle/intern/stroke/StyleModule.h
new file mode 100755
index 00000000000..c023ad7517b
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/StyleModule.h
@@ -0,0 +1,157 @@
+//
+// Filename : StyleModule.h
+// Author(s) : Stephane Grabli, Emmanuel Turquin
+// Purpose : Class representing a style module
+// 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 STYLE_MODULE_H
+# define STYLE_MODULE_H
+
+# include <iostream>
+# include <string>
+# include "../system/StringUtils.h"
+# include "StrokeLayer.h"
+# include "../system/Interpreter.h"
+# include "Operators.h"
+# include "StrokeShader.h"
+
+using namespace std;
+
+class StyleModule
+{
+public:
+
+ StyleModule(const string& file_name,
+ Interpreter* inter) : _file_name(file_name) {
+ _always_refresh = false;
+ _causal = false;
+ _drawable = true;
+ _modified = true;
+ _displayed = true;
+ _inter = inter;
+ }
+
+ ~StyleModule() {}
+
+ StrokeLayer* execute() {
+ if (!_inter) {
+ cerr << "Error: no interpreter was found to execute the script" << endl;
+ return NULL;
+ }
+
+ if (!_drawable) {
+ cerr << "Error: not drawable" << endl;
+ return NULL;
+ }
+
+ Operators::reset();
+
+ if( _inter->interpretFile(_file_name) ) {
+ cerr << "Error: interpretation failed" << endl;
+ return NULL;
+ }
+
+ Operators::StrokesContainer* strokes_set = Operators::getStrokesSet();
+ if( strokes_set->empty() ) {
+ cerr << "Error: strokes set empty" << endl;
+ return NULL;
+ }
+
+ StrokeLayer* sl = new StrokeLayer;
+ for (Operators::StrokesContainer::iterator it = strokes_set->begin();
+ it != strokes_set->end();
+ ++it)
+ sl->AddStroke(*it);
+
+ return sl;
+ }
+
+ // accessors
+
+ const string getFileName() const {
+ return _file_name;
+ }
+
+ bool getAlwaysRefresh() const {
+ return _always_refresh;
+ }
+
+ bool getCausal() const {
+ return _causal;
+ }
+
+ bool getDrawable() const {
+ return _drawable;
+ }
+
+ bool getModified() const {
+ return _modified;
+ }
+
+ bool getDisplayed() const {
+ return _displayed;
+ }
+
+ // modifiers
+
+ void setFileName(const string& file_name) {
+ _file_name = file_name;
+ }
+
+ void setAlwaysRefresh(bool b = true) {
+ _always_refresh = b;
+ }
+
+ void setCausal(bool b = true) {
+ _causal = b;
+ }
+
+ void setDrawable(bool b = true) {
+ _drawable = b;
+ }
+
+ void setModified(bool b = true) {
+ if (_always_refresh)
+ return;
+ _modified = b;
+ }
+
+ void setDisplayed(bool b = true) {
+ _displayed = b;
+ }
+
+private:
+
+ string _file_name;
+ bool _always_refresh;
+ bool _causal;
+ bool _drawable;
+ bool _modified;
+ bool _displayed;
+ Interpreter* _inter;
+};
+
+#endif // STYLE_MODULE_H
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
new file mode 100755
index 00000000000..ea5af287bbe
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.cpp
@@ -0,0 +1,73 @@
+
+//
+// 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 "TextStrokeRenderer.h"
+# include "Canvas.h"
+# include "StrokeIterators.h"
+
+TextStrokeRenderer::TextStrokeRenderer(const char* iFileName)
+:StrokeRenderer(){
+ if(!iFileName)
+ iFileName = "freestyle.txt";
+ // open the stream:
+ _ofstream.open(iFileName, ios::out);
+ if(!_ofstream.is_open()){
+ cerr << "couldn't open the output file " << iFileName << endl;
+ }
+ _ofstream << "%!FREESTYLE" << endl;
+ _ofstream << "%Creator: Freestyle (http://artis.imag.fr/Software/Freestyle)" << endl;
+ // Bounding box
+ _ofstream << 0 << " "<< 0 << " " << Canvas::getInstance()->width() << " " << Canvas::getInstance()->height() << endl;
+ _ofstream << "%u x y z tleft tright r g b ..." << endl;
+}
+
+TextStrokeRenderer::~TextStrokeRenderer(){
+ Close();
+}
+
+void TextStrokeRenderer::RenderStrokeRep(StrokeRep *iStrokeRep) const{
+ RenderStrokeRepBasic(iStrokeRep);
+}
+
+void TextStrokeRenderer::RenderStrokeRepBasic(StrokeRep *iStrokeRep) const{
+ Stroke *stroke = iStrokeRep->getStroke();
+ if(!stroke){
+ cerr << "no stroke associated with Rep" << endl;
+ return;
+ }
+
+ StrokeInternal::StrokeVertexIterator v = stroke->strokeVerticesBegin();
+ StrokeAttribute att;
+ while(!v.isEnd()){
+ att = v->attribute();
+ _ofstream << v->u() << " " << v->getProjectedX() << " " << v->getProjectedY() << " " << v->getProjectedZ() << " " \
+ << att.getThicknessL() << " " << att.getThicknessR() << " " \
+ << att.getColorR() << " " << att.getColorG() << " " << att.getColorB() << " ";
+ ++v;
+ }
+ _ofstream << endl;
+}
+
+void TextStrokeRenderer::Close(){
+ if(_ofstream.is_open())
+ _ofstream.close();
+}
+
diff --git a/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
new file mode 100755
index 00000000000..8b4b6bc80d7
--- /dev/null
+++ b/source/blender/freestyle/intern/stroke/TextStrokeRenderer.h
@@ -0,0 +1,68 @@
+//
+// Filename : TextStrokeRenderer.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to define the text rendering of a stroke
+// Format:
+// x y width height // bbox
+// //list of vertices :
+// t x y z t1 t2 r g b alpha ...
+// ...
+// Date of creation : 01/14/2005
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 TEXTSTROKERENDERER_H
+# define TEXTSTROKERENDERER_H
+
+# include "StrokeRenderer.h"
+# include "../system/FreestyleConfig.h"
+# include <fstream>
+
+/**********************************/
+/* */
+/* */
+/* TextStrokeRenderer */
+/* */
+/* */
+/**********************************/
+
+class LIB_STROKE_EXPORT TextStrokeRenderer : public StrokeRenderer
+{
+public:
+ TextStrokeRenderer(const char * iFileName = 0);
+ virtual ~TextStrokeRenderer();
+
+ /*! Renders a stroke rep */
+ virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const;
+ virtual void RenderStrokeRepBasic(StrokeRep *iStrokeRep) const;
+
+ /*! Closes the output file */
+ void Close();
+
+protected:
+ mutable ofstream _ofstream;
+};
+
+#endif // TEXTSTROKERENDERER_H
+
diff --git a/source/blender/freestyle/intern/system/BaseIterator.h b/source/blender/freestyle/intern/system/BaseIterator.h
new file mode 100755
index 00000000000..45cc19df4fe
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseIterator.h
@@ -0,0 +1,90 @@
+//
+// Filename : BaseIterator.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes defining the basic "Iterator" design pattern
+// Date of creation : 18/03/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 BASEITERATOR_H
+# define BASEITERATOR_H
+
+# include <iterator>
+
+// use for iterators defintions
+template <class Element>
+class Nonconst_traits;
+
+template <class Element>
+class Const_traits {
+public:
+ typedef Element value_type;
+ typedef const Element& reference;
+ typedef const Element* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef Nonconst_traits<Element> Non_const_traits;
+};
+
+template <class Element>
+class Nonconst_traits {
+public:
+ typedef Element value_type;
+ typedef Element& reference;
+ typedef Element* pointer;
+ typedef ptrdiff_t difference_type;
+ typedef Nonconst_traits<Element> Non_const_traits;
+};
+
+class InputIteratorTag_Traits {
+public:
+ typedef std::input_iterator_tag iterator_category;
+};
+
+class BidirectionalIteratorTag_Traits {
+public:
+ typedef std::bidirectional_iterator_tag iterator_category;
+};
+
+template<class Traits, class IteratorTagTraits>
+class IteratorBase
+{
+public:
+
+ virtual ~IteratorBase() {}
+
+ virtual bool begin() const = 0;
+ virtual bool end() const = 0;
+
+ typedef typename IteratorTagTraits::iterator_category iterator_category;
+ typedef typename Traits::value_type value_type;
+ typedef typename Traits::difference_type difference_type;
+ typedef typename Traits::pointer pointer;
+ typedef typename Traits::reference reference;
+
+protected:
+
+ IteratorBase() {}
+};
+
+#endif // BASEITERATOR_H
diff --git a/source/blender/freestyle/intern/system/BaseObject.cpp b/source/blender/freestyle/intern/system/BaseObject.cpp
new file mode 100755
index 00000000000..0cf1c917195
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseObject.cpp
@@ -0,0 +1 @@
+#include "BaseObject.h"
diff --git a/source/blender/freestyle/intern/system/BaseObject.h b/source/blender/freestyle/intern/system/BaseObject.h
new file mode 100755
index 00000000000..a8515f98385
--- /dev/null
+++ b/source/blender/freestyle/intern/system/BaseObject.h
@@ -0,0 +1,73 @@
+//
+// Filename : BaseObject.h
+// Author(s) : Stephane Grabli
+// Purpose : Base Class for most shared objects (Node, Rep).
+// Defines the addRef, release system.
+// Inspired by COM IUnknown system.
+// Date of creation : 06/02/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 BASEOBJECT_H
+# define BASEOBJECT_H
+
+#include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT BaseObject
+{
+public:
+
+ inline BaseObject() {
+ _ref_counter = 0;
+ }
+
+ virtual ~BaseObject() {}
+
+ /*! At least makes a release on this.
+ * The BaseObject::destroy method must be
+ * explicitely called at the end of any
+ * overloaded destroy
+ */
+ virtual int destroy() {
+ return release();
+ }
+
+ /*! Increments the reference counter */
+ inline int addRef() {
+ return ++_ref_counter;
+ }
+
+ /*! Decrements the reference counter */
+ inline int release() {
+ if (_ref_counter)
+ _ref_counter--;
+ return _ref_counter;
+ }
+
+private:
+
+ unsigned _ref_counter;
+};
+
+#endif // BASEOBJECT_H
diff --git a/source/blender/freestyle/intern/system/Cast.h b/source/blender/freestyle/intern/system/Cast.h
new file mode 100755
index 00000000000..15af767443e
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Cast.h
@@ -0,0 +1,44 @@
+//
+// Filename : Cast.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Cast function
+// 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 CAST_HPP
+# define CAST_HPP
+
+namespace Cast {
+
+ template <class T, class U>
+ U* cast(T* in) {
+ if (!in)
+ return NULL;
+ return dynamic_cast<U*>(in);
+ }
+
+} // end of namespace Cast
+
+#endif // CAST_HPP
diff --git a/source/blender/freestyle/intern/system/Exception.cpp b/source/blender/freestyle/intern/system/Exception.cpp
new file mode 100755
index 00000000000..d1d12d18297
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Exception.cpp
@@ -0,0 +1,24 @@
+
+//
+// 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 "Exception.h"
+
+Exception::exception_type Exception::_exception = Exception::NO_EXCEPTION;
diff --git a/source/blender/freestyle/intern/system/Exception.h b/source/blender/freestyle/intern/system/Exception.h
new file mode 100755
index 00000000000..378de6b558f
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Exception.h
@@ -0,0 +1,64 @@
+//
+// Filename : Exception.h
+// Author(s) : Stephane Grabli
+// Purpose : Singleton to manage exceptions
+// Date of creation : 10/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 EXCEPTION_H
+# define EXCEPTION_H
+
+# include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT Exception
+{
+public:
+
+ typedef enum {
+ NO_EXCEPTION,
+ UNDEFINED
+ } exception_type;
+
+ static int getException() {
+ exception_type e = _exception;
+ _exception = NO_EXCEPTION;
+ return e;
+ }
+
+ static int raiseException(exception_type exception = UNDEFINED) {
+ _exception = exception;
+ return _exception;
+ }
+
+ static void reset() {
+ _exception = NO_EXCEPTION;
+ }
+
+private:
+
+ static exception_type _exception;
+};
+
+#endif // EXCEPTION_H
diff --git a/source/blender/freestyle/intern/system/FreestyleConfig.h b/source/blender/freestyle/intern/system/FreestyleConfig.h
new file mode 100755
index 00000000000..f06b9928d1d
--- /dev/null
+++ b/source/blender/freestyle/intern/system/FreestyleConfig.h
@@ -0,0 +1,90 @@
+//
+// Filename : Config.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Configuration definitions
+// Date of creation : 25/02/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 CONFIG_H
+# define CONFIG_H
+
+# include <string>
+# include "BLI_math.h"
+
+using namespace std;
+
+namespace Config {
+
+ // Directory separators
+# ifdef WIN32
+ static const string DIR_SEP("\\");
+ static const string PATH_SEP(";");
+# else
+ static const string DIR_SEP("/");
+ static const string PATH_SEP(":");
+# endif // WIN32
+
+ // DLL import/export macros for Win32
+
+# ifndef LIB_SYSTEM_EXPORT
+# define LIB_SYSTEM_EXPORT
+# endif // LIB_SYSTEM_EXPORT
+
+# ifndef LIB_IMAGE_EXPORT
+# define LIB_IMAGE_EXPORT
+# endif // LIB_IMAGE_EXPORT
+
+# ifndef LIB_GEOMETRY_EXPORT
+# define LIB_GEOMETRY_EXPORT
+# endif // LIB_GEOMETRY_EXPORT
+
+# ifndef LIB_SCENE_GRAPH_EXPORT
+# define LIB_SCENE_GRAPH_EXPORT
+# endif // LIB_SCENE_GRAPH_EXPORT
+
+# ifndef LIB_WINGED_EDGE_EXPORT
+# define LIB_WINGED_EDGE_EXPORT
+# endif // LIB_WINGED_EDGE_EXPORT
+
+# ifndef LIB_VIEW_MAP_EXPORT
+# define LIB_VIEW_MAP_EXPORT
+# endif // LIB_VIEW_MAP_EXPORT
+
+# ifndef LIB_STROKE_EXPORT
+# define LIB_STROKE_EXPORT
+# endif // LIB_STROKE_EXPORT
+
+# ifndef LIB_RENDERING_EXPORT
+# define LIB_RENDERING_EXPORT
+# endif // LIB_RENDERING_EXPORT
+
+# ifndef LIB_WRAPPER_EXPORT
+# define LIB_WRAPPER_EXPORT
+# endif // LIB_WRAPPER_EXPORT
+
+} // end of namespace Config
+
+#endif // CONFIG_H
diff --git a/source/blender/freestyle/intern/system/Id.h b/source/blender/freestyle/intern/system/Id.h
new file mode 100755
index 00000000000..1f2206ed337
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Id.h
@@ -0,0 +1,126 @@
+//
+// Filename : Id.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Identification system
+// 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 ID_H
+# define ID_H
+
+/*! Class used to tag any object by an id .
+ * It is made of two unsigned integers.
+ */
+class Id
+{
+public:
+
+ typedef unsigned id_type;
+
+ /*! Default constructor */
+ Id() {
+ _first = 0;
+ _second = 0;
+ }
+
+ /*! Builds an Id from an integer.
+ * The second number is set to 0.
+ */
+ Id(id_type id) {
+ _first = id;
+ _second = 0;
+ }
+
+ /*! Builds the Id from the two numbers */
+ Id(id_type ifirst, id_type isecond) {
+ _first = ifirst;
+ _second = isecond;
+ }
+
+ /*! Copy constructor */
+ Id(const Id& iBrother) {
+ _first = iBrother._first;
+ _second = iBrother._second;
+ }
+
+ /*! Operator= */
+ Id& operator=(const Id& iBrother) {
+ _first = iBrother._first;
+ _second = iBrother._second;
+ return *this;
+ }
+
+ /*! Returns the first Id number */
+ id_type getFirst() const {
+ return _first;
+ }
+
+ /*! Returns the second Id number */
+ id_type getSecond() const {
+ return _second;
+ }
+
+ /*! Sets the first number constituing the Id */
+ void setFirst(id_type first) {
+ _first = first;
+ }
+
+ /*! Sets the second number constituing the Id */
+ void setSecond(id_type second) {
+ _second = second;
+ }
+
+ /*! Operator== */
+ bool operator==(const Id& id) const {
+ return ((_first == id._first) && (_second == id._second));
+ }
+
+ /*! Operator!= */
+ bool operator!=(const Id& id) const {
+ return !((*this)==id);
+ }
+
+ /*! Operator< */
+ bool operator<(const Id& id) const {
+ if (_first < id._first)
+ return true;
+ if (_first == id._first && _second < id._second)
+ return true;
+ return false;
+}
+
+private:
+
+ id_type _first;
+ id_type _second;
+};
+
+// stream operator
+inline std::ostream& operator<<(std::ostream& s, const Id& id) {
+ s << "[" << id.getFirst() << ", " << id.getSecond() << "]";
+ return s;
+}
+
+# endif // ID_H
diff --git a/source/blender/freestyle/intern/system/Interpreter.h b/source/blender/freestyle/intern/system/Interpreter.h
new file mode 100755
index 00000000000..75aaa2ccd18
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Interpreter.h
@@ -0,0 +1,56 @@
+//
+// Filename : Interpreter.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Base Class of all script interpreters
+// Date of creation : 17/04/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 INTERPRETER_H
+# define INTERPRETER_H
+
+# include <string>
+
+using namespace std;
+
+class LIB_SYSTEM_EXPORT Interpreter
+{
+ public:
+
+ Interpreter() { _language = "Unknown"; }
+
+ virtual ~Interpreter() {}; //soc
+
+ virtual int interpretFile(const string& filename) = 0;
+
+ virtual string getLanguage() const { return _language; }
+
+ virtual void reset() = 0;
+
+ protected:
+
+ string _language;
+};
+
+#endif // INTERPRETER_H
diff --git a/source/blender/freestyle/intern/system/Iterator.cpp b/source/blender/freestyle/intern/system/Iterator.cpp
new file mode 100644
index 00000000000..67acc893589
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Iterator.cpp
@@ -0,0 +1 @@
+#include "Iterator.h"
diff --git a/source/blender/freestyle/intern/system/Iterator.h b/source/blender/freestyle/intern/system/Iterator.h
new file mode 100644
index 00000000000..1801c1e3b2f
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Iterator.h
@@ -0,0 +1,41 @@
+#ifndef ITERATOR_H
+#define ITERATOR_H
+
+#include <iostream>
+#include <string>
+using namespace std;
+
+
+class Iterator
+{
+public:
+
+ virtual ~Iterator() {}
+
+ virtual string getExactTypeName() const {
+ return "Iterator";
+ }
+
+ virtual int increment() {
+ cerr << "Warning: increment() not implemented" << endl;
+ return 0;
+ }
+
+ virtual int decrement() {
+ cerr << "Warning: decrement() not implemented" << endl;
+ return 0;
+ }
+
+ virtual bool isBegin() const {
+ cerr << "Warning: isBegin() not implemented" << endl;
+ return false;
+ }
+
+ virtual bool isEnd() const {
+ cerr << "Warning: isEnd() not implemented" << endl;
+ return false;
+ }
+
+};
+
+#endif // ITERATOR_H
diff --git a/source/blender/freestyle/intern/system/Precision.h b/source/blender/freestyle/intern/system/Precision.h
new file mode 100755
index 00000000000..24327a280df
--- /dev/null
+++ b/source/blender/freestyle/intern/system/Precision.h
@@ -0,0 +1,39 @@
+//
+// Filename : Precision.h
+// Author(s) : Stephane Grabli
+// Purpose : Define the float precision used in the program
+// Date of creation : 30/07/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 PRECISION_H
+# define PRECISION_H
+
+typedef double real;
+
+# ifndef SWIG
+static const real M_EPSILON = 0.00000001;
+# endif // SWIG
+
+#endif // PRECISION_H
diff --git a/source/blender/freestyle/intern/system/ProgressBar.h b/source/blender/freestyle/intern/system/ProgressBar.h
new file mode 100755
index 00000000000..5b61f936c90
--- /dev/null
+++ b/source/blender/freestyle/intern/system/ProgressBar.h
@@ -0,0 +1,85 @@
+//
+// Filename : ProgressBar.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to encapsulate a progress bar
+// Date of creation : 27/08/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 PROGRESSBAR_H
+# define PROGRESSBAR_H
+
+# include <string>
+
+using namespace std;
+
+class ProgressBar
+{
+public:
+
+ inline ProgressBar() {
+ _numtotalsteps = 0;
+ _progress = 0;
+ }
+
+ virtual ~ProgressBar() {}
+
+ virtual void reset() {
+ _numtotalsteps = 0;
+ _progress = 0;
+ }
+
+ virtual void setTotalSteps(unsigned n) {
+ _numtotalsteps = n;
+ }
+
+ virtual void setProgress(unsigned i) {
+ _progress = i;
+ }
+
+ virtual void setLabelText(const string& s) {
+ _label = s;
+ }
+
+ /*! accessors */
+ inline unsigned int getTotalSteps() const {
+ return _numtotalsteps;
+ }
+
+ inline unsigned int getProgress() const {
+ return _progress;
+ }
+
+ inline string getLabelText() const {
+ return _label;
+ }
+
+protected:
+
+ unsigned _numtotalsteps;
+ unsigned _progress;
+ string _label;
+};
+
+#endif // PROGRESSBAR_H
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.cpp b/source/blender/freestyle/intern/system/PseudoNoise.cpp
new file mode 100755
index 00000000000..87ee45e69b2
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PseudoNoise.cpp
@@ -0,0 +1,108 @@
+
+//
+// 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 <math.h>
+#include "RandGen.h"
+#include "PseudoNoise.h"
+
+static const unsigned NB_VALUE_NOISE = 512;
+
+real *PseudoNoise::_values;
+
+PseudoNoise::PseudoNoise ()
+{
+}
+
+void
+PseudoNoise::init (long seed)
+{
+ _values = new real[NB_VALUE_NOISE];
+ RandGen::srand48(seed);
+ for (unsigned int i=0; i<NB_VALUE_NOISE; i++)
+ _values[i] = -1.0 + 2.0 * RandGen::drand48();
+}
+
+real
+PseudoNoise::linearNoise (real x)
+{
+ int i = x*NB_VALUE_NOISE;
+ real x1=_values[i%NB_VALUE_NOISE], x2=_values[(i+1)%NB_VALUE_NOISE];
+ real t=x*real(NB_VALUE_NOISE)-real(i);
+ return x1*(1-t)+x2*t;
+}
+
+real
+LanczosWindowed(real t)
+{
+ if (fabs(t)>2) return 0;
+ if (fabs(t)<M_EPSILON) return 1.0;
+ return sin(M_PI*t)/(M_PI*t) * sin(M_PI*t/2.0)/(M_PI*t/2.0);
+}
+
+real
+PseudoNoise::smoothNoise (real x)
+{
+ int i = x*NB_VALUE_NOISE;
+ real t=x*real(NB_VALUE_NOISE)-real(i);
+ if (i - 1 < 0)
+ {
+ int plus=-i/NB_VALUE_NOISE;
+ i=i+NB_VALUE_NOISE*(plus+2);
+ t=(x+plus+2)*real(NB_VALUE_NOISE)-real(i);
+ }
+
+ real x1=_values[i%NB_VALUE_NOISE], x2=_values[(i+1)%NB_VALUE_NOISE];
+ real x0=_values[(i-1)%NB_VALUE_NOISE], x3=_values[(i+2)%NB_VALUE_NOISE];
+
+ real y0=LanczosWindowed(-1-t);
+ real y1=LanczosWindowed(-t);
+ real y2=LanczosWindowed(1-t);
+ real y3=LanczosWindowed(2-t);
+ // cerr<<"x0="<<x0<<" x1="<<x1<<" x2="<<x2<<" x3="<<x3<<endl;
+ // cerr<<"y0="<<y0<<" y1="<<y1<<" y2="<<y2<<" y3="<<y3<<" :";
+ return (x0*y0+x1*y1+x2*y2+x3*y3)/(y0+y1+y2+y3);
+}
+
+real
+PseudoNoise::turbulenceSmooth (real x, unsigned nbOctave)
+{
+ real y=0;
+ real k=1.0;
+ for (unsigned i=0; i<nbOctave; i++)
+ {
+ y=y+k*smoothNoise(x*k);
+ k=k/2.0;
+ }
+ return y;
+}
+
+real
+PseudoNoise::turbulenceLinear (real x, unsigned nbOctave)
+{
+ real y=0;
+ real k=1.0;
+ for (unsigned i=0; i<nbOctave; i++)
+ {
+ y=y+k*linearNoise(x*k);
+ k=k/2.0;
+ }
+ return y;
+}
diff --git a/source/blender/freestyle/intern/system/PseudoNoise.h b/source/blender/freestyle/intern/system/PseudoNoise.h
new file mode 100755
index 00000000000..43143865600
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PseudoNoise.h
@@ -0,0 +1,58 @@
+//
+// Filename : PseudoNoise.h
+// Author(s) : Fredo Durand
+// Purpose : Class to define a pseudo Perlin noise
+// Date of creation : 16/06/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 PSEUDONOISE_H
+# define PSEUDONOISE_H
+
+# include "FreestyleConfig.h"
+# include "Precision.h"
+
+class LIB_SYSTEM_EXPORT PseudoNoise
+{
+public:
+
+ PseudoNoise ();
+
+ virtual ~PseudoNoise () {}
+
+ real smoothNoise (real x);
+ real linearNoise (real x);
+
+ real turbulenceSmooth (real x, unsigned nbOctave = 8);
+ real turbulenceLinear (real x, unsigned nbOctave = 8);
+
+ static void init (long seed);
+
+protected:
+
+ static real *_values;
+};
+
+#endif // PSEUDONOISE_H
+
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.cpp b/source/blender/freestyle/intern/system/PythonInterpreter.cpp
new file mode 100755
index 00000000000..821bd32b40b
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.cpp
@@ -0,0 +1,25 @@
+
+//
+// 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 "PythonInterpreter.h"
+
+string PythonInterpreter::_path = "";
+bool PythonInterpreter::_initialized = false;
diff --git a/source/blender/freestyle/intern/system/PythonInterpreter.h b/source/blender/freestyle/intern/system/PythonInterpreter.h
new file mode 100755
index 00000000000..1178e18cdea
--- /dev/null
+++ b/source/blender/freestyle/intern/system/PythonInterpreter.h
@@ -0,0 +1,158 @@
+//
+// Filename : PythonInterpreter.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Python Interpreter
+// Date of creation : 17/04/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 PYTHON_INTERPRETER_H
+# define PYTHON_INTERPRETER_H
+
+# include <Python.h>
+# include <iostream>
+# include "StringUtils.h"
+# include "Interpreter.h"
+
+//soc
+extern "C" {
+#include "MEM_guardedalloc.h"
+#include "BKE_main.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_report.h"
+#include "BKE_text.h"
+#include "BKE_library.h"
+#include "BPY_extern.h"
+}
+
+class LIB_SYSTEM_EXPORT PythonInterpreter : public Interpreter
+{
+ public:
+
+ PythonInterpreter() {
+ _language = "Python";
+ _context = 0;
+ //Py_Initialize();
+ }
+
+ virtual ~PythonInterpreter() {
+ //Py_Finalize();
+ }
+
+ void setContext(bContext *C) {
+ _context = C;
+ }
+
+ int interpretFile(const string& filename) {
+
+ initPath();
+
+ ReportList* reports = CTX_wm_reports(_context);
+ BKE_reports_clear(reports);
+ char *fn = const_cast<char*>(filename.c_str());
+#if 0
+ int status = BPY_run_python_script(_context, fn, NULL, reports);
+#else
+ int status;
+ Text *text = add_text(fn, G.sce);
+ if (text) {
+ status = BPY_run_python_script(_context, NULL, text, reports);
+ unlink_text(G.main, text);
+ free_libblock(&G.main->text, text);
+ } else {
+ BKE_reportf(reports, RPT_ERROR, "Cannot open file: %s", fn);
+ status = 0;
+ }
+#endif
+
+ if (status != 1) {
+ cout << "\nError executing Python script from PythonInterpreter::interpretFile" << endl;
+ cout << "File: " << fn << endl;
+ cout << "Errors: " << endl;
+ BKE_reports_print(reports, RPT_ERROR);
+ return 1;
+ }
+
+ // cleaning up
+ BKE_reports_clear(reports);
+
+ return 0;
+ }
+
+ struct Options
+ {
+ static void setPythonPath(const string& path) {
+ _path = path;
+ }
+
+ static string getPythonPath() {
+ return _path;
+ }
+ };
+
+ void reset() {
+ Py_Finalize();
+ Py_Initialize();
+ _initialized = false;
+ }
+
+private:
+
+ bContext* _context;
+
+ void initPath() {
+ if (_initialized)
+ return;
+
+ vector<string> pathnames;
+ StringUtils::getPathName(_path, "", pathnames);
+
+ struct Text *text = add_empty_text("tmp_freestyle_initpath.txt");
+ string cmd = "import sys\n";
+ txt_insert_buf(text, const_cast<char*>(cmd.c_str()));
+
+ for (vector<string>::const_iterator it = pathnames.begin(); it != pathnames.end();++it) {
+ if ( !it->empty() ) {
+ cout << "Adding Python path: " << *it << endl;
+ cmd = "sys.path.append(r\"" + *it + "\")\n";
+ txt_insert_buf(text, const_cast<char*>(cmd.c_str()));
+ }
+ }
+
+ BPY_run_python_script(_context, NULL, text, NULL);
+
+ // cleaning up
+ unlink_text(G.main, text);
+ free_libblock(&G.main->text, text);
+
+ //PyRun_SimpleString("from Freestyle import *");
+ _initialized = true;
+ }
+
+ static bool _initialized;
+ static string _path;
+};
+
+#endif // PYTHON_INTERPRETER_H
diff --git a/source/blender/freestyle/intern/system/RandGen.cpp b/source/blender/freestyle/intern/system/RandGen.cpp
new file mode 100755
index 00000000000..a328cb7f583
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RandGen.cpp
@@ -0,0 +1,86 @@
+
+//
+// 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 "RandGen.h"
+
+//
+// Macro definitions
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#define N 16
+#define MASK ((unsigned)(1 << (N - 1)) + (1 << (N - 1)) - 1)
+#define X0 0x330E
+#define X1 0xABCD
+#define X2 0x1234
+#define A0 0xE66D
+#define A1 0xDEEC
+#define A2 0x5
+#define C 0xB
+#define HI_BIT (1L << (2 * N - 1))
+
+#define LOW(x) ((unsigned)(x) & MASK)
+#define HIGH(x) LOW((x) >> N)
+#define MUL(x, y, z) { long l = (long)(x) * (long)(y); \
+ (z)[0] = LOW(l); (z)[1] = HIGH(l); }
+#define CARRY(x, y) ((unsigned long)((long)(x) + (long)(y)) > MASK)
+#define ADDEQU(x, y, z) (z = CARRY(x, (y)), x = LOW(x + (y)))
+#define SET3(x, x0, x1, x2) ((x)[0] = (x0), (x)[1] = (x1), (x)[2] = (x2))
+#define SETLOW(x, y, n) SET3(x, LOW((y)[n]), LOW((y)[(n)+1]), LOW((y)[(n)+2]))
+#define SEED(x0, x1, x2) (SET3(x, x0, x1, x2), SET3(a, A0, A1, A2), c = C)
+#define REST(v) for (i = 0; i < 3; i++) { xsubi[i] = x[i]; x[i] = temp[i]; } \
+ return (v);
+#define NEST(TYPE, f, F) TYPE f(register unsigned short *xsubi) { \
+ register int i; register TYPE v; unsigned temp[3]; \
+ for (i = 0; i < 3; i++) { temp[i] = x[i]; x[i] = LOW(xsubi[i]); } \
+ v = F(); REST(v); }
+
+static unsigned x[3] = { X0, X1, X2 }, a[3] = { A0, A1, A2 }, c = C;
+
+//
+// Methods implementation
+//
+///////////////////////////////////////////////////////////////////////////////
+
+real RandGen::drand48() {
+ static real two16m = 1.0 / (1L << N);
+ next();
+ return (two16m * (two16m * (two16m * x[0] + x[1]) + x[2]));
+}
+
+void RandGen::srand48(long seedval) {
+ SEED(X0, LOW(seedval), HIGH(seedval));
+}
+
+void RandGen::next() {
+ unsigned p[2], q[2], r[2], carry0, carry1;
+
+ MUL(a[0], x[0], p);
+ ADDEQU(p[0], c, carry0);
+ ADDEQU(p[1], carry0, carry1);
+ MUL(a[0], x[1], q);
+ ADDEQU(p[1], q[0], carry0);
+ MUL(a[1], x[0], r);
+ x[2] = LOW(carry0 + carry1 + CARRY(p[1], r[0]) + q[1] + r[1] +
+ a[0] * x[2] + a[1] * x[1] + a[2] * x[0]);
+ x[1] = LOW(p[1] + r[0]);
+ x[0] = LOW(p[0]);
+}
diff --git a/source/blender/freestyle/intern/system/RandGen.h b/source/blender/freestyle/intern/system/RandGen.h
new file mode 100755
index 00000000000..409d3b79609
--- /dev/null
+++ b/source/blender/freestyle/intern/system/RandGen.h
@@ -0,0 +1,48 @@
+//
+// Filename : RandGen.h
+// Author(s) : Fredo Durand
+// Purpose : Pseudo-random number generator
+// Date of creation : 20/05/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 RAND_GEN_H
+# define RAND_GEN_H
+
+# include "FreestyleConfig.h"
+# include "../system/Precision.h"
+
+class LIB_SYSTEM_EXPORT RandGen
+{
+public:
+
+ static real drand48();
+ static void srand48(long value);
+
+private:
+
+ static void next();
+};
+
+#endif // RAND_GEN_H
diff --git a/source/blender/freestyle/intern/system/StringUtils.cpp b/source/blender/freestyle/intern/system/StringUtils.cpp
new file mode 100755
index 00000000000..58798daf42a
--- /dev/null
+++ b/source/blender/freestyle/intern/system/StringUtils.cpp
@@ -0,0 +1,74 @@
+
+//
+// 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.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+//soc #include <qfileinfo.h>
+#include "FreestyleConfig.h"
+#include "StringUtils.h"
+
+namespace StringUtils {
+
+ void getPathName(const string& path, const string& base, vector<string>& pathnames) {
+ string dir;
+ string res;
+ char cleaned[FILE_MAX];
+ unsigned size = path.size();
+
+ pathnames.push_back(base);
+
+ for ( unsigned pos = 0, sep = path.find(Config::PATH_SEP, pos);
+ pos < size;
+ pos = sep + 1, sep = path.find(Config::PATH_SEP, pos)) {
+
+ if (sep == (unsigned)string::npos)
+ sep = size;
+
+ dir = path.substr(pos, sep - pos);
+
+ BLI_strncpy(cleaned, dir.c_str(), FILE_MAX);
+ BLI_cleanup_file(NULL, cleaned);
+ res = toAscii( string(cleaned) );
+
+ if (!base.empty())
+ res += Config::DIR_SEP + base;
+
+ pathnames.push_back(res);
+ }
+ }
+
+ string toAscii( const string &str ){
+ stringstream out("");
+ char s;
+
+ for(unsigned int i=0; i < str.size() ; i++){
+ s = ((char)(str.at(i) & 0x7F));
+ out << s;
+ }
+
+ return out.str();
+ }
+
+ const char* toAscii( const char *str ){
+ return toAscii(string(str)).c_str();
+ }
+
+
+
+} // end of namespace StringUtils
diff --git a/source/blender/freestyle/intern/system/StringUtils.h b/source/blender/freestyle/intern/system/StringUtils.h
new file mode 100755
index 00000000000..d44d3f62732
--- /dev/null
+++ b/source/blender/freestyle/intern/system/StringUtils.h
@@ -0,0 +1,62 @@
+//
+// Filename : StringUtils.h
+// Author(s) : Emmanuel Turquin
+// Purpose : String utilities
+// Date of creation : 20/05/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 STRING_UTILS_H
+# define STRING_UTILS_H
+
+# include <cstring>
+# include <vector>
+# include <string>
+# include <sstream>
+# include <iostream>
+# include "FreestyleConfig.h"
+
+//soc
+extern "C" {
+#include "BKE_utildefines.h"
+#include "BLI_blenlib.h"
+}
+
+using namespace std;
+
+namespace StringUtils {
+
+ LIB_SYSTEM_EXPORT
+ void getPathName(const string& path, const string& base, vector<string>& pathnames);
+ string toAscii( const string &str );
+ const char* toAscii( const char *str );
+
+ // STL related
+ struct ltstr{
+ bool operator()(const char* s1, const char* s2) const{
+ return strcmp(s1, s2) < 0;
+ }
+};
+
+} // end of namespace StringUtils
+
+#endif // STRING_UTILS_H
diff --git a/source/blender/freestyle/intern/system/TimeStamp.cpp b/source/blender/freestyle/intern/system/TimeStamp.cpp
new file mode 100755
index 00000000000..c66e1131611
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeStamp.cpp
@@ -0,0 +1,25 @@
+
+//
+// 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 "TimeStamp.h"
+
+LIB_SYSTEM_EXPORT
+TimeStamp* TimeStamp::_instance = 0;
diff --git a/source/blender/freestyle/intern/system/TimeStamp.h b/source/blender/freestyle/intern/system/TimeStamp.h
new file mode 100755
index 00000000000..568a7851e30
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeStamp.h
@@ -0,0 +1,71 @@
+//
+// Filename : TimeStamp.h
+// Author(s) : Stephane Grabli
+// Purpose : Class defining a singleton used as timestamp
+// Date of creation : 12/12/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 TIMESTAMP_H
+# define TIMESTAMP_H
+
+# include "FreestyleConfig.h"
+
+class LIB_SYSTEM_EXPORT TimeStamp
+{
+ public:
+
+ static inline TimeStamp* instance() {
+ if (_instance == 0)
+ _instance = new TimeStamp;
+ return _instance;
+ }
+
+ inline unsigned getTimeStamp() const {
+ return _time_stamp;
+ }
+
+ inline void increment() {
+ ++_time_stamp;
+ }
+
+ inline void reset() {
+ _time_stamp = 1;
+ }
+
+ protected:
+
+ TimeStamp() {
+ _time_stamp = 1;
+ }
+
+ TimeStamp(const TimeStamp&) {}
+
+ private:
+
+ static TimeStamp* _instance;
+ unsigned _time_stamp;
+};
+
+#endif // TIMESTAMP_H
diff --git a/source/blender/freestyle/intern/system/TimeUtils.h b/source/blender/freestyle/intern/system/TimeUtils.h
new file mode 100755
index 00000000000..99dd5b0a669
--- /dev/null
+++ b/source/blender/freestyle/intern/system/TimeUtils.h
@@ -0,0 +1,58 @@
+//
+// Filename : TimeUtils.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to measure ellapsed time
+// Date of creation : 10/04/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 TIMEUTILS_H
+# define TIMEUTILS_H
+
+#include <time.h>
+#include "FreestyleConfig.h"
+
+class Chronometer
+{
+ public:
+
+ inline Chronometer() {}
+ inline ~Chronometer() {}
+
+ inline clock_t start() {
+ _start = clock();
+ return _start;
+ }
+
+ inline double stop() {
+ clock_t stop = clock();
+ return (double)(stop - _start) / CLOCKS_PER_SEC ;
+ }
+
+ private:
+
+ clock_t _start;
+};
+
+#endif // TIMEUTILS_H
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..0551fd3ac15
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp
@@ -0,0 +1,700 @@
+
+//
+// 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;
+ if (_orthographicProjection) {
+ V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z());
+ } else {
+ V = Vec3r(_Viewpoint - firstPoint);
+ }
+ N.normalize();
+ V.normalize();
+ iFace->setDotP(N * V);
+
+ // compute the distance between the face center and the viewpoint:
+ if (_orthographicProjection) {
+ iFace->setZ(iFace->center().z() - _Viewpoint.z());
+ } else {
+ 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
+
+ //soc unused - real K1, K2
+ real 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;
+ if (_orthographicProjection) {
+ v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z());
+ } else {
+ v = Vec3r(_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);
+ normal.normalize();
+ Vec3r V;
+ if (_orthographicProjection) {
+ V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z());
+ } else {
+ V = Vec3r(_Viewpoint - point);
+ }
+ V.normalize();
+ real d = normal * V;
+ faceLayer->PushDotP(d);
+ // Find the point the closest to the viewpoint
+ if (_orthographicProjection) {
+ dist = point.z() - _Viewpoint.z();
+ } else {
+ 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..28034f3f42b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h
@@ -0,0 +1,153 @@
+//
+// 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;
+ _orthographicProjection = false;
+ _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 enableOrthographicProjection(bool b) {_orthographicProjection = b;}
+ 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
+ //oldtmp values
+ bool _computeViewIndependant;
+ real _meanK1;
+ real _meanKr;
+ real _minK1;
+ real _minKr;
+ real _maxK1;
+ real _maxKr;
+ unsigned _nPoints;
+ real _meanEdgeSize;
+ bool _orthographicProjection;
+
+ 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..b28ac575d00
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp
@@ -0,0 +1,365 @@
+
+//
+// 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;
+ }
+
+ //
+ int 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();
+ result = AB + BC;
+ if(result.norm() != 0)
+ result.normalize();
+ return 0;
+ }
+
+ int 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();
+ result = AB + BC;
+ if(result.norm() != 0)
+ result.normalize();
+ return 0;
+ }
+
+ int 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) {
+ // if we only have 2 vertices
+ result = 0;
+ return 0;
+ }
+
+ 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();
+ result = 0;
+ return -1;
+ }
+ double cosin = N1*N2;
+ if(cosin > 1)
+ cosin = 1;
+ if(cosin < -1)
+ cosin = -1;
+ result = acos(cosin);
+ return 0;
+ }
+
+ int ZDiscontinuityF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter, fe1, fe2);
+ result = fe1->z_discontinuity();
+ if(fe2!=0){
+ result += fe2->z_discontinuity();
+ result /= 2.f;
+ }
+ return 0;
+ }
+
+ int 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();
+ result = n;
+ return 0;
+ }
+
+ int MaterialF0D::operator()(Interface0DIterator& iter) {
+ FEdge *fe1, *fe2;
+ getFEdges(iter,fe1,fe2);
+
+ if(fe1 == 0)
+ getFEdges(iter, fe1, fe2);
+ if(fe1->isSmooth())
+ result = ((FEdgeSmooth*)fe1)->frs_material();
+ else
+ result = ((FEdgeSharp*)fe1)->bFrsMaterial();
+ // const SShape * sshape = getShapeF0D(iter);
+ // return sshape->material();
+ return 0;
+ }
+
+ int ShapeIdF0D::operator()(Interface0DIterator& iter) {
+ ViewShape * vshape = getShapeF0D(iter);
+ result = vshape->getId();
+ return 0;
+ }
+
+ 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;
+ }
+ result = qi1;
+ return 0;
+ }
+
+ int CurveNatureF0D::operator()(Interface0DIterator& iter) {
+ Nature::EdgeNature nat = 0;
+ ViewEdge * ve1, *ve2;
+ getViewEdges(iter, ve1, ve2);
+ nat |= ve1->getNature();
+ if(ve2!=0)
+ nat |= ve2->getNature();
+ result = nat;
+ return 0;
+ }
+
+ int GetOccludersF0D::operator()(Interface0DIterator& iter) {
+ set<ViewShape*> occluders;
+ getOccludersF0D(iter,occluders);
+ result.clear();
+ // vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end());
+ for(set<ViewShape*>::iterator it=occluders.begin(), itend=occluders.end();
+ it!=itend;
+ ++it){
+ result.push_back((*it));
+ }
+ return 0;
+ }
+
+ int GetShapeF0D::operator()(Interface0DIterator& iter) {
+ result = getShapeF0D(iter);
+ return 0;
+ }
+
+ int GetOccludeeF0D::operator()(Interface0DIterator& iter) {
+ result = getOccludeeF0D(iter);
+ return 0;
+ }
+
+} // 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..4adbc8a1bf5
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions0D.h
@@ -0,0 +1,500 @@
+//
+// 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/FrsMaterial.h"
+# include <set>
+# include <vector>
+class FEdge;
+class ViewEdge;
+class SShape;
+
+using namespace Geometry;
+
+#include "../python/Director.h"
+
+//
+// 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:
+
+ T result;
+ PyObject *py_uf0D;
+
+ /*! The type of the value
+ * returned by the functor.
+ */
+ typedef T ReturnedValueType;
+ /*! Default constructor. */
+UnaryFunction0D() { py_uf0D = 0;}
+ /*! 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 int operator()(Interface0DIterator& iter) {
+ return Director_BPy_UnaryFunction0D___call__( this, py_uf0D, iter );
+ }
+
+};
+
+# 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getX();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getY();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getZ();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getProjectedX();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getProjectedY();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter->getProjectedZ();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter.t();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int operator()(Interface0DIterator& iter) {
+ result = iter.u();
+ return 0;
+ }
+ };
+
+ // 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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<FrsMaterial>
+ {
+ public:
+ /*! Returns the string "MaterialF0D"*/
+ string getName() const {
+ return "MaterialF0D";
+ }
+ /*! the () operator.*/
+ int 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.*/
+ int 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.*/
+ 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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..8545c660084
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp
@@ -0,0 +1,231 @@
+
+//
+// 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 {
+
+ int GetXF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetYF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetZF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetProjectedXF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetProjectedYF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int GetProjectedZF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int Orientation2DF1D::operator()(Interface1D& inter) {
+ FEdge * fe = dynamic_cast<FEdge*>(&inter);
+ if(fe){
+ Vec3r res = fe->orientation2d();
+ result = Vec2f(res[0], res[1]);
+ } else {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ }
+ return 0;
+ }
+
+ int Orientation3DF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int ZDiscontinuityF1D::operator()(Interface1D& inter) {
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) {
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve) {
+ result = ve->qi();
+ return 0;
+ }
+ FEdge *fe = dynamic_cast<FEdge*>(&inter);
+ if (fe) {
+ result = ve->qi();
+ return 0;
+ }
+ result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+
+ int CurveNatureF1D::operator()(Interface1D& inter) {
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve)
+ result = 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;
+ }
+ result = nat;
+ }
+ return 0;
+ }
+
+ int TimeStampF1D::operator()(Interface1D& inter) {
+ TimeStamp *timestamp = TimeStamp::instance();
+ inter.setTimeStamp(timestamp->getTimeStamp());
+ return 0;
+ }
+
+ int ChainingTimeStampF1D::operator()(Interface1D& inter) {
+ TimeStamp *timestamp = TimeStamp::instance();
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if(ve)
+ ve->setChainingTimeStamp(timestamp->getTimeStamp());
+ return 0;
+ }
+
+ int IncrementChainingTimeStampF1D::operator()(Interface1D& inter) {
+ ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter);
+ if(ve)
+ ve->setChainingTimeStamp(ve->getChainingTimeStamp()+1);
+ return 0;
+ }
+
+ int 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());
+ }
+ result = shapesVector;
+ return 0;
+ }
+
+ int GetOccludersF1D::operator()(Interface1D& inter) {
+ vector<ViewShape*> shapesVector;
+ set<ViewShape*> shapesSet;
+ ViewEdge* ve = dynamic_cast<ViewEdge*>(&inter);
+ if (ve){
+ result = 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());
+ result = shapesVector;
+ }
+ return 0;
+ }
+
+ int 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());
+ }
+ result = shapesVector;
+ return 0;
+ }
+ // 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..ba42b25b47e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Functions1D.h
@@ -0,0 +1,555 @@
+//
+// 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 "ViewMap.h"
+# include "Functions0D.h"
+# include "Interface1D.h"
+# include "../system/Precision.h"
+# include "../system/TimeStamp.h"
+# include "../system/FreestyleConfig.h"
+
+#include "../python/Director.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:
+
+ T result;
+ PyObject *py_uf1D;
+
+ /*! 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 int operator()(Interface1D& inter) {
+ return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter );
+ }
+
+ /*! Sets the integration method */
+ void setIntegrationType(IntegrationType integration) {
+ _integration = integration;
+ }
+ /*! Returns the integration method. */
+ IntegrationType getIntegrationType() const {
+ return _integration;
+ }
+
+protected:
+
+ IntegrationType _integration;
+};
+
+
+class UnaryFunction1D_void
+{
+public:
+
+ PyObject *py_uf1D;
+
+ UnaryFunction1D_void(){_integration = MEAN;}
+ UnaryFunction1D_void(IntegrationType iType){_integration = iType;}
+ virtual ~UnaryFunction1D_void() {}
+
+ virtual string getName() const {
+ return "UnaryFunction1D_void";
+ }
+
+ int operator()(Interface1D& inter) {
+ return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter );
+ }
+
+ void setIntegrationType(IntegrationType integration) { _integration = integration; }
+ IntegrationType getIntegrationType() const { return _integration; }
+
+ protected:
+ IntegrationType _integration;
+};
+
+
+//
+// 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int 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.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+ 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.*/
+ int operator()(Interface1D& inter) {
+ result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration);
+ return 0;
+ }
+ 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.*/
+ int 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.*/
+ int 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.*/
+ int 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..48d956eec19
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface0D.h
@@ -0,0 +1,360 @@
+//
+// 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 <Python.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;
+
+#include "../system/Iterator.h" //soc
+
+//
+// Interface0D
+//
+//////////////////////////////////////////////////
+
+class FEdge;
+class SVertex;
+class ViewVertex;
+class NonTVertex;
+class TVertex;
+/*! Base class for any 0D element. */
+class Interface0D
+{
+public:
+
+ /*! Default constructor */
+ Interface0D() {}
+ virtual ~Interface0D() {}; //soc
+
+ /*! 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 {
+ PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D y coordinate of the point. */
+ virtual real getY() const {
+ PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D z coordinate of the point. */
+ virtual real getZ() const {
+ PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 3D point. */
+ virtual Geometry::Vec3f getPoint3D() const {
+ PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D x coordinate of the point. */
+ virtual real getProjectedX() const {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D y coordinate of the point. */
+ virtual real getProjectedY() const {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D z coordinate of the point. */
+ virtual real getProjectedZ() const {
+ PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the 2D point. */
+ virtual Geometry::Vec2f getPoint2D() const {
+ PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the FEdge that lies between this Interface0D and the
+ * Interface0D given as argument. */
+ virtual FEdge* getFEdge(Interface0D&) {
+ PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the Id of the point. */
+ virtual Id getId() const {
+ PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the nature of the point. */
+ virtual Nature::VertexNature getNature() const {
+ PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden");
+ return Nature::POINT;
+ }
+
+
+ /*! Cast the Interface0D in SVertex if it can be. */
+ virtual SVertex * castToSVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in ViewVertex if it can be. */
+ virtual ViewVertex * castToViewVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in NonTVertex if it can be. */
+ virtual NonTVertex * castToNonTVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden");
+ return 0;
+ }
+
+ /*! Cast the Interface0D in TVertex if it can be. */
+ virtual TVertex * castToTVertex(){
+ PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden");
+ return 0;
+ }
+
+};
+
+
+//
+// Interface0DIteratorNested
+//
+//////////////////////////////////////////////////
+
+class Interface0DIteratorNested : public Iterator
+{
+public:
+
+ virtual ~Interface0DIteratorNested() {}
+
+ virtual string getExactTypeName() const {
+ return "Interface0DIteratorNested";
+ }
+
+ virtual Interface0D& operator*() = 0;
+
+ virtual Interface0D* operator->() {
+ return &(operator*());
+ }
+
+ virtual int increment() = 0;
+
+ virtual int 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 Iterator
+{
+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". */
+ virtual 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. */
+ virtual int increment() {
+ return _iterator->increment();
+ }
+
+ /*! Decrements. */
+ virtual int decrement() {
+ return _iterator->decrement();
+ }
+
+ /*! Returns true if the pointed Interface0D is the
+ * first of the 1D element containing the points over
+ * which we're iterating.
+ */
+ virtual 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.
+ */
+ virtual 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..60cc0ebcb7e
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Interface1D.h
@@ -0,0 +1,226 @@
+//
+// 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 <Python.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;
+ unsigned size;
+ switch (integration_type) {
+ case MIN:
+ fun(it);
+ res = fun.result;++it;
+ for (; !it.isEnd(); ++it) {
+ fun(it);
+ if (fun.result < res)
+ res = fun.result;
+ }
+ break;
+ case MAX:
+ fun(it);
+ res = fun.result;++it;
+ for (; !it.isEnd(); ++it) {
+ fun(it);
+ if (fun.result > res)
+ res = fun.result;
+ }
+ break;
+ case FIRST:
+ fun(it);
+ res = fun.result;
+ break;
+ case LAST:
+ fun(--it_end);
+ res = fun.result;
+ break;
+ case MEAN:
+ default:
+ fun(it);
+ res = fun.result;++it;
+ for (size = 1; !it.isEnd(); ++it, ++size) {
+ fun(it);
+ res += fun.result;
+ }
+ res /= (size ? size : 1);
+ break;
+ }
+ return res;
+}
+
+//
+// Interface1D
+//
+//////////////////////////////////////////////////
+
+/*! Base class for any 1D element. */
+class Interface1D
+{
+public:
+
+ /*! Default constructor */
+ Interface1D() {_timeStamp=0;}
+ virtual ~Interface1D() {}; //soc
+
+ /*! 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() {
+ PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! Returns an iterator over the Interface1D vertices,
+ * pointing after the last vertex.
+ */
+ virtual Interface0DIterator verticesEnd(){
+ PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! 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) {
+ PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ /*! 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) {
+ PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden");
+ return Interface0DIterator();
+ }
+
+ // Data access methods
+
+ /*! Returns the 2D length of the 1D element. */
+ virtual real getLength2D() const {
+ PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden");
+ return 0;
+ }
+
+ /*! Returns the Id of the 1D element .*/
+ virtual Id getId() const {
+ PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden");
+ 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 {
+ PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden");
+ 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..7a7d0a51d4b
--- /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 FrsMaterial& FEdgeSharp::aFrsMaterial() const {
+ return _VertexA->shape()->frs_material(_aFrsMaterialIndex);
+}
+
+const FrsMaterial& FEdgeSharp::bFrsMaterial() const {
+ return _VertexA->shape()->frs_material(_bFrsMaterialIndex);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* FEdgeSmooth */
+ /* */
+ /* */
+ /**********************************/
+
+const FrsMaterial& FEdgeSmooth::frs_material() const {
+ return _VertexA->shape()->frs_material(_FrsMaterialIndex);
+}
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..fc0bff9cbff
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/Silhouette.h
@@ -0,0 +1,1429 @@
+//
+// 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 "Interface0D.h"
+# include "Interface1D.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/FrsMaterial.h"
+# include "../geometry/Polygon.h"
+# include "../system/Exception.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 * duplicate() {
+ 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;
+ _VertexA = NULL;
+ _VertexB = 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* duplicate()
+ {
+ 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 int increment() {
+ if (_vertex == _edge->vertexB()) {
+ _vertex = 0;
+ return 0;
+ }
+
+ _vertex = _edge->vertexB();
+ return 0;
+ }
+
+ virtual int decrement() {
+ if (_vertex == _edge->vertexA()) {
+ _vertex = 0;
+ return 0;
+ }
+ _vertex = _edge->vertexA();
+ return 0;
+ }
+
+ 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 _aFrsMaterialIndex;
+ unsigned _bFrsMaterialIndex;
+
+public:
+ /*! Returns the string "FEdgeSharp" . */
+ virtual string getExactTypeName() const {
+ return "FEdgeSharp";
+ }
+ /*! Default constructor. */
+ inline FEdgeSharp() : FEdge(){
+ _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
+ }
+ /*! Builds an FEdgeSharp going from vA to vB. */
+ inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB){
+ _aFrsMaterialIndex = _bFrsMaterialIndex = 0;
+ }
+ /*! Copy constructor. */
+ inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother){
+ _aNormal = iBrother._aNormal;
+ _bNormal = iBrother._bNormal;
+ _aFrsMaterialIndex = iBrother._aFrsMaterialIndex;
+ _bFrsMaterialIndex = iBrother._bFrsMaterialIndex;
+ }
+ /*! Destructor. */
+ virtual ~FEdgeSharp() {}
+ /*! Cloning method. */
+ virtual FEdge* duplicate(){
+ 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 aFrsMaterialIndex() const {return _aFrsMaterialIndex;}
+ /*! 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 FrsMaterial& aFrsMaterial() const ;
+ /*! Returns the index of the material of the face lying on the
+ * left of the FEdge.
+ */
+ inline unsigned bFrsMaterialIndex() const {return _bFrsMaterialIndex;}
+ /*! Returns the material of the face lying on the
+ * left of the FEdge.
+ */
+ const FrsMaterial& bFrsMaterial() 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 setaFrsMaterialIndex(unsigned i) {_aFrsMaterialIndex = i;}
+ /*! Sets the index of the material lying on the left of the FEdge.*/
+ inline void setbFrsMaterialIndex(unsigned i) {_bFrsMaterialIndex = 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 _FrsMaterialIndex;
+ // 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:
+ /*! Returns the string "FEdgeSmooth" . */
+ virtual string getExactTypeName() const {
+ return "FEdgeSmooth";
+ }
+ /*! Default constructor. */
+ inline FEdgeSmooth() : FEdge(){
+ _Face=0;
+ _FrsMaterialIndex = 0;
+ _isSmooth = true;
+ }
+ /*! Builds an FEdgeSmooth going from vA to vB. */
+ inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB){
+ _Face=0;
+ _FrsMaterialIndex = 0;
+ _isSmooth = true;
+
+ }
+ /*! Copy constructor. */
+ inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother){
+ _Normal = iBrother._Normal;
+ _Face = iBrother._Face;
+ _FrsMaterialIndex = iBrother._FrsMaterialIndex;
+ _isSmooth = true;
+ }
+ /*! Destructor. */
+ virtual ~FEdgeSmooth() {}
+ /*! Cloning method. */
+ virtual FEdge* duplicate(){
+ 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 frs_materialIndex() const {return _FrsMaterialIndex;}
+ /*! Returns the material of the face it is running accross. */
+ const FrsMaterial& frs_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 setFrsMaterialIndex(unsigned i) {_FrsMaterialIndex = 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<FrsMaterial> _FrsMaterials;
+
+ 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();
+ _FrsMaterials = iBrother._FrsMaterials;
+
+ _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)->duplicate();
+ _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 * duplicate()
+ {
+ 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->setFrsMaterialIndex(fes->frs_materialIndex());
+ }else{
+ newEdge = new FEdgeSharp((*sv), svB);
+ FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(fe);
+ se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
+ se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
+ }
+
+ 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)
+ {
+ //soc unused - 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->setFrsMaterialIndex(fes->frs_materialIndex());
+ }else{
+ newEdge = new FEdgeSharp(ioNewVertex, B);
+ FEdgeSharp * se = dynamic_cast<FEdgeSharp*>(newEdge);
+ FEdgeSharp * fes = dynamic_cast<FEdgeSharp*>(ioEdge);
+ se->setaFrsMaterialIndex(fes->aFrsMaterialIndex());
+ se->setbFrsMaterialIndex(fes->bFrsMaterialIndex());
+ }
+ 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 FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];}
+ /*! Returns the list of materials of the Shape. */
+ inline const vector<FrsMaterial>& frs_materials() const {return _FrsMaterials;}
+ 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 setFrsMaterials(const vector<FrsMaterial>& iMaterials) {_FrsMaterials = 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..c0817189bc2
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp
@@ -0,0 +1,266 @@
+
+//
+// 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 "SilhouetteGeomEngine.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;
+bool SilhouetteGeomEngine::_isOrthographicProjection = false;
+
+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;
+
+ _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0);
+}
+
+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)
+{
+ if( _isOrthographicProjection )
+ return t;
+
+ // we need to compute for each parameter t the corresponding
+ // parameter T which gives the intersection in 3D.
+ real T;
+
+ // suffix w for world, c for camera, r for retina, i for image
+ Vec3r Aw = (fe)->vertexA()->point3D();
+ Vec3r Bw = (fe)->vertexB()->point3D();
+ Vec3r Ac, Bc;
+ GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix);
+ GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix);
+ Vec3r ABc = Bc - Ac;
+#if 0
+ cout << "Ac " << Ac << endl;
+ cout << "Bc " << Bc << endl;
+ cout << "ABc " << ABc << endl;
+#endif
+ Vec3r Ai = (fe)->vertexA()->point2D();
+ Vec3r Bi = (fe)->vertexB()->point2D();
+ Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space
+ Vec3r Ir, Ic;
+ GeomUtils::fromImageToRetina(Ii, Ir, _viewport);
+
+ real alpha, beta, denom;
+ real m11 = _projectionMatrix[0][0];
+ real m13 = _projectionMatrix[0][2];
+ real m22 = _projectionMatrix[1][1];
+ real m23 = _projectionMatrix[1][2];
+
+ if (fabs(ABc[0]) > 1e-6) {
+
+ alpha = ABc[2] / ABc[0];
+ beta = Ac[2] - alpha * Ac[0];
+ denom = alpha * (Ir[0] + m13) + m11;
+ if (fabs(denom) < 1e-6)
+ goto iter;
+ Ic[0] = -beta * (Ir[0] + m13) / denom;
+// Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22;
+// Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2];
+ T = (Ic[0] - Ac[0]) / ABc[0];
+
+ } else if (fabs(ABc[1]) > 1e-6) {
+
+ alpha = ABc[2] / ABc[1];
+ beta = Ac[2] - alpha * Ac[1];
+ denom = alpha * (Ir[1] + m23) + m22;
+ if (fabs(denom) < 1e-6)
+ goto iter;
+ Ic[1] = -beta * (Ir[1] + m23) / denom;
+// Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11;
+// Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2];
+ T = (Ic[1] - Ac[1]) / ABc[1];
+
+ } else {
+
+iter: bool x_coords, less_than;
+ if (fabs(Bi[0] - Ai[0]) > 1e-6) {
+ x_coords = true;
+ less_than = Ai[0] < Bi[0];
+ } else {
+ x_coords = false;
+ less_than = Ai[1] < Bi[1];
+ }
+ Vec3r Pc, Pr, Pi;
+ real T_sta = 0.0;
+ real T_end = 1.0;
+ real delta_x, delta_y, dist, dist_threshold = 1e-6;
+ int i, max_iters = 100;
+ for (i = 0; i < max_iters; i++) {
+ T = T_sta + 0.5 * (T_end - T_sta);
+ Pc = Ac + T * ABc;
+ GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix);
+ GeomUtils::fromRetinaToImage(Pr, Pi, _viewport);
+ delta_x = Ii[0] - Pi[0];
+ delta_y = Ii[1] - Pi[1];
+ dist = sqrt(delta_x * delta_x + delta_y * delta_y);
+ if (dist < dist_threshold)
+ break;
+ if (x_coords) {
+ if (less_than) {
+ if (Pi[0] < Ii[0]) { T_sta = T; } else { T_end = T; }
+ } else {
+ if (Pi[0] > Ii[0]) { T_sta = T; } else { T_end = T; }
+ }
+ } else {
+ if (less_than) {
+ if (Pi[1] < Ii[1]) { T_sta = T; } else { T_end = T; }
+ } else {
+ if (Pi[1] > Ii[1]) { T_sta = T; } else { T_end = T; }
+ }
+ }
+ }
+#if 0
+ printf("SilhouetteGeomEngine::ImageToWorldParameter(): #iters = %d, dist = %e\n", i, dist);
+#endif
+ if (i == max_iters)
+ printf("SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = %e)\n", dist);
+ }
+
+ 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..5bd89f8a162
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h
@@ -0,0 +1,123 @@
+//
+// 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 bool _isOrthographicProjection;
+
+
+ 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..2c3a2cebadc
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp
@@ -0,0 +1,268 @@
+//
+// 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 "SteerableViewMap.h"
+#include "../image/ImagePyramid.h"
+#include "../image/Image.h"
+#include <math.h>
+#include "../geometry/Geom.h"
+using namespace Geometry;
+
+//soc #include <qstring.h>
+//soc #include <qimage.h>
+#include <sstream>
+
+extern "C" {
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+#include "intern/IMB_png.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);
+ //soc 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);
+
+ //soc QString base("SteerableViewMap");
+ string base("SteerableViewMap");
+ stringstream filename;
+
+ for(int j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ //soc
+ float coeff = 1;//1/255.f; //100*255;//*pow(2,j);
+ //soc QImage qtmp(ow, oh, QImage::Format_RGB32);
+ ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect, 0);
+ int rowbytes = ow*4;
+ char *pix;
+
+ for(int y=0;y<oh;++y){ //soc
+ for(int x=0;x<ow;++x){ //soc
+ int c = (int)(coeff*_imagesPyramids[i]->pixel(x,y,j));
+ if(c>255)
+ c=255;
+ //int c = (int)(_imagesPyramids[i]->pixel(x,y,j));
+
+ //soc qtmp.setPixel(x,y,qRgb(c,c,c));
+ pix = (char*)ibuf->rect + y*rowbytes + x*4;
+ pix[0] = pix [1] = pix[2] = c;
+ }
+ }
+
+ //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG");
+ filename << base;
+ filename << i << "-" << j << ".png";
+
+ imb_savepng(ibuf, const_cast<char *>(filename.str().c_str()), 0);
+
+ }
+ // 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..3e0979f684f
--- /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 "ViewMap.h"
+#include "ViewEdgeXBuilder.h"
+#include "../winged_edge/WXEdge.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 = 0;
+ 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 = 0;
+ 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->setFrsMaterialIndex(ifl.fl->getFace()->frs_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()->frs_materialIndex());
+ if(!(iwe.e->nature() & Nature::BORDER)) {
+ normalA = (iwe.e->GetaFace()->GetNormal());
+ matA = (iwe.e->GetaFace()->frs_materialIndex());
+ }
+ }else{
+ normalA = (iwe.e->GetbFace()->GetNormal());
+ matA = (iwe.e->GetbFace()->frs_materialIndex());
+ if(!(iwe.e->nature() & Nature::BORDER)) {
+ normalB = (iwe.e->GetaFace()->GetNormal());
+ matB = (iwe.e->GetaFace()->frs_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->setaFrsMaterialIndex(matA);
+ fe->setbFrsMaterialIndex(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..28a5d7d9dd4
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h
@@ -0,0 +1,215 @@
+//
+// 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>
+
+// soc
+// # 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);
+
+ //oldtmp 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..87624669204
--- /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..5a9d8f3b57b
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMap.h
@@ -0,0 +1,1492 @@
+//
+// 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 "Interface0D.h"
+# include "Interface1D.h"
+# include "Silhouette.h" // defines the embedding
+# include "../system/BaseIterator.h"
+# include "../system/FreestyleConfig.h"
+# include "../geometry/GeomUtils.h"
+# 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 * duplicate() = 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 * duplicate()
+ {
+ 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 setFrontSVertex(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 * duplicate()
+ {
+ 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
+ }
+
+//soc 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 * duplicate()
+ {
+ 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();
+ // duplicate vertices
+ for(vv=vvertices.begin(), vvend=vvertices.end();
+ vv!=vvend;
+ vv++)
+ {
+ ViewVertex * newVertex = (*vv)->duplicate();
+ AddVertex(newVertex);
+ }
+
+ vector<ViewEdge*>& vvedges = iBrother.edges();
+ // duplicate edges
+ for(ve=vvedges.begin(), veend=vvedges.end();
+ ve!=veend;
+ ve++)
+ {
+ ViewEdge * newEdge = (*ve)->duplicate();
+ 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 * duplicate()
+ {
+ 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..31abefbfb97
--- /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"
+#include "../system/Iterator.h" //soc
+
+ /**********************************/
+ /* */
+ /* */
+ /* 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..7e582e7f037
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp
@@ -0,0 +1,1064 @@
+
+//
+// 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 "ViewMapBuilder.h"
+#include <algorithm>
+
+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->setFrsMaterials((*it)->frs_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;
+ if (_orthographicProjection) {
+ viewvector = Vec3r(0.0, 0.0, m.z()-_viewpoint.z());
+ } else {
+ viewvector = Vec3r(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;
+ if (_orthographicProjection) {
+ u = Vec3r(0.0, 0.0, _viewpoint.z()-A.z());
+ } else {
+ u = Vec3r(_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 vp;
+ if (_orthographicProjection) {
+ vp = Vec3r(center.x(), center.y(), _viewpoint.z());
+ } else {
+ vp = Vec3r(_viewpoint);
+ }
+ Vec3r u(vp - 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, vp, 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, epsilon);
+
+ 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: 2D intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl;
+
+ if((tb < -epsilon) || (tb > 1+epsilon))
+ cerr << "Warning: 2D 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);
+
+ if((Ta < -epsilon) || (Ta > 1+epsilon))
+ cerr << "Warning: 3D intersection out of range for edge " << fA->vertexA()->getId() << " - " << fA->vertexB()->getId() << endl;
+
+ if((Tb < -epsilon) || (Tb > 1+epsilon))
+ cerr << "Warning: 3D intersection out of range for edge " << fB->vertexA()->getId() << " - " << fB->vertexB()->getId() << endl;
+
+#if 0
+ if((Ta < -epsilon) || (Ta > 1+epsilon) || (Tb < -epsilon) || (Tb > 1+epsilon)) {
+ printf("ta %.12e\n", ta);
+ printf("tb %.12e\n", tb);
+ printf("a1 %e, %e -- b1 %e, %e\n", a1[0], a1[1], b1[0], b1[1]);
+ printf("a2 %e, %e -- b2 %e, %e\n", a2[0], a2[1], b2[0], b2[1]);
+ if((Ta < -epsilon) || (Ta > 1+epsilon))
+ printf("Ta %.12e\n", Ta);
+ if((Tb < -epsilon) || (Tb > 1+epsilon))
+ printf("Tb %.12e\n", Tb);
+ printf("A1 %e, %e, %e -- B1 %e, %e, %e\n", A1[0], A1[1], A1[2], B1[0], B1[1], B1[2]);
+ printf("A2 %e, %e, %e -- B2 %e, %e, %e\n", A2[0], A2[1], A2[2], B2[0], B2[1], B2[2]);
+ }
+#endif
+
+ 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..12b1266fa12
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h
@@ -0,0 +1,226 @@
+//
+// 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 "Silhouette.h"
+# include <vector>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../scene_graph/NodeGroup.h"
+# include "../winged_edge/WXEdge.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;
+ bool _orthographicProjection;
+ 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) {
+ _orthographicProjection = (iProjectionMatrix[3][3] != 0.0);
+ 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..f99a574766b
--- /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, FrsMaterial& 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<FrsMaterial> frs_materials;
+ FrsMaterial m;
+ for(i=0; i<size; ++i){
+ load(in, m);
+ frs_materials.push_back(m);
+ }
+ vs->sshape()->setFrsMaterials(frs_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->setFrsMaterialIndex(matindex);
+ }else{
+ // aNormal
+ load(in, v);
+ fesharp->setNormalA(v);
+
+ // bNormal
+ load(in, v);
+ fesharp->setNormalB(v);
+
+ // Materials
+ READ(matindex);
+ fesharp->setaFrsMaterialIndex(matindex);
+ READ(matindex);
+ fesharp->setbFrsMaterialIndex(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->setFrontSVertex(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 FrsMaterial& 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()->frs_materials().size();
+ WRITE(size);
+ for(unsigned i=0; i<size; ++i)
+ save(out, vs->sshape()->frs_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->frs_materialIndex();
+ WRITE(index);
+ }else{
+ // aNormal
+ save(out, fesharp->normalA());
+ // bNormal
+ save(out, fesharp->normalB());
+ // aMaterial
+ index = fesharp->aFrsMaterialIndex();
+ WRITE(index);
+ // bMaterial
+ index = fesharp->bFrsMaterialIndex();
+ 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;
+
+ //soc unused - 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..185841a90ec
--- /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 "ViewMap.h"
+# include <fstream>
+# include <string>
+# include "../system/FreestyleConfig.h"
+# include "../system/ProgressBar.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..789aec0d5c3
--- /dev/null
+++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h
@@ -0,0 +1,549 @@
+//
+// 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"
+#include "../system/Iterator.h" //soc
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* 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 Iterator
+ {
+ 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.*/
+ virtual inline int 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;
+ return 0;
+ }
+ };
+
+ }
+ /**********************************/
+ /* */
+ /* */
+ /* 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 int increment(){
+ if (!_next_edge) {
+ _vertex = 0;
+ return 0;
+ }
+ _t += (float)_next_edge->getLength2D();
+ _vertex = _next_edge->vertexB();
+ _previous_edge = _next_edge;
+ _next_edge = _next_edge->nextEdge();
+ return 0;
+
+ }
+ virtual int decrement(){
+ if (!_previous_edge) {
+ _vertex = 0;
+ return 0;
+ }
+ if((!_next_edge) && (!_vertex)){
+ _vertex = _previous_edge->vertexB();
+ return 0;
+ }
+ _t -= (float)_previous_edge->getLength2D();
+ _vertex = _previous_edge->vertexA();
+ _next_edge = _previous_edge;
+ _previous_edge = _previous_edge->previousEdge();
+ return 0;
+ }
+
+ virtual bool isBegin() const {
+ return _vertex == _begin;
+ }
+
+ virtual 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 Iterator
+{
+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 int increment() {
+ cerr << "Warning: method increment() not implemented" << endl;
+ return 0;
+ }
+
+ /*! 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 int decrement(){
+ cerr << "Warning: method decrement() not implemented" << endl;
+ return 0;
+ }
+
+ /*! 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..0177dc630b8
--- /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 "Silhouette.h"
+# include "ViewMap.h"
+# include "../scene_graph/NodeShape.h"
+# include "../winged_edge/WEdge.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;_FrsMaterial.setDiffuse(0,0,0,1);_overloadFrsMaterial=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 setFrsMaterial(const FrsMaterial& iMaterial) {_FrsMaterial=iMaterial;_overloadFrsMaterial=true;}
+ inline Nature::EdgeNature nature() {return _nature;}
+ inline const FrsMaterial& frs_material() const {return _FrsMaterial;}
+
+protected:
+ virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0;
+
+private:
+ Nature::EdgeNature _nature;
+ FrsMaterial _FrsMaterial;
+ bool _overloadFrsMaterial;
+};
+
+/*! 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->frs_material().setDiffuse(0.f, 0.f, 0.f, 1.f);
+ tshape->setFrsMaterial(_FrsMaterial);
+
+ 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(_overloadFrsMaterial)
+ line->setFrsMaterial(_FrsMaterial);
+
+ // 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/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
new file mode 100755
index 00000000000..2997d9b6922
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp
@@ -0,0 +1,648 @@
+/* GTS - Library for the manipulation of triangulated surfaces
+ * Copyright (C) 1999-2002 Ray Jones, Stéphane Popinet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cstdlib> // for malloc and free
+#include "Curvature.h"
+#include <math.h>
+#include "WEdge.h"
+#include "../system/FreestyleConfig.h"
+#include "../geometry/normal_cycle.h"
+#include <set>
+#include <stack>
+
+static bool angle_obtuse (WVertex * v, WFace * f)
+{
+ WOEdge * e;
+ f->getOppositeEdge (v, e);
+
+ Vec3r vec1(e->GetaVertex()->GetVertex()-v->GetVertex());
+ Vec3r vec2(e->GetbVertex()->GetVertex()-v->GetVertex());
+ return ((vec1 * vec2) < 0);
+}
+
+// FIXME
+// WVvertex is useless but kept for history reasons
+static bool triangle_obtuse (WVertex*, WFace * f)
+{
+ bool b=false;
+ for (int i=0; i<3; i++)
+ b = b ||
+ ((f->getEdgeList()[i]->getVec3r() * f->getEdgeList()[(i+1)%3]->getVec3r()) < 0);
+ return b;
+}
+
+static real cotan (WVertex * vo, WVertex * v1, WVertex * v2)
+{
+ /* cf. Appendix B of [Meyer et al 2002] */
+ real udotv, denom;
+
+ Vec3r u(v1->GetVertex()- vo->GetVertex());
+ Vec3r v(v2->GetVertex()- vo->GetVertex());
+
+ udotv = u * v;
+ denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
+
+ /* denom can be zero if u==v. Returning 0 is acceptable, based on
+ * the callers of this function below. */
+ if (denom == 0.0) return (0.0);
+
+ return (udotv / denom);
+}
+
+static real angle_from_cotan (WVertex * vo, WVertex * v1, WVertex * v2)
+{
+ /* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */
+ real udotv, denom;
+
+ Vec3r u (v1->GetVertex()-vo->GetVertex());
+ Vec3r v(v2->GetVertex()-vo->GetVertex());
+
+ udotv = u * v;
+ denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv);
+
+ /* Note: I assume this is what they mean by using atan2 (). -Ray Jones */
+
+ /* tan = denom/udotv = y/x (see man page for atan2) */
+ return (fabs (atan2 (denom, udotv)));
+}
+
+/**
+ * gts_vertex_mean_curvature_normal:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kh: the Mean Curvature Normal at @v.
+ *
+ * Computes the Discrete Mean Curvature Normal approximation at @v.
+ * The mean curvature at @v is half the magnitude of the vector @Kh.
+ *
+ * Note: the normal computed is not unit length, and may point either
+ * into or out of the surface, depending on the curvature at @v. It
+ * is the responsibility of the caller of the function to use the mean
+ * curvature normal appropriately.
+ *
+ * This approximation is from the paper:
+ * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
+ * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
+ * VisMath '02, Berlin (Germany)
+ * http://www-grail.usc.edu/pubs.html
+ *
+ * Returns: %TRUE if the operator could be evaluated, %FALSE if the
+ * evaluation failed for some reason (@v is boundary or is the
+ * endpoint of a non-manifold edge.)
+ */
+bool gts_vertex_mean_curvature_normal (WVertex * v, Vec3r &Kh)
+{
+ real area = 0.0;
+
+ if (!v) return false;
+
+ /* this operator is not defined for boundary edges */
+ if (v->isBoundary()) return false;
+
+ WVertex::incoming_edge_iterator itE;
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ area+=(*itE)->GetaFace()->getArea();
+
+ Kh=Vec3r(0.0, 0.0, 0.0);
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ {
+ WOEdge * e = (*itE)->getPrevOnFace();
+ //if ((e->GetaVertex()==v) || (e->GetbVertex()==v)) cerr<< "BUG ";
+
+ WVertex * v1 = e->GetaVertex();
+ WVertex * v2 = e->GetbVertex();
+ real temp;
+
+ temp = cotan (v1, v, v2);
+ Kh = Vec3r(Kh+temp*(v2->GetVertex()-v->GetVertex()));
+
+ temp = cotan (v2, v, v1);
+ Kh = Vec3r(Kh+temp*(v1->GetVertex()-v->GetVertex()));
+ }
+ if (area > 0.0)
+ {
+ Kh[0] /= 2*area;
+ Kh[1] /= 2*area;
+ Kh[2] /= 2*area;
+ }
+ else return false;
+
+ return true;
+}
+
+/**
+ * gts_vertex_gaussian_curvature:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kg: the Discrete Gaussian Curvature approximation at @v.
+ *
+ * Computes the Discrete Gaussian Curvature approximation at @v.
+ *
+ * This approximation is from the paper:
+ * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds
+ * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr
+ * VisMath '02, Berlin (Germany)
+ * http://www-grail.usc.edu/pubs.html
+ *
+ * Returns: %TRUE if the operator could be evaluated, %FALSE if the
+ * evaluation failed for some reason (@v is boundary or is the
+ * endpoint of a non-manifold edge.)
+ */
+bool gts_vertex_gaussian_curvature (WVertex * v, real * Kg)
+{
+ real area = 0.0;
+ real angle_sum = 0.0;
+
+ if (!v) return false;
+ if (!Kg) return false;
+
+ /* this operator is not defined for boundary edges */
+ if (v->isBoundary()) {*Kg=0.0 ;return false;}
+
+ WVertex::incoming_edge_iterator itE;
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ area+=(*itE)->GetaFace()->getArea();
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ {
+ WOEdge * e = (*itE)->getPrevOnFace();
+ WVertex * v1 = e->GetaVertex();
+ WVertex * v2 = e->GetbVertex();
+ angle_sum += angle_from_cotan (v, v1, v2);
+ }
+
+ *Kg = (2.0*M_PI - angle_sum)/area;
+
+ return true;
+}
+
+/**
+ * gts_vertex_principal_curvatures:
+ * @Kh: mean curvature.
+ * @Kg: Gaussian curvature.
+ * @K1: first principal curvature.
+ * @K2: second principal curvature.
+ *
+ * Computes the principal curvatures at a point given the mean and
+ * Gaussian curvatures at that point.
+ *
+ * The mean curvature can be computed as one-half the magnitude of the
+ * vector computed by gts_vertex_mean_curvature_normal().
+ *
+ * The Gaussian curvature can be computed with
+ * gts_vertex_gaussian_curvature().
+ */
+void gts_vertex_principal_curvatures (real Kh, real Kg,
+ real * K1, real * K2)
+{
+ real temp = Kh*Kh - Kg;
+
+ if (!K1) return;
+ if (!K1) return;
+
+ if (temp < 0.0) temp = 0.0;
+ temp = sqrt (temp);
+ *K1 = Kh + temp;
+ *K2 = Kh - temp;
+}
+
+/* from Maple */
+static void linsolve (real m11, real m12, real b1,
+ real m21, real m22, real b2,
+ real * x1, real * x2)
+{
+ real temp;
+
+ temp = 1.0 / (m21*m12 - m11*m22);
+ *x1 = (m12*b2 - m22*b1)*temp;
+ *x2 = (m11*b2 - m21*b1)*temp;
+}
+
+/* from Maple - largest eigenvector of [a b; b c] */
+static void eigenvector (real a, real b, real c,
+ Vec3r e)
+{
+ if (b == 0.0) {
+ e[0] = 0.0;
+ } else {
+ e[0] = -(c - a - sqrt (c*c - 2*a*c + a*a + 4*b*b))/(2*b);
+ }
+ e[1] = 1.0;
+ e[2] = 0.0;
+}
+
+/**
+ * gts_vertex_principal_directions:
+ * @v: a #WVertex.
+ * @s: a #GtsSurface.
+ * @Kh: mean curvature normal (a #Vec3r).
+ * @Kg: Gaussian curvature (a real).
+ * @e1: first principal curvature direction (direction of largest curvature).
+ * @e2: second principal curvature direction.
+ *
+ * Computes the principal curvature directions at a point given @Kh
+ * and @Kg, the mean curvature normal and Gaussian curvatures at that
+ * point, computed with gts_vertex_mean_curvature_normal() and
+ * gts_vertex_gaussian_curvature(), respectively.
+ *
+ * Note that this computation is very approximate and tends to be
+ * unstable. Smoothing of the surface or the principal directions may
+ * be necessary to achieve reasonable results.
+ */
+void gts_vertex_principal_directions (WVertex * v,
+ Vec3r Kh, real Kg,
+ Vec3r &e1, Vec3r &e2)
+{
+ Vec3r N;
+ real normKh;
+
+ Vec3r basis1, basis2, d, eig;
+ real ve2, vdotN;
+ real aterm_da, bterm_da, cterm_da, const_da;
+ real aterm_db, bterm_db, cterm_db, const_db;
+ real a, b, c;
+ real K1, K2;
+ real *weights, *kappas, *d1s, *d2s;
+ int edge_count;
+ real err_e1, err_e2;
+ int e;
+ WVertex::incoming_edge_iterator itE;
+
+ /* compute unit normal */
+ normKh = Kh.norm();
+
+ if (normKh > 0.0) {
+ Kh.normalize();
+ } else {
+ /* This vertex is a point of zero mean curvature (flat or saddle
+ * point). Compute a normal by averaging the adjacent triangles
+ */
+ N[0] = N[1] = N[2] = 0.0;
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ N=Vec3r(N+(*itE)->GetaFace()->GetNormal());
+ real normN = N.norm();
+ if (normN <= 0.0)
+ return;
+ N.normalize();
+ }
+
+
+ /* construct a basis from N: */
+ /* set basis1 to any component not the largest of N */
+ basis1[0] = basis1[1] = basis1[2] = 0.0;
+ if (fabs (N[0]) > fabs (N[1]))
+ basis1[1] = 1.0;
+ else
+ basis1[0] = 1.0;
+
+ /* make basis2 orthogonal to N */
+ basis2 = (N ^ basis1);
+ basis2.normalize();
+
+ /* make basis1 orthogonal to N and basis2 */
+ basis1 = (N ^ basis2);
+ basis1.normalize();
+
+ aterm_da = bterm_da = cterm_da = const_da = 0.0;
+ aterm_db = bterm_db = cterm_db = const_db = 0.0;
+ int nb_edges=v->GetEdges().size();
+
+ weights = (real *) malloc (sizeof (real)*nb_edges);
+ kappas = (real*) malloc (sizeof (real)*nb_edges);
+ d1s = (real*) malloc (sizeof (real)*nb_edges);
+ d2s = (real*) malloc (sizeof (real)*nb_edges);
+ edge_count = 0;
+
+ for (itE=v->incoming_edges_begin();
+ itE!=v->incoming_edges_end(); itE++)
+ {
+ WOEdge * e;
+ WFace * f1, * f2;
+ real weight, kappa, d1, d2;
+ Vec3r vec_edge;
+ if (! *itE) continue;
+ e = *itE;
+
+ /* since this vertex passed the tests in
+ * gts_vertex_mean_curvature_normal(), this should be true. */
+ //g_assert (gts_edge_face_number (e, s) == 2);
+
+ /* identify the two triangles bordering e in s */
+ f1=e->GetaFace();
+ f2=e->GetbFace();
+
+ /* We are solving for the values of the curvature tensor
+ * B = [ a b ; b c ].
+ * The computations here are from section 5 of [Meyer et al 2002].
+ *
+ * The first step is to calculate the linear equations governing
+ * the values of (a,b,c). These can be computed by setting the
+ * derivatives of the error E to zero (section 5.3).
+ *
+ * Since a + c = norm(Kh), we only compute the linear equations
+ * for dE/da and dE/db. (NB: [Meyer et al 2002] has the
+ * equation a + b = norm(Kh), but I'm almost positive this is
+ * incorrect.)
+ *
+ * Note that the w_ij (defined in section 5.2) are all scaled by
+ * (1/8*A_mixed). We drop this uniform scale factor because the
+ * solution of the linear equations doesn't rely on it.
+ *
+ * The terms of the linear equations are xterm_dy with x in
+ * {a,b,c} and y in {a,b}. There are also const_dy terms that are
+ * the constant factors in the equations.
+ */
+
+ /* find the vector from v along edge e */
+ vec_edge=Vec3r(-1*e->getVec3r());
+
+ ve2 = vec_edge.squareNorm();
+ vdotN = vec_edge * N;
+
+ /* section 5.2 - There is a typo in the computation of kappa. The
+ * edges should be x_j-x_i.
+ */
+ kappa = 2.0 * vdotN / ve2;
+
+ /* section 5.2 */
+
+ /* I don't like performing a minimization where some of the
+ * weights can be negative (as can be the case if f1 or f2 are
+ * obtuse). To ensure all-positive weights, we check for
+ * obtuseness. */
+ weight = 0.0;
+ if (! triangle_obtuse(v, f1)) {
+ weight += ve2 *
+ cotan (f1->GetNextOEdge(e->twin())->GetbVertex(),
+ e->GetaVertex(), e->GetbVertex()) / 8.0;
+ } else {
+ if (angle_obtuse (v, f1)) {
+ weight += ve2 * f1->getArea() / 4.0;
+ } else {
+ weight += ve2 * f1->getArea() / 8.0;
+ }
+ }
+
+ if (! triangle_obtuse(v, f2)) {
+ weight += ve2 *
+ cotan (f2->GetNextOEdge(e)->GetbVertex(),
+ e->GetaVertex(), e->GetbVertex()) / 8.0;
+ } else {
+ if (angle_obtuse (v, f2)) {
+ weight += ve2 * f1->getArea() / 4.0;
+ } else {
+ weight += ve2 * f1->getArea() / 8.0;
+ }
+ }
+
+ /* projection of edge perpendicular to N (section 5.3) */
+ d[0] = vec_edge[0] - vdotN * N[0];
+ d[1] = vec_edge[1] - vdotN * N[1];
+ d[2] = vec_edge[2] - vdotN * N[2];
+ d.normalize();
+
+ /* not explicit in the paper, but necessary. Move d to 2D basis. */
+ d1 = d * basis1;
+ d2 = d * basis2;
+
+ /* store off the curvature, direction of edge, and weights for later use */
+ weights[edge_count] = weight;
+ kappas[edge_count] = kappa;
+ d1s[edge_count] = d1;
+ d2s[edge_count] = d2;
+ edge_count++;
+
+ /* Finally, update the linear equations */
+ aterm_da += weight * d1 * d1 * d1 * d1;
+ bterm_da += weight * d1 * d1 * 2 * d1 * d2;
+ cterm_da += weight * d1 * d1 * d2 * d2;
+ const_da += weight * d1 * d1 * (- kappa);
+
+ aterm_db += weight * d1 * d2 * d1 * d1;
+ bterm_db += weight * d1 * d2 * 2 * d1 * d2;
+ cterm_db += weight * d1 * d2 * d2 * d2;
+ const_db += weight * d1 * d2 * (- kappa);
+
+ }
+
+ /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */
+ aterm_da -= cterm_da;
+ const_da += cterm_da * normKh;
+
+ aterm_db -= cterm_db;
+ const_db += cterm_db * normKh;
+
+ /* check for solvability of the linear system */
+ if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) &&
+ ((const_da != 0.0) || (const_db != 0.0))) {
+ linsolve (aterm_da, bterm_da, -const_da,
+ aterm_db, bterm_db, -const_db,
+ &a, &b);
+
+ c = normKh - a;
+
+ eigenvector (a, b, c, eig);
+ } else {
+ /* region of v is planar */
+ eig[0] = 1.0;
+ eig[1] = 0.0;
+ }
+
+ /* Although the eigenvectors of B are good estimates of the
+ * principal directions, it seems that which one is attached to
+ * which curvature direction is a bit arbitrary. This may be a bug
+ * in my implementation, or just a side-effect of the inaccuracy of
+ * B due to the discrete nature of the sampling.
+ *
+ * To overcome this behavior, we'll evaluate which assignment best
+ * matches the given eigenvectors by comparing the curvature
+ * estimates computed above and the curvatures calculated from the
+ * discrete differential operators. */
+
+ gts_vertex_principal_curvatures (0.5 * normKh, Kg, &K1, &K2);
+
+ err_e1 = err_e2 = 0.0;
+ /* loop through the values previously saved */
+ for (e = 0; e < edge_count; e++) {
+ real weight, kappa, d1, d2;
+ real temp1, temp2;
+ real delta;
+
+ weight = weights[e];
+ kappa = kappas[e];
+ d1 = d1s[e];
+ d2 = d2s[e];
+
+ temp1 = fabs (eig[0] * d1 + eig[1] * d2);
+ temp1 = temp1 * temp1;
+ temp2 = fabs (eig[1] * d1 - eig[0] * d2);
+ temp2 = temp2 * temp2;
+
+ /* err_e1 is for K1 associated with e1 */
+ delta = K1 * temp1 + K2 * temp2 - kappa;
+ err_e1 += weight * delta * delta;
+
+ /* err_e2 is for K1 associated with e2 */
+ delta = K2 * temp1 + K1 * temp2 - kappa;
+ err_e2 += weight * delta * delta;
+ }
+ free (weights);
+ free (kappas);
+ free (d1s);
+ free (d2s);
+
+ /* rotate eig by a right angle if that would decrease the error */
+ if (err_e2 < err_e1) {
+ real temp = eig[0];
+
+ eig[0] = eig[1];
+ eig[1] = -temp;
+ }
+
+ e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0];
+ e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1];
+ e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2];
+ e1.normalize();
+
+ /* make N,e1,e2 a right handed coordinate sytem */
+ e2 = N ^ e1;
+ e2.normalize();
+}
+
+namespace OGF {
+ static real angle(WOEdge* h) {
+ Vec3r e(h->GetbVertex()->GetVertex()-h->GetaVertex()->GetVertex()) ;
+ Vec3r n1 = h->GetbFace()->GetNormal();
+ Vec3r n2 = h->GetaFace()->GetNormal();
+ real sine = (n1 ^ n2) * e / e.norm() ;
+ if(sine >= 1.0) {
+ return M_PI / 2.0 ;
+ }
+ if(sine <= -1.0) {
+ return -M_PI / 2.0 ;
+ }
+ return ::asin(sine) ;
+ }
+
+ // precondition1: P is inside the sphere
+ // precondition2: P,V points to the outside of
+ // the sphere (i.e. OP.V > 0)
+ static bool sphere_clip_vector(
+ const Vec3r& O, real r,
+ const Vec3r& P, Vec3r& V
+ ) {
+
+ Vec3r W = P - O ;
+ real a = V.squareNorm() ;
+ real b = 2.0 * V * W ;
+ real c = W.squareNorm() - r*r ;
+ real delta = b*b - 4*a*c ;
+ if(delta < 0) {
+ // Should not happen, but happens sometimes (numerical precision)
+ return true ;
+ }
+ real t = - b + ::sqrt(delta) / (2.0 * a) ;
+ if(t < 0.0) {
+ // Should not happen, but happens sometimes (numerical precision)
+ return true ;
+ }
+ if(t >= 1.0) {
+ // Inside the sphere
+ return false ;
+ }
+
+ V[0] = (t * V.x()) ;
+ V[1] = (t * V.y()) ;
+ V[2] = (t * V.z()) ;
+
+ return true ;
+ }
+
+ // TODO: check optimizations:
+ // use marking ? (measure *timings* ...)
+ void compute_curvature_tensor(
+ WVertex* start, real radius, NormalCycle& nc
+ ) {
+ // in case we have a non-manifold vertex, skip it...
+ if(start->isBoundary())
+ return;
+
+ std::set<WVertex*> vertices ;
+ const Vec3r& O = start->GetVertex() ;
+ std::stack<WVertex*> S ;
+ S.push(start) ;
+ vertices.insert(start) ;
+ while(!S.empty()) {
+ WVertex* v = S.top() ;
+ S.pop() ;
+ if(v->isBoundary())
+ continue;
+ const Vec3r& P = v->GetVertex() ;
+ WVertex::incoming_edge_iterator woeit = v->incoming_edges_begin();
+ WVertex::incoming_edge_iterator woeitend = v->incoming_edges_end();
+ for(;woeit!=woeitend; ++woeit){
+ WOEdge *h = *woeit;
+ Vec3r V(h->GetaVertex()->GetVertex()-h->GetbVertex()->GetVertex()) ;
+ if((v == start) || V * (P - O) > 0.0) {
+ bool isect = sphere_clip_vector(O, radius, P, V) ;
+ if(h->GetOwner()->GetNumberOfOEdges() == 2) {
+ real beta = angle(h) ;
+ nc.accumulate_dihedral_angle(V, beta) ;
+ }
+ if(!isect) {
+ WVertex* w = h->GetaVertex() ;
+ if(vertices.find(w) == vertices.end()) {
+ vertices.insert(w) ;
+ S.push(w) ;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ void compute_curvature_tensor_one_ring(
+ WVertex* start, NormalCycle& nc
+ ) {
+ // in case we have a non-manifold vertex, skip it...
+ if(start->isBoundary())
+ return;
+
+ WVertex::incoming_edge_iterator woeit = start->incoming_edges_begin();
+ WVertex::incoming_edge_iterator woeitend = start->incoming_edges_end();
+ for(;woeit!=woeitend; ++woeit){
+ WOEdge *h = (*woeit)->twin();
+ Vec3r hvec(h->GetbVertex()->GetVertex()-h->GetaVertex()->GetVertex());
+ nc.accumulate_dihedral_angle(hvec, angle(h)) ;
+ WOEdge *hprev = h->getPrevOnFace();
+ Vec3r hprevvec(hprev->GetbVertex()->GetVertex()-hprev->GetaVertex()->GetVertex());
+ nc.accumulate_dihedral_angle(hprevvec, angle(hprev)) ;
+ }
+ }
+
+}
diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.h b/source/blender/freestyle/intern/winged_edge/Curvature.h
new file mode 100755
index 00000000000..214a32ca922
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Curvature.h
@@ -0,0 +1,156 @@
+
+/* GTS - Library for the manipulation of triangulated surfaces
+ * Copyright (C) 1999 Stéphane Popinet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CURVATURE_H__
+#define __CURVATURE_H__
+
+# include "../system/FreestyleConfig.h"
+# include "../system/Precision.h"
+# include "../geometry/Geom.h"
+using namespace Geometry;
+
+class WVertex;
+
+class LIB_WINGED_EDGE_EXPORT CurvatureInfo
+{
+public:
+
+ CurvatureInfo()
+ {
+ K1 = 0.0;
+ K2 = 0.0;
+ e1 = Vec3r(0.0,0.0,0.0);
+ e2 = Vec3r(0.0,0.0,0.0);
+ Kr = 0.0;
+ dKr = 0.0;
+ er = Vec3r(0.0,0.0,0.0);
+ }
+
+ CurvatureInfo(const CurvatureInfo& iBrother){
+ K1 = iBrother.K1;
+ K2 = iBrother.K2;
+ e1 = iBrother.e1;
+ e2 = iBrother.e2;
+ Kr = iBrother.Kr;
+ dKr = iBrother.dKr;
+ er = iBrother.er;
+ }
+
+ CurvatureInfo(const CurvatureInfo& ca, const CurvatureInfo& cb, real t) {
+ K1 = ca.K1 + t * (cb.K1 - ca.K1);
+ K2 = ca.K2 + t * (cb.K2 - ca.K2);
+ e1 = ca.e1 + t * (cb.e1 - ca.e1);
+ e2 = ca.e2 + t * (cb.e2 - ca.e2);
+ Kr = ca.Kr + t * (cb.Kr - ca.Kr);
+ dKr = ca.dKr + t * (cb.dKr - ca.dKr);
+ er = ca.er + t * (cb.er - ca.er);
+ }
+
+ real K1; // maximum curvature
+ real K2; // minimum curvature
+ Vec3r e1; // maximum curvature direction
+ Vec3r e2; // minimum curvature direction
+ real Kr; // radial curvature
+ real dKr; // radial curvature
+ Vec3r er; // radial curvature direction
+};
+
+class Face_Curvature_Info{
+public:
+ Face_Curvature_Info() {}
+ ~Face_Curvature_Info(){
+ for(vector<CurvatureInfo*>::iterator ci=vec_curvature_info.begin(), ciend=vec_curvature_info.end();
+ ci!=ciend;
+ ++ci){
+ delete (*ci);
+ }
+ vec_curvature_info.clear();
+ }
+ vector<CurvatureInfo *> vec_curvature_info;
+};
+
+bool LIB_WINGED_EDGE_EXPORT gts_vertex_mean_curvature_normal (WVertex * v,
+ Vec3r &n);
+
+bool LIB_WINGED_EDGE_EXPORT gts_vertex_gaussian_curvature (WVertex * v,
+ real * Kg);
+
+void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_curvatures (real Kh,
+ real Kg,
+ real * K1,
+ real * K2);
+
+void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_directions (WVertex * v,
+ Vec3r Kh,
+ real Kg,
+ Vec3r &e1,
+ Vec3r &e2);
+
+/*
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000-2003 Bruno Levy
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * If you modify this software, you should include a notice giving the
+ * name of the person performing the modification, the date of modification,
+ * and the reason for such modification.
+ *
+ * Contact: Bruno Levy
+ *
+ * levy@loria.fr
+ *
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Note that the GNU General Public License does not permit incorporating
+ * the Software into proprietary programs.
+ */
+ namespace OGF {
+
+ class NormalCycle ;
+
+ void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor(
+ WVertex* start, double radius, NormalCycle& nc
+ ) ;
+
+ void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor_one_ring(
+ WVertex* start, NormalCycle& nc
+ ) ;
+ }
+
+
+#endif /* __CURVATURE_H__ */
+
diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h
new file mode 100755
index 00000000000..1f165e677f5
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/Nature.h
@@ -0,0 +1,75 @@
+//
+// Filename : Nature.h
+// Author(s) : Emmanuel Turquin
+// Purpose : Different natures for both vertices and edges
+// 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 NATURE_H
+# define NATURE_H
+
+/*! \file Nature.h
+ * Definitions of Natures of the ViewMap's elements
+ */
+
+/*! Namespace gathering the different possible
+ * natures of 0D and 1D elements of the ViewMap
+ */
+namespace Nature {
+
+ typedef unsigned short VertexNature;
+
+ /*! true for any 0D element */
+ static const VertexNature POINT = 0; // 0
+ /*! true for SVertex */
+ static const VertexNature S_VERTEX = (1 << 0); // 1
+ /*! true for ViewVertex */
+ static const VertexNature VIEW_VERTEX = (1 << 1); // 2
+ /*! true for NonTVertex */
+ static const VertexNature NON_T_VERTEX = (1 << 2); // 4
+ /*! true for TVertex */
+ static const VertexNature T_VERTEX = (1 << 3); // 8
+ /*! true for CUSP */
+ static const VertexNature CUSP = (1 << 4); // 16
+
+ typedef unsigned short EdgeNature;
+ /*! true for non feature edges (always false for 1D elements of the ViewMap) */
+ static const EdgeNature NO_FEATURE = 0; // 0
+ /*! true for silhouettes */
+ static const EdgeNature SILHOUETTE = (1 << 0); // 1
+ /*! true for borders */
+ static const EdgeNature BORDER = (1 << 1); // 2
+ /*! true for creases */
+ static const EdgeNature CREASE = (1 << 2); // 4
+ /*! true for ridges */
+ static const EdgeNature RIDGE = (1 << 3); // 8
+ /*! true for valleys */
+ static const EdgeNature VALLEY = (1 << 4); // 16
+ /*! true for suggestive contours */
+ static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32
+
+} // end of namespace Nature
+
+#endif // NATURE_H
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
new file mode 100755
index 00000000000..95be5f55794
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp
@@ -0,0 +1,732 @@
+
+//
+// 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 <iostream>
+#include "WEdge.h"
+
+/*! Temporary structures */
+class vertexdata
+{
+public:
+ WVertex *_copy;
+};
+
+class oedgedata
+{
+public:
+ WOEdge *_copy;
+};
+
+class edgedata
+{
+public:
+ WEdge *_copy;
+};
+
+class facedata
+{
+public:
+ WFace *_copy;
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WVertex */
+ /* */
+ /* */
+ /**********************************/
+
+WVertex::WVertex(WVertex& iBrother)
+{
+ _Id = iBrother._Id;
+ _Vertex = iBrother._Vertex;
+ _EdgeList = iBrother._EdgeList;
+
+ _Shape = iBrother._Shape;
+ _Smooth = iBrother._Smooth;
+ _Border = iBrother._Border;
+ userdata = NULL;
+ iBrother.userdata = new vertexdata;
+ ((vertexdata*)(iBrother.userdata))->_copy = this;
+}
+
+WVertex* WVertex::duplicate()
+{
+ WVertex *clone = new WVertex(*this);
+ return clone;
+}
+
+
+WOEdge* WVertex::incoming_edge_iterator::operator*()
+
+{
+ return _current;
+}
+void WVertex::incoming_edge_iterator::increment(){
+ WOEdge *twin = _current->twin();
+ if(!twin){
+ // we reached a hole
+ _current = 0;
+ return;
+ }
+ WOEdge *next = twin->getPrevOnFace();
+ if(next == _begin){
+ next = 0;
+ }
+ _current = next;
+}
+
+WFace* WVertex::face_iterator::operator*(){
+ WOEdge * woedge = *_edge_it;
+ if(woedge == 0)
+ return 0;
+ return (woedge)->GetbFace();
+}
+
+//bool WVertex::isBoundary () const{
+// return _Border;
+//}
+bool WVertex::isBoundary ()
+{
+ if(_Border == 1)
+ return true;
+ else if(_Border == 0)
+ return false;
+
+ vector<WEdge *>::const_iterator it;
+ for(it=_EdgeList.begin(); it!=_EdgeList.end(); it++){
+ if((*it)->GetNumberOfOEdges() == 1){
+ _Border = 1;
+ return true;
+ }
+ }
+ //if (!(*it)->GetaOEdge()->GetaFace()) return true;
+ _Border = 0;
+ return false;
+}
+
+void WVertex::AddEdge(WEdge *iEdge) {
+ _EdgeList.push_back(iEdge);
+}
+
+WVertex::incoming_edge_iterator WVertex::incoming_edges_begin(){
+ WOEdge *begin;
+ WEdge * wedge = _EdgeList.front();
+ WOEdge* aOEdge = wedge->GetaOEdge();
+ if(aOEdge->GetbVertex() == this)
+ begin = aOEdge;
+ else
+ begin = _EdgeList.front()->GetbOEdge();
+ return incoming_edge_iterator(this, begin, begin);
+}
+WVertex::incoming_edge_iterator WVertex::incoming_edges_end(){
+ WOEdge *begin;
+ WOEdge* aOEdge = _EdgeList.front()->GetaOEdge();
+ if(aOEdge->GetbVertex() == this)
+ begin = aOEdge;
+ else
+ begin = _EdgeList.front()->GetbOEdge();
+ return incoming_edge_iterator(this, begin, 0);
+}
+//WOEdge** WVertex::incoming_edge_iterator::operator->()
+//{
+// WOEdge ** ppaOEdge = (*_iter)->GetaOEdge();
+// if(aOEdge->GetbVertex() == _vertex)
+// return ppaOEdge;
+// else
+// {
+// WOEdge *bOEdge = (*_iter)->GetbOEdge();
+// return &bOEdge;
+// }
+//
+//}
+ /**********************************/
+ /* */
+ /* */
+ /* WOEdge */
+ /* */
+ /* */
+ /**********************************/
+
+WOEdge::WOEdge(WOEdge& iBrother)
+{
+ _paVertex = iBrother.GetaVertex();
+ _pbVertex = iBrother.GetbVertex();
+ _paFace = iBrother.GetaFace();
+ _pbFace = iBrother.GetbFace();
+ _pOwner = iBrother.GetOwner();
+ userdata = NULL;
+ iBrother.userdata = new oedgedata;
+ ((oedgedata*)(iBrother.userdata))->_copy = this;
+}
+
+WOEdge * WOEdge::duplicate()
+{
+ WOEdge *clone = new WOEdge(*this);
+ return clone;
+}
+
+Vec3r
+WOEdge::getVec3r ()
+{
+ return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex());
+}
+
+WOEdge * WOEdge::twin ()
+{
+ return GetOwner()->GetOtherOEdge(this);
+}
+
+WOEdge *
+WOEdge::getPrevOnFace()
+{
+ return _pbFace->GetPrevOEdge(this);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WEdge */
+ /* */
+ /* */
+ /**********************************/
+
+WEdge::WEdge(WEdge& iBrother)
+{
+ _paOEdge = NULL;
+ _pbOEdge = NULL;
+ WOEdge *aoedge = iBrother.GetaOEdge();
+ WOEdge *boedge = iBrother.GetbOEdge();
+ userdata = NULL;
+
+ if(NULL != aoedge)
+ //_paOEdge = new WOEdge(*aoedge);
+ _paOEdge = aoedge->duplicate();
+ if(NULL != boedge)
+ //_pbOEdge = new WOEdge(*boedge);
+ _pbOEdge = boedge->duplicate();
+
+ _nOEdges = iBrother.GetNumberOfOEdges();
+ _Id = iBrother.GetId();
+ iBrother.userdata = new edgedata;
+ ((edgedata*)(iBrother.userdata))->_copy = this;
+}
+
+WEdge * WEdge::duplicate()
+{
+ WEdge *clone = new WEdge(*this);
+ return clone;
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WFace */
+ /* */
+ /* */
+ /**********************************/
+
+
+WFace::WFace(WFace& iBrother)
+{
+ _OEdgeList = iBrother.getEdgeList();
+ _Normal = iBrother.GetNormal();
+ _VerticesNormals = iBrother._VerticesNormals;
+ _VerticesTexCoords = iBrother._VerticesTexCoords;
+ _Id = iBrother.GetId();
+ _FrsMaterialIndex = iBrother._FrsMaterialIndex;
+ userdata = NULL;
+ iBrother.userdata = new facedata;
+ ((facedata*)(iBrother.userdata))->_copy = this;
+}
+
+WFace * WFace::duplicate()
+{
+ WFace * clone = new WFace(*this);
+ return clone;
+}
+
+const FrsMaterial& WFace::frs_material() {
+ return getShape()->frs_material(_FrsMaterialIndex);
+}
+
+WOEdge * WFace::MakeEdge(WVertex *v1, WVertex *v2)
+{
+ // First check whether the same oriented edge already exists
+ // or not:
+ vector<WEdge *>& v1Edges = v1->GetEdges();
+ for(vector<WEdge*>::iterator it1=v1Edges.begin(), end=v1Edges.end();
+ it1!=end;
+ it1++)
+ {
+
+ WEdge *we=(*it1);
+
+ WOEdge *woea = we->GetaOEdge();
+
+ if((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2))
+ //if((*it1)->GetbVertex() == v2)
+ {
+ // The oriented edge already exists
+ cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
+ // Adds the edge to the face
+ //AddEdge((*it1)->GetaOEdge());
+ AddEdge(woea);
+ (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1);
+ //sets these vertices as border:
+ v1->setBorder(true);
+ v2->setBorder(true);
+ //return (*it1)->GetaOEdge();
+ return woea;
+ }
+
+ WOEdge *woeb = we->GetbOEdge();
+ if((woeb != 0) && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2))
+
+ //if((*it1)->GetbVertex() == v2)
+
+ {
+ // The oriented edge already exists
+ cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
+ // Adds the edge to the face
+ //AddEdge((*it1)->GetaOEdge());
+ AddEdge(woeb);
+ (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1);
+ //sets these vertices as border:
+ v1->setBorder(true);
+ v2->setBorder(true);
+ //return (*it1)->GetaOEdge();
+ return woeb;
+ }
+ }
+
+ // the oriented edge we're about to build
+ WOEdge *pOEdge = new WOEdge;
+
+ WEdge * edge; // The edge containing the oriented edge.
+
+ // checks whether this edge already exists or not
+ // If it exists, it points outward v2
+
+ bool exist = false;
+ WOEdge *pInvertEdge = NULL; // The inverted edge if it exists
+ vector<WEdge *>& v2Edges = v2->GetEdges();
+ vector<WEdge *>::iterator it;
+ for(it=v2Edges.begin(); it!=v2Edges.end(); it++)
+ {
+ if((*it)->GetbVertex() == v1)
+ {
+ // The invert edge already exists
+ exist = true;
+ pInvertEdge = (*it)->GetaOEdge();
+ break;
+ }
+ }
+
+ //DEBUG:
+
+
+ if(true == exist) // The invert edge already exists
+ {
+ // Retrieves the corresponding edge
+ edge = pInvertEdge->GetOwner();
+
+ // Sets the a Face (retrieved from pInvertEdge
+ pOEdge->setaFace(pInvertEdge->GetbFace());
+
+ // Updates the invert edge:
+ pInvertEdge->setaFace(this);
+ }
+ else // The invert edge does not exist yet
+ {
+ // we must create a new edge
+ //edge = new WEdge;
+ edge = instanciateEdge();
+
+ // updates the a,b vertex edges list:
+ v1->AddEdge(edge);
+ v2->AddEdge(edge);
+
+ }
+
+ pOEdge->setOwner(edge);
+ // Add the vertices:
+ pOEdge->setaVertex(v1);
+ pOEdge->setbVertex(v2);
+
+ // Debug:
+ if(v1->GetId() == v2->GetId())
+ cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl;
+
+ edge->AddOEdge(pOEdge);
+ //edge->setNumberOfOEdges(edge->GetNumberOfOEdges()+1);
+
+ // Add this face (the b face)
+ pOEdge->setbFace(this);
+
+ // Adds the edge to the face
+ AddEdge(pOEdge);
+
+ return pOEdge;
+}
+
+
+bool
+WFace::getOppositeEdge (const WVertex *v, WOEdge* &e)
+{
+ if (_OEdgeList.size()!=3) return false;
+
+ vector<WOEdge *>::iterator it;
+ e=NULL;
+ for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++)
+ if ((*it)->GetaVertex()==v) e=*it;
+ if (!e) return false;
+ e=NULL;
+ for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++)
+ if (((*it)->GetaVertex()!=v) && ((*it)->GetbVertex()!=v)) e=*it;
+ if (!e) return false;
+ else return true;
+}
+
+real
+WFace::getArea ()
+{
+ vector<WOEdge *>::iterator it;
+ Vec3r origin=(*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
+ it=_OEdgeList.begin();
+ real a=0;
+ for (it=it++; it!=_OEdgeList.end(); it++) {
+ Vec3r v1=Vec3r((*it)->GetaVertex()->GetVertex() - origin);
+ Vec3r v2=Vec3r((*it)->GetbVertex()->GetVertex() - origin);
+ a += (v1 ^ v2).norm() / 2.0;
+ }
+ return a;
+}
+
+
+WOEdge*
+WFace::GetPrevOEdge(WOEdge* iOEdge)
+ {
+ vector<WOEdge*>::iterator woe,woend, woefirst;
+ woefirst = _OEdgeList.begin();
+ woend=_OEdgeList.end();
+ WOEdge *prev =*woefirst;
+ woe=woefirst;
+ woe++;
+ for(;
+ woe!=woend;
+ woe++)
+ {
+ if((*woe) == iOEdge)
+ return prev;
+ prev= *woe;
+ }
+ // We left the loop. That means that the first
+ // OEdge was the good one:
+ if((*woefirst)==iOEdge)
+ return prev;
+
+ return NULL;
+ }
+
+WShape * WFace::getShape()
+{
+ return GetVertex(0)->shape();
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+LIB_WINGED_EDGE_EXPORT
+unsigned WShape::_SceneCurrentId = 0;
+
+WShape * WShape::duplicate()
+{
+ WShape *clone = new WShape(*this);
+ return clone;
+}
+
+WShape::WShape(WShape& iBrother)
+{
+ _Id = iBrother.GetId();
+ _FrsMaterials = iBrother._FrsMaterials;
+ _meanEdgeSize = iBrother._meanEdgeSize;
+ iBrother.bbox(_min, _max);
+ vector<WVertex*>& vertexList = iBrother.getVertexList();
+ vector<WVertex*>::iterator v=vertexList.begin(), vend=vertexList.end();
+ for(;
+ v!=vend;
+ v++)
+ {
+ //WVertex *newVertex = new WVertex(*(*v));
+ WVertex *newVertex = (*v)->duplicate();
+
+ newVertex->setShape(this);
+ AddVertex(newVertex);
+ }
+
+ vector<WEdge*>& edgeList = iBrother.getEdgeList();
+ vector<WEdge*>::iterator e=edgeList.begin(), eend=edgeList.end();
+ for(;
+ e!=eend;
+ e++)
+ {
+ //WEdge *newEdge = new WEdge(*(*e));
+ WEdge *newEdge = (*e)->duplicate();
+ AddEdge(newEdge);
+ }
+
+ vector<WFace*>& faceList = iBrother.GetFaceList();
+ vector<WFace*>::iterator f=faceList.begin(), fend=faceList.end();
+ for(;
+ f!=fend;
+ f++)
+ {
+ //WFace *newFace = new WFace(*(*f));
+ WFace *newFace = (*f)->duplicate();
+ AddFace(newFace);
+ }
+
+ // update all pointed addresses thanks to the newly created objects:
+ vend=_VertexList.end();
+ for(v=_VertexList.begin();
+ v!=vend;
+ v++)
+ {
+ const vector<WEdge*>& vedgeList = (*v)->GetEdges();
+ vector<WEdge*> newvedgelist;
+ unsigned int i;
+ for(i=0; i<vedgeList.size(); i++)
+ {
+ WEdge *current = vedgeList[i];
+ edgedata * currentvedata = (edgedata*)current->userdata;
+ newvedgelist.push_back(currentvedata->_copy);
+ }
+ (*v)->setEdges(newvedgelist);
+ }
+
+ eend = _EdgeList.end();
+ for(e=_EdgeList.begin();
+ e!=eend;
+ e++)
+ {
+ // update aOedge:
+ WOEdge *aoEdge = (*e)->GetaOEdge();
+ aoEdge->setaVertex(((vertexdata*)(aoEdge->GetaVertex()->userdata))->_copy);
+ aoEdge->setbVertex(((vertexdata*)(aoEdge->GetbVertex()->userdata))->_copy);
+ if(NULL != aoEdge->GetaFace())
+ aoEdge->setaFace(((facedata*)(aoEdge->GetaFace()->userdata))->_copy);
+ aoEdge->setbFace(((facedata*)(aoEdge->GetbFace()->userdata))->_copy);
+ aoEdge->setOwner(((edgedata*)(aoEdge->GetOwner()->userdata))->_copy);
+ // update bOedge:
+
+ WOEdge *boEdge = (*e)->GetbOEdge();
+ if(boEdge != 0)
+ {
+ boEdge->setaVertex(((vertexdata*)(boEdge->GetaVertex()->userdata))->_copy);
+ boEdge->setbVertex(((vertexdata*)(boEdge->GetbVertex()->userdata))->_copy);
+ if(NULL != boEdge->GetaFace())
+ boEdge->setaFace(((facedata*)(boEdge->GetaFace()->userdata))->_copy);
+ boEdge->setbFace(((facedata*)(boEdge->GetbFace()->userdata))->_copy);
+ boEdge->setOwner(((edgedata*)(boEdge->GetOwner()->userdata))->_copy);
+ }
+ }
+
+ fend = _FaceList.end();
+ for(f=_FaceList.begin();
+ f!=fend;
+ f++)
+ {
+ unsigned i;
+ const vector<WOEdge*>& oedgeList = (*f)->getEdgeList();
+ vector<WOEdge*> newoedgelist;
+
+ unsigned n = oedgeList.size();
+ for(i=0; i<n; i++)
+ {
+ WOEdge *current = oedgeList[i];
+ oedgedata * currentoedata = (oedgedata*)current->userdata;
+ newoedgelist.push_back(currentoedata->_copy);
+ //oedgeList[i] = currentoedata->_copy;
+ //oedgeList[i] = ((oedgedata*)(oedgeList[i]->userdata))->_copy;
+ }
+ (*f)->setEdgeList(newoedgelist);
+ }
+
+ // Free all memory (arghh!)
+ // Vertex
+ vend = iBrother.getVertexList().end();
+ for(v=iBrother.getVertexList().begin();
+ v!=vend;
+ v++)
+ {
+ delete (vertexdata*)((*v)->userdata);
+ (*v)->userdata = NULL;
+ }
+
+ // Edges and OEdges:
+ eend = iBrother.getEdgeList().end();
+ for(e=iBrother.getEdgeList().begin();
+ e!=eend;
+ e++)
+ {
+ delete (edgedata*)((*e)->userdata);
+ (*e)->userdata = NULL;
+ // OEdge a :
+ delete (oedgedata*)((*e)->GetaOEdge()->userdata);
+ (*e)->GetaOEdge()->userdata = NULL;
+ // OEdge b:
+ WOEdge* oedgeb = (*e)->GetbOEdge();
+ if(NULL != oedgeb)
+ {
+ delete (oedgedata*)(oedgeb->userdata);
+ oedgeb->userdata = NULL;
+ }
+ }
+ // Faces
+ fend = iBrother.GetFaceList().end();
+ for(f=iBrother.GetFaceList().begin();
+ f!=fend;
+ f++)
+ {
+ delete (facedata*)((*f)->userdata);
+ (*f)->userdata = NULL;
+ }
+}
+
+WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial)
+{
+ // allocate the new face
+ WFace *face = instanciateFace();
+
+ return MakeFace(iVertexList, iMaterial, face);
+}
+
+WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterial)
+{
+ // allocate the new face
+ WFace *face = MakeFace(iVertexList, iMaterial);
+
+ if(0 == face)
+
+ return 0;
+
+ // set the list of per-vertex normals
+ face->setNormalList(iNormalsList);
+ // set the list of per-vertex tex coords
+ face->setTexCoordsList(iTexCoordsList);
+
+ return face;
+}
+
+WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial, WFace *face)
+{
+
+ int id = _FaceList.size();
+
+ face->setFrsMaterialIndex(iMaterial);
+
+ // Check whether we have a degenerated face:
+
+ // LET'S HACK IT FOR THE TRIANGLE CASE:
+
+ if(3 == iVertexList.size())
+
+ {
+
+ if((iVertexList[0] == iVertexList[1])
+
+ || (iVertexList[0] == iVertexList[2])
+
+ || (iVertexList[2] == iVertexList[1]))
+
+ {
+
+ cerr << "Warning: degenerated triangle detected, correcting" << endl;
+ return 0;
+
+ }
+
+ }
+ // vertex pointers used to build each edge
+ vector<WVertex*>::iterator va, vb, it;
+
+ va = iVertexList.begin();
+ vb = va;
+ for(; va != iVertexList.end(); va = vb)
+ {
+ vb++;
+ // Adds va to the vertex list:
+ //face->AddVertex(*va);
+
+ WOEdge * oedge;
+ if(*va == iVertexList.back())
+ oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge
+ else
+ oedge = face->MakeEdge(*va, *vb);
+
+
+ if(oedge == 0)
+ return 0;
+
+
+ WEdge *edge = oedge->GetOwner();
+ if(1 == edge->GetNumberOfOEdges())
+ {
+ // means that we just created a new edge and that we must add it to the
+ // shape's edges list
+ edge->setId(_EdgeList.size());
+ AddEdge(edge);
+ // compute the mean edge value:
+ _meanEdgeSize += edge->GetaOEdge()->getVec3r().norm();
+ }
+ }
+
+ // compute the face normal (v1v2 ^ v1v3)
+ WVertex *v1, *v2, *v3;
+ it = iVertexList.begin();
+ v1 = *it;
+ it++;
+ v2 = *it;
+ it++;
+ v3 = *it;
+
+ Vec3r vector1(v2->GetVertex()-v1->GetVertex());
+ Vec3r vector2(v3->GetVertex()-v1->GetVertex());
+
+ Vec3r normal(vector1 ^ vector2);
+ normal.normalize();
+ face->setNormal(normal);
+
+ // Add the face to the shape's faces list:
+ face->setId(id);
+ AddFace(face);
+
+ return face;
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h
new file mode 100755
index 00000000000..9b05b4577a9
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WEdge.h
@@ -0,0 +1,955 @@
+//
+// Filename : WEdge.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define a Winged Edge data structure.
+// Date of creation : 18/02/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 WEDGE_H
+# define WEDGE_H
+
+# include <vector>
+# include <iterator>
+# include "../system/FreestyleConfig.h"
+# include "../geometry/Geom.h"
+# include "../scene_graph/FrsMaterial.h"
+
+using namespace std;
+using namespace Geometry;
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WVertex */
+ /* */
+ /* */
+ /**********************************/
+
+
+class WOEdge;
+class WEdge;
+class WShape;
+class WFace;
+class LIB_WINGED_EDGE_EXPORT WVertex
+{
+protected:
+ int _Id; // an identificator
+ Vec3r _Vertex;
+ vector<WEdge*> _EdgeList;
+ WShape * _Shape; // the shape to which the vertex belongs
+ bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not
+ int _Border; // 1 -> border, 0 -> no border, -1 -> not set
+
+public:
+ void * userdata; // designed to store specific user data
+ inline WVertex(const Vec3r &v) {_Id = 0; _Vertex = v; userdata = NULL; _Shape = NULL;_Smooth=true;_Border=-1;}
+ /*! Copy constructor */
+ WVertex(WVertex& iBrother);
+ virtual WVertex * duplicate();
+ virtual ~WVertex() {}
+
+ /*! accessors */
+ inline Vec3r& GetVertex() {return _Vertex;}
+ inline vector<WEdge*>& GetEdges() {return _EdgeList;}
+ inline int GetId() {return _Id;}
+ inline WShape * shape() const {return _Shape;}
+ inline bool isSmooth() const {return _Smooth;}
+ bool isBoundary();
+
+ /*! modifiers */
+ inline void setVertex(const Vec3r& v) {_Vertex = v;}
+ inline void setEdges(const vector<WEdge *>& iEdgeList) {_EdgeList = iEdgeList;}
+ inline void setId(int id) {_Id = id;}
+ inline void setShape(WShape *iShape) {_Shape = iShape;}
+ inline void setSmooth(bool b) {_Smooth = b;}
+ inline void setBorder(bool b) {if(b) _Border= 1; else _Border = 0;}
+
+ /*! Adds an edge to the edges list */
+ void AddEdge(WEdge *iEdge) ;
+
+ virtual void ResetUserData() {userdata = 0;}
+
+
+
+public:
+
+
+
+ /*! Iterator to iterate over a vertex incoming edges in the CCW order*/
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ class incoming_edge_iterator : public input_iterator<WOEdge*,ptrdiff_t>
+# else
+ class LIB_WINGED_EDGE_EXPORT incoming_edge_iterator : public iterator<input_iterator_tag, WOEdge*,ptrdiff_t>
+# endif
+ {
+ private:
+ WVertex *_vertex;
+ //
+ WOEdge *_begin;
+ WOEdge *_current;
+
+ public:
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ inline incoming_edge_iterator() : input_iterator<WOEdge*,ptrdiff_t>() {}
+# else
+ inline incoming_edge_iterator() : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>() {}
+# endif
+ virtual ~incoming_edge_iterator() {}; //soc
+
+ protected:
+ friend class WVertex;
+ inline incoming_edge_iterator(
+ WVertex *iVertex,
+ WOEdge * iBegin,
+ WOEdge * iCurrent)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WOEdge*,ptrdiff_t>()
+# else
+ : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>()
+# endif
+ {
+ _vertex = iVertex;
+ _begin = iBegin;
+ _current = iCurrent;
+ }
+
+ public:
+ inline incoming_edge_iterator(const incoming_edge_iterator& iBrother)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WOEdge*,ptrdiff_t>(iBrother)
+# else
+ : iterator<input_iterator_tag, WOEdge*,ptrdiff_t>(iBrother)
+# endif
+ {
+ _vertex = iBrother._vertex;
+ _begin = iBrother._begin;
+ _current = iBrother._current;
+ }
+
+ public:
+ // operators
+ virtual incoming_edge_iterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ virtual incoming_edge_iterator operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ incoming_edge_iterator tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const incoming_edge_iterator& b) const
+ {
+ return ((_current) != (b._current));
+ }
+
+ virtual bool operator==(const incoming_edge_iterator& b) const
+ {
+ return ((_current)== (b._current));
+ }
+
+ // dereferencing
+ virtual WOEdge* operator*();
+ //virtual WOEdge** operator->();
+ protected:
+ virtual void increment();
+ };
+
+
+ /*! Iterator to iterate over a vertex faces in the CCW order */
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ class face_iterator : public input_iterator<WFace*,ptrdiff_t>
+# else
+ class LIB_WINGED_EDGE_EXPORT face_iterator : public iterator<input_iterator_tag, WFace*,ptrdiff_t>
+# endif
+ {
+ private:
+ incoming_edge_iterator _edge_it;
+
+ public:
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ inline face_iterator() : input_iterator<WFace*,ptrdiff_t>() {}
+# else
+ inline face_iterator() : iterator<input_iterator_tag, WFace*,ptrdiff_t>() {}
+# endif
+ virtual ~face_iterator() {}; //soc
+
+ protected:
+ friend class WVertex;
+ inline face_iterator(
+ incoming_edge_iterator it)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WFace*,ptrdiff_t>()
+# else
+ : iterator<input_iterator_tag, WFace*,ptrdiff_t>()
+# endif
+ {
+ _edge_it = it;
+ }
+
+ public:
+ inline face_iterator(const face_iterator& iBrother)
+# if defined(__GNUC__) && (__GNUC__ < 3)
+ : input_iterator<WFace*,ptrdiff_t>(iBrother)
+# else
+ : iterator<input_iterator_tag, WFace*,ptrdiff_t>(iBrother)
+# endif
+ {
+ _edge_it = iBrother._edge_it;
+ }
+
+ public:
+ // operators
+ virtual face_iterator& operator++() // operator corresponding to ++i
+ {
+ increment();
+ return *this;
+ }
+ virtual face_iterator operator++(int) // opérateur correspondant à i++
+ { // c.a.d qui renvoie la valeur *puis* incrémente.
+ face_iterator tmp = *this; // C'est pour cela qu'on stocke la valeur
+ increment(); // dans un temporaire.
+ return tmp;
+ }
+
+ // comparibility
+ virtual bool operator!=(const face_iterator& b) const
+ {
+ return ((_edge_it) != (b._edge_it));
+ }
+
+ virtual bool operator==(const face_iterator& b) const
+ {
+ return ((_edge_it)== (b._edge_it));
+ }
+
+ // dereferencing
+ virtual WFace* operator*();
+ //virtual WOEdge** operator->();
+ protected:
+ inline void increment(){
+ ++_edge_it;
+ }
+ };
+
+public:
+ /*! iterators access */
+ virtual incoming_edge_iterator incoming_edges_begin();
+ virtual incoming_edge_iterator incoming_edges_end() ;
+
+ virtual face_iterator faces_begin() {
+ return face_iterator(incoming_edges_begin());
+ }
+ virtual face_iterator faces_end() {
+ return face_iterator(incoming_edges_end());
+ }
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WOEdge */
+ /* */
+ /* */
+ /**********************************/
+class WFace;
+class WEdge;
+
+class LIB_WINGED_EDGE_EXPORT WOEdge
+{
+protected:
+ // WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge
+ // WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge
+ // WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge
+ // WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge
+ WVertex *_paVertex; // starting vertex
+ WVertex *_pbVertex; // ending vertex
+ WFace *_paFace; // when following the edge, face on the right
+ WFace *_pbFace; // when following the edge, face on the left
+ WEdge *_pOwner; // Edge
+
+public:
+ void *userdata;
+ inline WOEdge()
+ {
+ // _paCWEdge = NULL;
+ // _pbCWEdge = NULL;
+ // _paCCWEdge = NULL;
+ // _pbCCWEdge = NULL;
+ _paVertex = NULL;
+ _pbVertex = NULL;
+ _paFace = NULL;
+ _pbFace = NULL;
+ _pOwner = NULL;
+ userdata = NULL;
+ }
+ virtual ~WOEdge() {}; //soc
+
+ /*! copy constructor */
+ WOEdge(WOEdge& iBrother);
+ virtual WOEdge * duplicate();
+
+ /*! accessors */
+ // inline WOEdge *GetaCWEdge() {return _paCWEdge;}
+ // inline WOEdge *GetbCWEdge() {return _pbCWEdge;}
+ // inline WOEdge *GetaCCWEdge() {return _paCCWEdge;}
+ // inline WOEdge *GetbCCWEdge() {return _pbCCWEdge;}
+ inline WVertex *GetaVertex() {return _paVertex;}
+ inline WVertex *GetbVertex() {return _pbVertex;}
+ inline WFace *GetaFace() {return _paFace;}
+ inline WFace *GetbFace() {return _pbFace;}
+ inline WEdge *GetOwner() {return _pOwner;}
+
+
+ /*! modifiers */
+ // inline void SetaCWEdge(WOEdge *pe) {_paCWEdge = pe;}
+ // inline void SetbCWEdge(WOEdge *pe) {_pbCWEdge = pe;}
+ // inline void SetaCCWEdge(WOEdge *pe) {_paCCWEdge = pe;}
+ // inline void SetbCCCWEdge(WOEdge *pe) {_pbCCWEdge = pe;}
+ inline void setaVertex(WVertex *pv) {_paVertex = pv;}
+ inline void setbVertex(WVertex *pv) {_pbVertex = pv;}
+ inline void setaFace(WFace *pf) {_paFace = pf;}
+ inline void setbFace(WFace *pf) {_pbFace = pf;}
+ inline void setOwner(WEdge *pe) {_pOwner = pe;}
+
+ /*! Retrieves the list of edges in CW order */
+ inline void RetrieveCWOrderedEdges(vector<WEdge*>& oEdges);
+ /*! returns the vector between the two vertices */
+ Vec3r getVec3r ();
+ WOEdge * twin ();
+ WOEdge * getPrevOnFace();
+ virtual void ResetUserData() {userdata = 0;}
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WEdge */
+ /* */
+ /* */
+ /**********************************/
+
+class LIB_WINGED_EDGE_EXPORT WEdge
+{
+protected:
+ WOEdge *_paOEdge; // first oriented edge
+ WOEdge *_pbOEdge; // second oriented edge
+ int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge)
+ int _Id; // Identifier for the edge
+
+public:
+ void * userdata; // designed to store specific user data
+ inline WEdge()
+ {
+ _paOEdge = NULL;
+ _pbOEdge = NULL;
+ _nOEdges = 0;
+ userdata = NULL;
+ }
+
+ inline WEdge(WOEdge *iOEdge)
+ {
+ _paOEdge = iOEdge;
+ _pbOEdge = NULL;
+ _nOEdges = 1;
+ userdata = NULL;
+ }
+
+ inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge)
+ {
+ _paOEdge = iaOEdge;
+ _pbOEdge = ibOEdge;
+ _nOEdges = 2;
+ userdata = NULL;
+ }
+
+ /*! Copy constructor */
+ WEdge(WEdge& iBrother);
+ virtual WEdge * duplicate();
+
+ virtual ~WEdge()
+ {
+ if(NULL != _paOEdge)
+ {
+ delete _paOEdge;
+ _paOEdge = NULL;
+ }
+
+ if(NULL != _pbOEdge)
+ {
+ delete _pbOEdge;
+ _pbOEdge = NULL;
+ }
+ }
+
+ /*! checks whether two WEdge have a common vertex.
+ * Returns a pointer on the common vertex if it exists,
+ * NULL otherwise.
+ */
+ static inline WVertex* CommonVertex(WEdge *iEdge1, WEdge* iEdge2)
+ {
+ if((NULL == iEdge1) || (NULL == iEdge2))
+ return NULL;
+
+ WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex();
+ WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex();
+ WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex();
+ WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex();
+
+ if((wv1 == wv3) || (wv1 == wv4))
+ {
+ return wv1;
+ }
+ else if((wv2 == wv3) || (wv2 == wv4))
+ {
+ return wv2;
+ }
+
+ return NULL;
+ }
+ /*! accessors */
+ inline WOEdge * GetaOEdge() {return _paOEdge;}
+ inline WOEdge * GetbOEdge() {return _pbOEdge;}
+ inline int GetNumberOfOEdges() {return _nOEdges;}
+ inline int GetId() {return _Id;}
+ inline WVertex * GetaVertex() {return _paOEdge->GetaVertex();}
+ inline WVertex * GetbVertex() {return _paOEdge->GetbVertex();}
+ inline WFace * GetaFace() {return _paOEdge->GetaFace();}
+ inline WFace * GetbFace() {return _paOEdge->GetbFace();}
+ inline WOEdge* GetOtherOEdge(WOEdge* iOEdge)
+ {
+ if(iOEdge == _paOEdge)
+ return _pbOEdge;
+ else
+ return _paOEdge;
+ }
+
+ /*! modifiers */
+ inline void setaOEdge(WOEdge *iEdge) {_paOEdge = iEdge;}
+ inline void setbOEdge(WOEdge *iEdge) {_pbOEdge = iEdge;}
+ inline void AddOEdge(WOEdge *iEdge)
+ {
+ if(NULL == _paOEdge)
+ {
+ _paOEdge = iEdge;
+ _nOEdges++;
+ return;
+ }
+ if(NULL == _pbOEdge)
+ {
+ _pbOEdge = iEdge;
+ _nOEdges++;
+ return;
+ }
+ }
+ inline void setNumberOfOEdges(int n) {_nOEdges = n;}
+ inline void setId(int id) {_Id = id;}
+ virtual void ResetUserData() {userdata = 0;}
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* WFace */
+ /* */
+ /* */
+ /**********************************/
+
+
+class LIB_WINGED_EDGE_EXPORT WFace
+{
+protected:
+ vector<WOEdge *> _OEdgeList; // list of oriented edges of bording the face
+ Vec3r _Normal; // normal to the face
+ vector<Vec3r> _VerticesNormals; // in case there is a normal per vertex.
+ // The normal number i corresponds to the
+ // aVertex of the oedge number i, for that face
+ vector<Vec2r> _VerticesTexCoords;
+
+ int _Id;
+ unsigned _FrsMaterialIndex;
+
+public:
+ void *userdata;
+ inline WFace() {userdata = NULL;_FrsMaterialIndex = 0;}
+ /*! copy constructor */
+ WFace(WFace& iBrother);
+ virtual WFace * duplicate();
+ virtual ~WFace() {}
+
+ /*! accessors */
+ inline const vector<WOEdge*>& getEdgeList() {return _OEdgeList;}
+ inline WOEdge * GetOEdge(int i) {return _OEdgeList[i];}
+ inline Vec3r& GetNormal() {return _Normal;}
+ inline int GetId() {return _Id;}
+ inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;}
+ const FrsMaterial& frs_material() ;
+
+ /*! The vertex of index i corresponds to the a vertex
+ * of the edge of index i
+ */
+ inline WVertex* GetVertex(unsigned int index)
+ {
+ // if(index >= _OEdgeList.size())
+ // return NULL;
+ return _OEdgeList[index]->GetaVertex();
+ }
+ /*! returns the index at which iVertex is stored in the
+ * array.
+ * returns -1 if iVertex doesn't belong to the face.
+ */
+ inline int GetIndex(WVertex *iVertex){
+ int index = 0;
+ for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++){
+ if((*woe)->GetaVertex() == iVertex)
+ return index;
+ ++index;
+ }
+ return -1;
+ }
+ inline void RetrieveVertexList(vector<WVertex*>& oVertices)
+ {
+ for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ oVertices.push_back((*woe)->GetaVertex());
+ }
+ }
+ inline void RetrieveBorderFaces(vector<const WFace*>& oWFaces)
+ {
+ for(vector<WOEdge*>::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ WFace *af;
+ if(NULL != (af = (*woe)->GetaFace()))
+ oWFaces.push_back(af);
+ }
+ }
+ inline WFace * GetBordingFace(int index)
+ {
+ // if(index >= _OEdgeList.size())
+ // return 0;
+ return _OEdgeList[index]->GetaFace();
+ }
+ inline WFace * GetBordingFace(WOEdge *iOEdge)
+ {
+ return iOEdge->GetaFace();
+ }
+ inline vector<Vec3r>& GetPerVertexNormals()
+ {
+ return _VerticesNormals;
+ }
+ inline vector<Vec2r>& GetPerVertexTexCoords()
+ {
+ return _VerticesTexCoords;
+ }
+ /*! Returns the normal of the vertex of index index */
+ inline Vec3r& GetVertexNormal(int index)
+ {
+ return _VerticesNormals[index];
+ }
+ /*! Returns the tex coords of the vertex of index index */
+ inline Vec2r& GetVertexTexCoords(int index)
+ {
+ return _VerticesTexCoords[index];
+ }
+ /*! Returns the normal of the vertex iVertex for that face */
+ inline Vec3r& GetVertexNormal(WVertex *iVertex)
+ {
+ int i = 0;
+ int index = 0;
+ for(vector<WOEdge*>::const_iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ if((*woe)->GetaVertex() == iVertex)
+ {
+ index = i;
+ break;
+ }
+ ++i;
+ }
+
+ return _VerticesNormals[index];
+ }
+ inline WOEdge* GetNextOEdge(WOEdge* iOEdge)
+ {
+ bool found = false;
+ vector<WOEdge*>::iterator woe,woend, woefirst;
+ woefirst = _OEdgeList.begin();
+ for(woe=woefirst,woend=_OEdgeList.end();
+ woe!=woend;
+ woe++)
+ {
+ if(true == found)
+ return (*woe);
+
+ if((*woe) == iOEdge)
+ {
+ found = true;
+ }
+ }
+
+ // We left the loop. That means that the first
+ // OEdge was the good one:
+ if(found)
+ return (*woefirst);
+
+ return NULL;
+ }
+ WOEdge* GetPrevOEdge(WOEdge* iOEdge);
+
+ inline int numberOfEdges() const { return _OEdgeList.size();}
+ inline int numberOfVertices() const { return _OEdgeList.size();}
+ /*! Returns true if the face has one ot its edge which is a border
+ * edge
+ */
+ inline bool isBorder() const
+ {
+ for(vector<WOEdge*>::const_iterator woe=_OEdgeList.begin(), woeend=_OEdgeList.end();
+ woe!=woeend;
+ ++woe)
+ {
+ if((*woe)->GetOwner()->GetbOEdge() == 0)
+ return true;
+ }
+ return false;
+ }
+ /*! modifiers */
+ inline void setEdgeList(const vector<WOEdge*>& iEdgeList) {_OEdgeList = iEdgeList;}
+ inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;}
+ inline void setNormalList(const vector<Vec3r>& iNormalsList) {_VerticesNormals = iNormalsList;}
+ inline void setTexCoordsList(const vector<Vec2r>& iTexCoordsList) {_VerticesTexCoords = iTexCoordsList;}
+ inline void setId(int id) {_Id = id;}
+ inline void setFrsMaterialIndex(unsigned iMaterialIndex) {_FrsMaterialIndex = iMaterialIndex;}
+
+ /*! designed to build a specialized WEdge
+ * for use in MakeEdge
+ */
+ virtual WEdge * instanciateEdge() const {return new WEdge;}
+
+ /*! Builds an oriented edge
+ * Returns the built edge.
+ * v1, v2
+ * Vertices at the edge's extremities
+ * The edge is oriented from v1 to v2.
+ */
+ virtual WOEdge * MakeEdge(WVertex *v1, WVertex *v2);
+
+ /*! Adds an edge to the edges list */
+ inline void AddEdge(WOEdge *iEdge) {_OEdgeList.push_back(iEdge);}
+
+ /*! For triangles, returns the edge opposite to the vertex in e.
+ returns flase if the face is not a triangle or if the vertex is not found*/
+ bool getOppositeEdge (const WVertex *v, WOEdge* &e);
+
+ /*! compute the area of the face */
+ real getArea ();
+
+ WShape * getShape() ;
+ virtual void ResetUserData() {userdata = 0;}
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+class LIB_WINGED_EDGE_EXPORT WShape
+{
+protected:
+ vector<WVertex*> _VertexList;
+ vector<WEdge*> _EdgeList;
+ vector<WFace*> _FaceList;
+ int _Id;
+ static unsigned _SceneCurrentId;
+ Vec3r _min;
+ Vec3r _max;
+ vector<FrsMaterial> _FrsMaterials;
+ real _meanEdgeSize;
+
+public:
+ inline WShape() {_meanEdgeSize = 0;_Id = _SceneCurrentId; _SceneCurrentId++;}
+ /*! copy constructor */
+ WShape(WShape& iBrother);
+ virtual WShape * duplicate();
+ virtual ~WShape()
+ {
+ if(_EdgeList.size() != 0)
+ {
+ vector<WEdge *>::iterator e;
+ for(e=_EdgeList.begin(); e!=_EdgeList.end(); e++)
+ {
+ delete (*e);
+ }
+ _EdgeList.clear();
+ }
+
+ if(_VertexList.size() != 0)
+ {
+ vector<WVertex *>::iterator v;
+ for(v=_VertexList.begin(); v!=_VertexList.end(); v++)
+ {
+ delete (*v);
+ }
+ _VertexList.clear();
+ }
+
+ if(_FaceList.size() != 0)
+ {
+ vector<WFace *>::iterator f;
+ for(f=_FaceList.begin(); f!=_FaceList.end(); f++)
+ {
+ delete (*f);
+ }
+ _FaceList.clear();
+ }
+ }
+
+ /*! accessors */
+ inline vector<WEdge *>& getEdgeList() {return _EdgeList;}
+ inline vector<WVertex*>& getVertexList() {return _VertexList;}
+ inline vector<WFace*>& GetFaceList() {return _FaceList;}
+ inline unsigned GetId() {return _Id;}
+ inline void bbox(Vec3r& min, Vec3r& max) {min=_min; max=_max;}
+ inline const FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];}
+ inline const vector<FrsMaterial>& frs_materials() const {return _FrsMaterials;}
+ inline const real getMeanEdgeSize() const {return _meanEdgeSize;}
+ /*! modifiers */
+ static inline void setCurrentId(const unsigned id) { _SceneCurrentId = id; }
+ inline void setEdgeList(const vector<WEdge*>& iEdgeList) {_EdgeList = iEdgeList;}
+ inline void setVertexList(const vector<WVertex*>& iVertexList) {_VertexList = iVertexList;}
+ inline void setFaceList(const vector<WFace*>& iFaceList) {_FaceList = iFaceList;}
+ inline void setId(int id) {_Id = id;}
+ inline void setBBox(const Vec3r& min, const Vec3r& max) {_min = min; _max=max;}
+ inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i) {_FrsMaterials[i]=frs_material;}
+ inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) {_FrsMaterials = iMaterials;}
+
+ /*! designed to build a specialized WFace
+ * for use in MakeFace
+ */
+ virtual WFace * instanciateFace() const {return new WFace;}
+
+ /*! adds a new face to the shape
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The material index for this face
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex);
+
+ /*! adds a new face to the shape. The difference with
+ * the previous method is that this one is designed
+ * to build a WingedEdge structure for which there are
+ * per vertex normals, opposed to per face normals.
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The materialIndex for this face
+ * iNormalsList
+ * The list of normals, iNormalsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ * iTexCoordsList
+ * The list of tex coords, iTexCoordsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex);
+
+ inline void AddEdge(WEdge *iEdge) {_EdgeList.push_back(iEdge);}
+ inline void AddFace(WFace* iFace) {_FaceList.push_back(iFace);}
+ inline void AddVertex(WVertex *iVertex) {iVertex->setShape(this); _VertexList.push_back(iVertex);}
+
+ inline void ResetUserData()
+ {
+ for(vector<WVertex*>::iterator v=_VertexList.begin(),vend=_VertexList.end();
+ v!=vend;
+ v++)
+ {
+ (*v)->ResetUserData();
+ }
+
+ for(vector<WEdge*>::iterator e=_EdgeList.begin(),eend=_EdgeList.end();
+ e!=eend;
+ e++)
+ {
+ (*e)->ResetUserData();
+ // manages WOEdge:
+ WOEdge *oe = (*e)->GetaOEdge();
+ if(oe != NULL)
+ oe->ResetUserData();
+ oe = (*e)->GetbOEdge();
+ if(oe != NULL)
+ oe->ResetUserData();
+ }
+
+ for(vector<WFace*>::iterator f=_FaceList.begin(),fend=_FaceList.end();
+ f!=fend;
+ f++)
+ {
+ (*f)->ResetUserData();
+ }
+
+ }
+
+ inline void ComputeBBox()
+ {
+ _min = _VertexList[0]->GetVertex();
+ _max = _VertexList[0]->GetVertex();
+
+ Vec3r v;
+ for(vector<WVertex*>::iterator wv=_VertexList.begin(), wvend=_VertexList.end();
+ wv!=wvend;
+ wv++)
+ {
+ for(unsigned int i=0; i<3; i++)
+ {
+ v = (*wv)->GetVertex();
+ if(v[i] < _min[i])
+ _min[i] = v[i];
+ if(v[i] > _max[i])
+ _max[i] = v[i];
+ }
+ }
+ }
+
+ inline real ComputeMeanEdgeSize(){
+ _meanEdgeSize = _meanEdgeSize/(_EdgeList.size());
+ return _meanEdgeSize;
+ }
+
+protected:
+ /*! Builds the face passed as argument (which as already been allocated)
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iMaterialIndex
+ * The material index for this face
+ * face
+ * The Face that is filled in
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex, WFace *face);
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WingedEdge */
+ /* */
+ /* */
+ /**********************************/
+
+class WingedEdge {
+
+ public:
+
+ WingedEdge() {}
+
+ ~WingedEdge() {
+ clear();
+ }
+
+ void clear() {
+ for (vector<WShape*>::iterator it = _wshapes.begin();
+ it != _wshapes.end();
+ it++)
+ delete *it;
+ _wshapes.clear();
+ }
+
+ void addWShape(WShape* wshape) {
+ _wshapes.push_back(wshape);
+ }
+
+ vector<WShape*>& getWShapes() {
+ return _wshapes;
+ }
+
+ private:
+
+ vector<WShape*> _wshapes;
+};
+
+
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+/* for inline functions */
+void WOEdge::RetrieveCWOrderedEdges(vector<WEdge*>& oEdges)
+{
+
+ WOEdge *currentOEdge = this;
+ do
+ {
+ WOEdge* nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge);
+ oEdges.push_back(nextOEdge->GetOwner());
+ currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge);
+
+ } while((currentOEdge != NULL) && (currentOEdge->GetOwner() != GetOwner()));
+}
+
+#endif // WEDGE_H
diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp
new file mode 100755
index 00000000000..7d0a2d3c561
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp
@@ -0,0 +1,60 @@
+
+//
+// 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 "WEdge.h"
+#include "WFillGrid.h"
+
+void WFillGrid::fillGrid() {
+ if (!_winged_edge || !_grid)
+ return;
+
+ vector<WShape*> wshapes = _winged_edge->getWShapes();
+ vector<WVertex*> fvertices;
+ vector<Vec3r> vectors;
+ vector<WFace*> faces;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++) {
+ faces = (*it)->GetFaceList();
+
+ for (vector<WFace*>::const_iterator f = faces.begin();
+ f != faces.end();
+ f++) {
+ (*f)->RetrieveVertexList(fvertices);
+
+ for (vector<WVertex*>::const_iterator wv = fvertices.begin();
+ wv != fvertices.end();
+ wv++)
+ vectors.push_back(Vec3r((*wv)->GetVertex()));
+
+ // occluder will be deleted by the grid
+ Polygon3r *occluder =
+ new Polygon3r(vectors, (*f)->GetNormal());
+ occluder->setId(_polygon_id++);
+ occluder->userdata = (void*)(*f);
+ _grid->insertOccluder(occluder);
+ vectors.clear();
+ fvertices.clear();
+ }
+ faces.clear();
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.h b/source/blender/freestyle/intern/winged_edge/WFillGrid.h
new file mode 100755
index 00000000000..2ebbc2f359a
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.h
@@ -0,0 +1,80 @@
+//
+// Filename : WFillGrid.h
+// Author(s) : Stephane Grabli
+// Emmanuel Turquin
+// Purpose : Class to fill in a grid from a SceneGraph
+// (uses only the WingedEdge structures)
+// Date of creation : 03/05/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 W_FILL_GRID_H
+# define W_FILL_GRID_H
+
+# include "../geometry/Grid.h"
+# include "../geometry/Polygon.h"
+# include "WEdge.h"
+
+class LIB_WINGED_EDGE_EXPORT WFillGrid
+{
+public:
+
+ inline WFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) {
+ _winged_edge = winged_edge;
+ _grid = grid;
+ _polygon_id = 0;
+ }
+
+ virtual ~WFillGrid() {}
+
+ void fillGrid();
+
+ /*! Accessors */
+ WingedEdge* getWingedEdge() {
+ return _winged_edge;
+ }
+
+ Grid* getGrid() {
+ return _grid;
+ }
+
+ /*! Modifiers */
+ void setWingedEdge(WingedEdge* winged_edge) {
+ if (winged_edge)
+ _winged_edge = winged_edge;
+ }
+
+ void setGrid(Grid* grid) {
+ if (grid)
+ _grid = grid;
+ }
+
+private:
+
+ Grid* _grid;
+ WingedEdge* _winged_edge;
+ unsigned _polygon_id;
+};
+
+#endif // WS_FILL_GRID_H
diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp
new file mode 100755
index 00000000000..55fa418d4f5
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp
@@ -0,0 +1,60 @@
+
+//
+// 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 "WEdge.h"
+#include "WSFillGrid.h"
+
+void WSFillGrid::fillGrid() {
+ if (!_winged_edge || !_grid)
+ return;
+
+ vector<WShape*> wshapes = _winged_edge->getWShapes();
+ vector<WVertex*> fvertices;
+ vector<Vec3r> vectors;
+ vector<WFace*> faces;
+
+ for (vector<WShape*>::const_iterator it = wshapes.begin();
+ it != wshapes.end();
+ it++) {
+ faces = (*it)->GetFaceList();
+
+ for (vector<WFace*>::const_iterator f = faces.begin();
+ f != faces.end();
+ f++) {
+ (*f)->RetrieveVertexList(fvertices);
+
+ for (vector<WVertex*>::const_iterator wv = fvertices.begin();
+ wv != fvertices.end();
+ wv++)
+ vectors.push_back(Vec3r((*wv)->GetVertex()));
+
+ // occluder will be deleted by the grid
+ Polygon3r *occluder =
+ new Polygon3r(vectors, (*f)->GetNormal());
+ occluder->setId(_polygon_id++);
+ occluder->userdata = (void*)(*f);
+ _grid->insertOccluder(occluder);
+ vectors.clear();
+ fvertices.clear();
+ }
+ faces.clear();
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.h b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h
new file mode 100755
index 00000000000..2ea5bc6c621
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h
@@ -0,0 +1,79 @@
+//
+// Filename : WSFillGrid.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to fill in a grid from a SceneGraph
+// (uses only the WingedEdge structures)
+// Date of creation : 03/05/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 WS_FILL_GRID_H
+# define WS_FILL_GRID_H
+
+# include "../geometry/Grid.h"
+# include "../geometry/Polygon.h"
+# include "WEdge.h"
+
+class LIB_WINGED_EDGE_EXPORT WSFillGrid
+{
+public:
+
+ inline WSFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) {
+ _winged_edge = winged_edge;
+ _grid = grid;
+ _polygon_id = 0;
+ }
+
+ virtual ~WSFillGrid() {}
+
+ void fillGrid();
+
+ /*! Accessors */
+ WingedEdge* getWingedEdge() {
+ return _winged_edge;
+ }
+
+ Grid* getGrid() {
+ return _grid;
+ }
+
+ /*! Modifiers */
+ void setWingedEdge(WingedEdge* winged_edge) {
+ if (winged_edge)
+ _winged_edge = winged_edge;
+ }
+
+ void setGrid(Grid* grid) {
+ if (grid)
+ _grid = grid;
+ }
+
+private:
+
+ Grid* _grid;
+ WingedEdge* _winged_edge;
+ unsigned _polygon_id;
+};
+
+#endif // WS_FILL_GRID_H
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
new file mode 100755
index 00000000000..ff567aee06a
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp
@@ -0,0 +1,296 @@
+//
+// 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 "WXEdge.h"
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXFace */
+ /* */
+ /* */
+ /**********************************/
+
+unsigned int WXFaceLayer::Get0VertexIndex() const {
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for(i=0; i<nEdges; ++i){
+ if(_DotP[i] == 0){
+ return i;
+ }
+ }
+ return -1;
+}
+unsigned int WXFaceLayer::GetSmoothEdgeIndex() const{
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for(i=0; i<nEdges; ++i){
+ if((_DotP[i] == 0) && (_DotP[(i+1)%nEdges] == 0)){
+ return i;
+ }
+ }
+ return -1;
+}
+
+void WXFaceLayer::RetrieveCuspEdgesIndices(vector<int>& oCuspEdges){
+ int i = 0;
+ int nEdges = _pWXFace->numberOfEdges();
+ for(i=0; i<nEdges; ++i){
+ if(_DotP[i]*_DotP[(i+1)%nEdges] < 0){
+ // we got one
+ oCuspEdges.push_back(i);
+ }
+ }
+}
+
+WXSmoothEdge* WXFaceLayer::BuildSmoothEdge(){
+ // if the smooth edge has already been
+ // built: exit
+ if(0 != _pSmoothEdge)
+ return _pSmoothEdge;
+ real ta, tb;
+ WOEdge *woea(0), *woeb(0);
+ bool ok = false;
+ vector<int> cuspEdgesIndices;
+ int indexStart, indexEnd;
+ unsigned nedges = _pWXFace->numberOfEdges();
+ if(_nNullDotP == nedges){
+ _pSmoothEdge = 0;
+ return _pSmoothEdge;
+ }
+ if((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)){
+ // that means that we have a smooth edge that starts from
+ // an edge and ends at an edge
+ //-----------------------------
+ // We retrieve the 2 edges for which we have
+ // opposite signs for each extremity
+ RetrieveCuspEdgesIndices(cuspEdgesIndices);
+ if(cuspEdgesIndices.size() != 2) // we necessarly have 2 cusp edges
+ return 0;
+
+ // let us determine which cusp edge corresponds to the starting:
+ // We can do that because we defined that
+ // a silhouette edge had the back facing part on its right.
+ // So if the WOEdge woea is such that woea[0].dotp > 0 and
+ // woea[1].dotp < 0, it is the starting edge.
+ //-------------------------------------------
+
+ if(_DotP[cuspEdgesIndices[0]] > 0){
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
+ indexStart = cuspEdgesIndices[0];
+ indexEnd = cuspEdgesIndices[1];
+ }else{
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ indexStart = cuspEdgesIndices[1];
+ indexEnd = cuspEdgesIndices[0];
+ }
+
+ // Compute the interpolation:
+ ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]);
+ tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]);
+ ok = true;
+ }else if(_nNullDotP == 1){
+ // that means that we have exactly one of the
+ // 2 extremities of our silhouette edge is
+ // a vertex of the mesh
+ if((_nPosDotP == 2) || (_nPosDotP == 0)){
+ _pSmoothEdge = 0;
+ return _pSmoothEdge;
+ }
+ RetrieveCuspEdgesIndices(cuspEdgesIndices);
+ // We should have only one EdgeCusp:
+ if(cuspEdgesIndices.size() != 1){
+ cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl;
+ _pSmoothEdge = 0;
+ return 0;
+ }
+ unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index
+ unsigned nedges = _pWXFace->numberOfEdges();
+ if(_DotP[cuspEdgesIndices[0]] > 0){
+ woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ woeb = _pWXFace->GetOEdge(index0);
+ indexStart = cuspEdgesIndices[0];
+ ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]);
+ tb = 0.0;
+ }else{
+ woea = _pWXFace->GetOEdge(index0);
+ woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
+ indexEnd = cuspEdgesIndices[0];
+ ta = 0.0;
+ tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]);
+ }
+ ok = true;
+ }else if(_nNullDotP == 2){
+ // that means that the silhouette edge
+ // is an edge of the mesh
+ int index = GetSmoothEdgeIndex();
+ if(!_pWXFace->front()) {// is it in the right order ?
+ // the order of the WOEdge index is wrong
+ woea = _pWXFace->GetOEdge((index+1)%nedges);
+ woeb = _pWXFace->GetOEdge((index-1)%nedges);
+ ta = 0;
+ tb = 1;
+ ok = true;
+ }else{
+ // here it's not good, our edge is a single point -> skip that face
+ ok = false;
+ // the order of the WOEdge index is good
+ // woea = _pWXFace->GetOEdge((index-1)%nedges);
+ // woeb = _pWXFace->GetOEdge((index+1)%nedges);
+ // ta = 1;
+ // tb = 0;
+ }
+ }
+ if(ok){
+ _pSmoothEdge = new WXSmoothEdge;
+ _pSmoothEdge->setWOeA(woea);
+ _pSmoothEdge->setWOeB(woeb);
+ _pSmoothEdge->setTa(ta);
+ _pSmoothEdge->setTb(tb);
+ if(_Nature & Nature::SILHOUETTE){
+ if(_nNullDotP != 2){
+ if(_DotP[_ClosestPointIndex] + 0.01 > 0)
+ _pSmoothEdge->setFront(true);
+ else
+ _pSmoothEdge->setFront(false);
+ }
+ }
+ }
+
+ // check bording edges to see if they have different dotp values
+ // in bording faces.
+ // for(int i=0; i<numberOfEdges(); i++)
+ // {
+ // WSFace * bface = (WSFace*)GetBordingFace(i);
+ // if(bface != 0)
+ // {
+ // if((front())^(bface->front())) // fA->front XOR fB->front (true if one is 0 and the other is 1)
+ // {
+ // // that means that the edge i of the face is
+ // // a silhouette edge
+ // // TESTER D'ABORD SI LE EXACTSILHOUETTEEDGE N'A PAS
+ // // ETE CONSTRUIT SUR L'AUTRE FACE.(1 suffit)
+ // if(0 != ((WSExactFace*)bface)->exactSilhouetteEdge())
+ // {
+ // // that means that this silhouette edge has already been built
+ // return ((WSExactFace*)bface)->exactSilhouetteEdge();
+ // }
+ // // Else we must build it
+ // WOEdge *woea, *woeb;
+ // real ta, tb;
+ // if(!front()) // is it in the right order ?
+ // {
+ // // the order of the WOEdge index is wrong
+ // woea = _OEdgeList[(i+1)%numberOfEdges()];
+ // if(0 == i)
+ // woeb = _OEdgeList[numberOfEdges()-1];
+ // else
+ // woeb = _OEdgeList[(i-1)];
+ // ta = 0;
+ // tb = 1;
+ // }
+ // else
+ // {
+ // // the order of the WOEdge index is good
+ // if(0 == i)
+ // woea = _OEdgeList[numberOfEdges()-1];
+ // else
+ // woea = _OEdgeList[(i-1)];
+ // woeb = _OEdgeList[(i+1)%numberOfEdges()];
+ // ta = 1;
+ // tb = 0;
+ // }
+ //
+ // _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX);
+ // _pSmoothEdge->setWOeA(woea);
+ // _pSmoothEdge->setWOeA(woeb);
+ // _pSmoothEdge->setTa(ta);
+ // _pSmoothEdge->setTb(tb);
+ //
+ // return _pSmoothEdge;
+ // }
+ // }
+ //}
+ return _pSmoothEdge;
+}
+
+
+void WXFace::ComputeCenter()
+{
+ vector<WVertex*> iVertexList;
+ RetrieveVertexList(iVertexList);
+ Vec3r center;
+ for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end();
+ wv!=wvend;
+ wv++)
+ {
+ center += (*wv)->GetVertex();
+ }
+ center /= (real)iVertexList.size();
+ setCenter(center);
+}
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+WFace* WXShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex)
+{
+ WFace *face = WShape::MakeFace(iVertexList, iMaterialIndex);
+ if(0 == face)
+ return 0;
+
+ Vec3r center;
+ for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end();
+ wv!=wvend;
+ wv++)
+ {
+ center += (*wv)->GetVertex();
+ }
+ center /= (real)iVertexList.size();
+ ((WXFace*)face)->setCenter(center);
+
+ return face;
+}
+
+WFace * WXShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex)
+{
+ WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iMaterialIndex);
+
+ // Vec3r center;
+ // for(vector<WVertex*>::iterator wv=iVertexList.begin(),wvend=iVertexList.end();
+ // wv!=wvend;
+ // wv++)
+ // {
+ // center += (*wv)->GetVertex();
+ // }
+ // center /= (real)iVertexList.size();
+ // ((WSFace*)face)->setCenter(center);
+
+ return face;
+}
+
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h
new file mode 100755
index 00000000000..9ec8fd4bddb
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h
@@ -0,0 +1,582 @@
+//
+// Filename : WXEdge.h
+// Author(s) : Stephane Grabli
+// Purpose : Classes to define an Extended Winged Edge data 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 WXEDGE_H
+# define WXEDGE_H
+
+# include "WEdge.h"
+# include "Nature.h"
+# include "Curvature.h"
+
+typedef Nature::EdgeNature WXNature;
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXVertex */
+ /* */
+ /* */
+ /**********************************/
+
+class WXVertex : public WVertex
+{
+private:
+ // Curvature info
+ CurvatureInfo *_curvatures;
+
+public:
+ inline WXVertex(const Vec3r &v)
+ : WVertex(v)
+ {_curvatures = 0;}
+ /*! Copy constructor */
+ WXVertex(WXVertex& iBrother)
+ : WVertex(iBrother)
+ {_curvatures = new CurvatureInfo(*iBrother._curvatures);}
+ virtual WVertex * duplicate()
+ {
+ WXVertex *clone = new WXVertex(*this);
+ return clone;
+ }
+ virtual ~WXVertex() {if(_curvatures) delete _curvatures;}
+ virtual void Reset() {if(_curvatures) _curvatures->Kr = 0.0;}
+ inline void setCurvatures(CurvatureInfo *ci) {_curvatures = ci;}
+
+ inline bool isFeature();
+ inline CurvatureInfo* curvatures() {return _curvatures;}
+
+};
+
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXEdge */
+ /* */
+ /* */
+ /**********************************/
+class WXEdge : public WEdge
+{
+private:
+ WXNature _nature; // flag to indicate whether the edge is a silhouette edge or not
+ int _order; // 0: the order doesn't matter. 1: the order is the orginal one. -1: the order is not good
+ bool _front; // a front facing edge is an edge for which the bording face which is the nearest
+ // from the viewpoint is front. A back facing edge is the opposite.
+
+public:
+ inline WXEdge()
+ : WEdge(){
+ _nature = Nature::NO_FEATURE;
+ _front = false;
+ _order=0;
+ }
+
+ inline WXEdge(WOEdge *iOEdge)
+ : WEdge(iOEdge)
+ { _nature = Nature::NO_FEATURE;_front = false;_order=0;}
+
+ inline WXEdge(WOEdge *iaOEdge, WOEdge *ibOEdge)
+ : WEdge(iaOEdge, ibOEdge)
+ { _nature = Nature::NO_FEATURE;_front = false;_order=0;}
+
+ /*! Copy constructor */
+ inline WXEdge(WXEdge& iBrother)
+ : WEdge(iBrother)
+ {_nature = iBrother.nature();_front = iBrother._front;_order = iBrother._order;}
+ virtual WEdge * duplicate()
+ {
+ WXEdge *clone = new WXEdge(*this);
+ return clone;
+ }
+
+ virtual ~WXEdge()
+ {}
+
+ virtual void Reset(){
+ _nature = _nature & ~Nature::SILHOUETTE;
+ _nature = _nature & ~Nature::SUGGESTIVE_CONTOUR;
+ }
+
+ /*! accessors */
+ inline WXNature nature() {return _nature;}
+ inline bool front() {return _front;}
+ inline int order() const {return _order;}
+
+ /*! modifiers */
+ inline void setFront(bool iFront) {_front = iFront;}
+ inline void setNature(WXNature iNature) {_nature = iNature;}
+ inline void AddNature(WXNature iNature) {_nature = _nature|iNature;}
+ inline void setOrder(int i) {_order = i;}
+
+};
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXFace */
+ /* */
+ /* */
+ /**********************************/
+
+/*! Class to store a smooth edge (i.e Hertzman & Zorin smooth silhouette edges) */
+class WXSmoothEdge{
+public:
+ typedef enum{
+ EDGE_EDGE,
+ VERTEX_EDGE,
+ EDGE_VERTEX
+ } Configuration;
+
+ WOEdge *_woea; // Oriented edge from which the silhouette edge starts
+ WOEdge *_woeb; // Oriented edge where the silhouette edge ends
+ real _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0])
+ real _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0])
+ bool _front;
+ Configuration _config;
+
+ WXSmoothEdge(){
+ _woea = 0;
+ _woeb = 0;
+ _ta = 0;
+ _tb = 0;
+ _front = false;
+ _config = EDGE_EDGE;
+ }
+ WXSmoothEdge(const WXSmoothEdge& iBrother){
+ _woea = iBrother._woea;
+ _woeb = iBrother._woeb;
+ _ta = iBrother._ta;
+ _tb = iBrother._tb;
+ _config = iBrother._config;
+ _front = iBrother._front;
+ }
+ ~WXSmoothEdge() {}
+
+ inline WOEdge * woea() {return _woea;}
+ inline WOEdge * woeb() {return _woeb;}
+ inline real ta() const {return _ta;}
+ inline real tb() const {return _tb;}
+ inline bool front() const {return _front;}
+ inline Configuration configuration() const {return _config;}
+
+ /*! modifiers */
+ inline void setWOeA(WOEdge *iwoea) {_woea = iwoea;}
+ inline void setWOeB(WOEdge *iwoeb) {_woeb = iwoeb;}
+ inline void setTa(real ta) {_ta = ta;}
+ inline void setTb(real tb) {_tb = tb;}
+ inline void setFront(bool iFront) {_front = iFront;}
+ inline void setConfiguration(Configuration iConf) {_config = iConf;}
+
+};
+/* Class to store a value per vertex and a smooth edge.
+ * The WXFace stores a list of these
+ */
+class WXFace;
+class LIB_WINGED_EDGE_EXPORT WXFaceLayer{
+public:
+ void * userdata;
+ WXFace * _pWXFace;
+ vector<real> _DotP;// in case of silhouette: the values obtained when computing the normal-view direction
+ // dot product. _DotP[i] is this value for the vertex i for that
+ // face.
+ WXSmoothEdge * _pSmoothEdge;
+ WXNature _Nature;
+
+ //oldtmp values
+ unsigned _nPosDotP; // count the number of positive dot products for vertices.
+ // if this number is != 0 and !=_DotP.size() -> it is a silhouette fac
+
+ unsigned _nNullDotP; // count the number of null dot products for vertices.
+ unsigned _ClosestPointIndex;
+ bool _viewDependant;
+
+ WXFaceLayer(WXFace *iFace, WXNature iNature, bool viewDependant){
+ _pWXFace = iFace;
+ _pSmoothEdge = 0;
+ _nPosDotP = 0;
+ _nNullDotP=0;
+ _Nature = iNature;
+ _viewDependant = viewDependant;
+ userdata = 0;
+ }
+ WXFaceLayer(const WXFaceLayer& iBrother){
+ _pWXFace = iBrother._pWXFace;
+ _pSmoothEdge = 0;
+ _DotP = iBrother._DotP;
+ _nPosDotP = iBrother._nPosDotP;
+ _nNullDotP = iBrother._nNullDotP;
+ _Nature = iBrother._Nature;
+ if(0 != iBrother._pSmoothEdge)
+ {
+ _pSmoothEdge = new WXSmoothEdge(*(iBrother._pSmoothEdge));
+ }
+ _viewDependant = iBrother._viewDependant;
+ userdata = 0;
+ }
+ virtual ~WXFaceLayer() {
+ if(!_DotP.empty())
+ _DotP.clear();
+ if(0 != _pSmoothEdge){
+ delete _pSmoothEdge;
+ _pSmoothEdge = 0;
+ }
+ }
+ inline const real dotP(int i) const {return _DotP[i];}
+ inline unsigned nPosDotP() const {return _nPosDotP;}
+ inline unsigned nNullDotP() const {return _nNullDotP;}
+ inline int closestPointIndex() const {return _ClosestPointIndex;}
+ inline Nature::EdgeNature nature() const {return _Nature;}
+ inline bool hasSmoothEdge() const {if(_pSmoothEdge) return true; return false;}
+ inline WXFace * getFace() {return _pWXFace;}
+ inline WXSmoothEdge * getSmoothEdge() {return _pSmoothEdge;}
+ inline bool isViewDependant() const {return _viewDependant;}
+ inline void setClosestPointIndex(int iIndex) {_ClosestPointIndex = iIndex;}
+
+ inline void removeSmoothEdge() {
+ if(!_DotP.empty())
+ _DotP.clear();
+ if (_pSmoothEdge) {
+ delete _pSmoothEdge;
+ _pSmoothEdge = 0;
+ }
+ }
+
+ /*! If one of the face layer vertex has a DotP equal
+ * to 0, this method returns the vertex where it happens
+ */
+ unsigned int Get0VertexIndex() const ;
+
+ /*! In case one of the edge of the triangle
+ * is a smooth edge, this method
+ * allows to retrieve the concerned edge
+ */
+ unsigned int GetSmoothEdgeIndex() const;
+ /*! retrieves the edges of the triangle for which
+ * the signs are different (a null value is not considered) for the dotp
+ * values at each edge extrimity
+ */
+ void RetrieveCuspEdgesIndices(vector<int>& oCuspEdges);
+ WXSmoothEdge * BuildSmoothEdge();
+ inline void setDotP(const vector<real>& iDotP) {_DotP = iDotP;}
+ inline void PushDotP(real iDotP) {
+ _DotP.push_back(iDotP);
+ if(iDotP > 0)
+ ++_nPosDotP;
+ if(iDotP == 0)
+ ++_nNullDotP;
+ }
+ inline void ReplaceDotP(unsigned int index, real newDotP){
+ _DotP[index] = newDotP;
+ updateDotPInfos();
+ }
+ inline void updateDotPInfos() {
+ for(vector<real>::iterator d=_DotP.begin(), dend=_DotP.end();
+ d!=dend;
+ ++d){
+ _nPosDotP = 0;
+ _nNullDotP = 0;
+ if((*d) > 0)
+ ++_nPosDotP;
+ if((*d) == 0)
+ ++_nNullDotP;
+ }
+ }
+};
+
+
+class WXFace : public WFace
+{
+protected:
+ Vec3r _center; // center of the face
+ real _Z; // distance from viewpoint to the center of the face
+ bool _front; // flag to tell whether the face is front facing or back facing
+ real _dotp; // value obtained when computing the normal-viewpoint dot product
+
+ vector<WXFaceLayer*> _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face
+public:
+ inline WXFace() : WFace() {_Z=0.0;_front = false;}
+ /*! Copy constructor */
+ WXFace(WXFace& iBrother)
+ : WFace(iBrother)
+ {
+ _center = iBrother.center();
+ _Z = iBrother.Z();
+ _front = iBrother.front();
+ for(vector<WXFaceLayer*>::iterator wxf = iBrother._SmoothLayers.begin(), wxfend = iBrother._SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ _SmoothLayers.push_back(new WXFaceLayer(**wxf));
+ }
+ }
+ virtual WFace * duplicate()
+ {
+ WXFace * clone = new WXFace(*this);
+ return clone;
+ }
+
+ virtual ~WXFace() {
+ if(!_SmoothLayers.empty()){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ delete (*wxf);
+ }
+ _SmoothLayers.clear();
+ }
+ }
+
+ /*! designed to build a specialized WEdge
+ * for use in MakeEdge
+ */
+ virtual WEdge * instanciateEdge() const {return new WXEdge;}
+
+ /*! accessors */
+ inline Vec3r& center() {return _center;}
+ inline real Z() {return _Z;}
+ inline bool front() {return _front;}
+ inline real dotp() {return _dotp;}
+ inline bool hasSmoothEdges() const {
+ for(vector<WXFaceLayer*>::const_iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if( ((*wxf)->hasSmoothEdge())){
+ return true;
+ }
+ }
+ return false;
+ }
+ vector<WXFaceLayer*>& getSmoothLayers() {return _SmoothLayers;}
+ /*! retrieve the smooth edges that match the Nature given as argument */
+ void retrieveSmoothEdges(WXNature iNature, vector<WXSmoothEdge*>& oSmoothEdges){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){
+ oSmoothEdges.push_back((*wxf)->_pSmoothEdge);
+ }
+ }
+ }
+ void retrieveSmoothEdgesLayers(WXNature iNature, vector<WXFaceLayer*>& oSmoothEdgesLayers){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){
+ oSmoothEdgesLayers.push_back((*wxf));
+ }
+ }
+ }
+ void retrieveSmoothLayers(WXNature iNature, vector<WXFaceLayer*>& oSmoothLayers){
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if((*wxf)->_Nature & iNature){
+ oSmoothLayers.push_back(*wxf);
+ }
+ }
+ }
+ /*! modifiers */
+ inline void setCenter(const Vec3r& iCenter) {_center = iCenter;}
+ void ComputeCenter();
+ inline void setZ(real z) {_Z = z;}
+ inline void setFront(bool iFront) {_front = iFront;}
+ inline void setDotP(real iDotP)
+ {
+ _dotp = iDotP;
+ if(_dotp > 0)
+ _front = true;
+ else
+ _front = false;
+ }
+ inline void AddSmoothLayer(WXFaceLayer * iLayer){
+ _SmoothLayers.push_back(iLayer);
+ }
+ inline void Reset() {
+ vector<WXFaceLayer*> layersToKeep;
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ if((*wxf)->isViewDependant())
+ delete (*wxf);
+ else
+ layersToKeep.push_back(*wxf);
+ }
+ _SmoothLayers = layersToKeep;
+ }
+ /*! Clears everything */
+ inline void Clear() {
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ delete (*wxf);
+ }
+ _SmoothLayers.clear();
+ }
+ virtual void ResetUserData() {
+ WFace::ResetUserData();
+ for(vector<WXFaceLayer*>::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end();
+ wxf != wxfend;
+ ++wxf){
+ (*wxf)->userdata = 0;
+ }
+ }
+};
+
+
+ /**********************************/
+ /* */
+ /* */
+ /* WXShape */
+ /* */
+ /* */
+ /**********************************/
+
+
+class WXShape : public WShape
+{
+public:
+ typedef WXShape type_name;
+protected:
+ bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not
+public:
+ inline WXShape() : WShape() {_computeViewIndependant = true;}
+ /*! copy constructor */
+ inline WXShape(WXShape& iBrother)
+ :WShape(iBrother)
+ {
+ _computeViewIndependant = iBrother._computeViewIndependant;
+ }
+ virtual WShape * duplicate()
+ {
+ WXShape *clone = new WXShape(*this);
+ return clone;
+ }
+
+ virtual ~WXShape()
+ {
+ }
+
+ inline bool getComputeViewIndependantFlag() const {return _computeViewIndependant;}
+ inline void setComputeViewIndependantFlag(bool iFlag) {_computeViewIndependant = iFlag;}
+
+ /*! designed to build a specialized WFace
+ * for use in MakeFace
+ */
+ virtual WFace * instanciateFace() const {return new WXFace;}
+
+ /*! adds a new face to the shape
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterialIndex);
+
+ /*! adds a new face to the shape. The difference with
+ * the previous method is that this one is designed
+ * to build a WingedEdge structure for which there are
+ * per vertex normals, opposed to per face normals.
+ * returns the built face.
+ * iVertexList
+ * List of face's vertices. These vertices are
+ * not added to the WShape vertex list; they are
+ * supposed to be already stored when calling MakeFace.
+ * The order in which the vertices are stored in the list
+ * determines the face's edges orientation and (so) the
+ * face orientation.
+ * iNormalsList
+ * The list of normals, iNormalsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ * iTexCoordsList
+ * The list of tex coords, iTexCoordsList[i] corresponding to the
+ * normal of the vertex iVertexList[i] for that face.
+ */
+ virtual WFace * MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterialIndex);
+
+ /*! Reset all edges and vertices flags (which might
+ * have been set up on a previous pass)
+ */
+ virtual void Reset(){
+ // Reset Edges
+ vector<WEdge*>& wedges = getEdgeList();
+ for(vector<WEdge*>::iterator we=wedges.begin(),weend=wedges.end();
+ we!=weend;
+ we++){
+ ((WXEdge*)(*we))->Reset();
+ }
+
+ //Reset faces:
+ vector<WFace*>& wfaces = GetFaceList();
+ for(vector<WFace*>::iterator wf=wfaces.begin(),wfend=wfaces.end();
+ wf!=wfend;
+ wf++){
+ ((WXFace*)(*wf))->Reset();
+ }
+ }
+ /*! accessors */
+};
+
+/*
+
+ #############################################
+ #############################################
+ #############################################
+ ###### ######
+ ###### I M P L E M E N T A T I O N ######
+ ###### ######
+ #############################################
+ #############################################
+ #############################################
+
+*/
+/* for inline functions */
+
+bool WXVertex::isFeature()
+{
+ int counter = 0;
+ vector<WEdge*>& vedges = GetEdges();
+ for(vector<WEdge*>::iterator ve=vedges.begin(), vend=vedges.end();
+ ve!=vend;
+ ve++)
+ {
+ if(((WXEdge*)(*ve))->nature() != Nature::NO_FEATURE)
+ counter++;
+ }
+
+ if((counter == 1) || (counter > 2))
+ return true;
+
+ return false;
+}
+
+
+#endif
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
new file mode 100755
index 00000000000..9d22b4f8db5
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp
@@ -0,0 +1,43 @@
+//
+// 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 "WXEdgeBuilder.h"
+#include "WXEdge.h"
+
+void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs)
+{
+ WXShape *shape = new WXShape;
+ buildWShape(*shape, ifs);
+ shape->setId(ifs.getId().getFirst());
+ //ifs.setId(shape->GetId());
+}
+
+void WXEdgeBuilder::buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize) {
+ WXVertex *vertex;
+ for (unsigned i = 0; i < vsize; i += 3) {
+ vertex = new WXVertex(Vec3r(vertices[i],
+ vertices[i + 1],
+ vertices[i + 2]));
+ vertex->setId(i / 3);
+ shape.AddVertex(vertex);
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
new file mode 100755
index 00000000000..b646d66a285
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h
@@ -0,0 +1,51 @@
+#ifndef WXEDGEBUILDER_H
+# define WXEDGEBUILDER_H
+
+//
+// Filename : WSBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class inherited from WingedEdgeBuilder and
+// designed to build a WX (WingedEdge + extended info(silhouette etc...))
+// structure from a polygonal model
+// Date of creation : 28/05/03
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 "WingedEdgeBuilder.h"
+# include "../scene_graph/IndexedFaceSet.h"
+
+class LIB_WINGED_EDGE_EXPORT WXEdgeBuilder : public WingedEdgeBuilder
+{
+public:
+ WXEdgeBuilder() : WingedEdgeBuilder() {}
+ virtual ~WXEdgeBuilder() {}
+ VISIT_DECL(IndexedFaceSet)
+
+protected:
+ virtual void buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize);
+};
+
+#endif // WXEDGEBUILDER_H
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
new file mode 100755
index 00000000000..9f3da4707e3
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp
@@ -0,0 +1,362 @@
+
+//
+// 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 "../geometry/GeomUtils.h"
+#include "../scene_graph/NodeShape.h"
+#include "WingedEdgeBuilder.h"
+#include <set>
+using namespace std;
+
+void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) {
+ WShape *shape = new WShape;
+ buildWShape(*shape, ifs);
+ shape->setId(ifs.getId().getFirst());
+ //ifs.setId(shape->GetId());
+}
+
+void WingedEdgeBuilder::visitNodeShape(NodeShape& ns) {
+ //Sets the current material to iShapeode->material:
+ _current_frs_material = &(ns.frs_material());
+}
+
+void WingedEdgeBuilder::visitNodeTransform(NodeTransform& tn) {
+ if(!_current_matrix) {
+ _current_matrix = new Matrix44r(tn.matrix());
+ return;
+ }
+
+ _matrices_stack.push_back(_current_matrix);
+ Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix());
+ _current_matrix = new_matrix;
+}
+
+void WingedEdgeBuilder::visitNodeTransformAfter(NodeTransform&) {
+ if(_current_matrix)
+ delete _current_matrix;
+
+ if(_matrices_stack.empty()) {
+ _current_matrix = NULL;
+ return;
+ }
+
+ _current_matrix = _matrices_stack.back();
+ _matrices_stack.pop_back();
+}
+
+void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) {
+ unsigned vsize = ifs.vsize();
+ unsigned nsize = ifs.nsize();
+ //soc unused - unsigned tsize = ifs.tsize();
+
+ const real* vertices = ifs.vertices();
+ const real* normals = ifs.normals();
+ const real* texCoords = ifs.texCoords();
+
+ real* new_vertices;
+ real* new_normals;
+
+ new_vertices = new real[vsize];
+ new_normals = new real[nsize];
+
+ // transform coordinates from local to world system
+ if(_current_matrix) {
+ transformVertices(vertices, vsize, *_current_matrix, new_vertices);
+ transformNormals(normals, nsize, *_current_matrix, new_normals);
+ }
+ else {
+ memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices));
+ memcpy(new_normals, normals, nsize * sizeof(*new_normals));
+ }
+
+ const IndexedFaceSet::TRIANGLES_STYLE* faceStyle = ifs.trianglesStyle();
+
+ vector<FrsMaterial> frs_materials;
+ if(ifs.msize()){
+ const FrsMaterial*const* mats = ifs.frs_materials();
+ for(unsigned i=0; i<ifs.msize(); ++i)
+ frs_materials.push_back(*(mats[i]));
+ shape.setFrsMaterials(frs_materials);
+ }
+
+ // const FrsMaterial * mat = (ifs.frs_material());
+ // if (mat)
+ // shape.setFrsMaterial(*mat);
+ // else if(_current_frs_material)
+ // shape.setFrsMaterial(*_current_frs_material);
+
+ // sets the current WShape to shape
+ _current_wshape = &shape;
+
+ // create a WVertex for each vertex
+ buildWVertices(shape, new_vertices, vsize);
+
+ const unsigned* vindices = ifs.vindices();
+ const unsigned* nindices = ifs.nindices();
+ const unsigned* tindices = 0;
+ if(ifs.tsize()){
+ tindices = ifs.tindices();
+ }
+
+ const unsigned *mindices = 0;
+ if(ifs.msize())
+ mindices = ifs.mindices();
+ const unsigned* numVertexPerFace = ifs.numVertexPerFaces();
+ const unsigned numfaces = ifs.numFaces();
+
+ for (unsigned index = 0; index < numfaces; index++) {
+ switch(faceStyle[index]) {
+ case IndexedFaceSet::TRIANGLE_STRIP:
+ buildTriangleStrip(new_vertices,
+ new_normals,
+ frs_materials,
+ texCoords,
+ vindices,
+ nindices,
+ mindices,
+ tindices,
+ numVertexPerFace[index]);
+ break;
+ case IndexedFaceSet::TRIANGLE_FAN:
+ buildTriangleFan(new_vertices,
+ new_normals,
+ frs_materials,
+ texCoords,
+ vindices,
+ nindices,
+ mindices,
+ tindices,
+ numVertexPerFace[index]);
+ break;
+ case IndexedFaceSet::TRIANGLES:
+ buildTriangles(new_vertices,
+ new_normals,
+ frs_materials,
+ texCoords,
+ vindices,
+ nindices,
+ mindices,
+ tindices,
+ numVertexPerFace[index]);
+ break;
+ }
+ vindices += numVertexPerFace[index];
+ nindices += numVertexPerFace[index];
+ if(mindices)
+ mindices += numVertexPerFace[index];
+ if(tindices)
+ tindices += numVertexPerFace[index];
+ }
+
+ delete[] new_vertices;
+ delete[] new_normals;
+
+ // compute bbox
+ shape.ComputeBBox();
+ // compute mean edge size:
+ shape.ComputeMeanEdgeSize();
+
+ // Parse the built winged-edge shape to update post-flags
+ set<Vec3r> normalsSet;
+ vector<WVertex*>& wvertices = shape.getVertexList();
+ for(vector<WVertex*>::iterator wv=wvertices.begin(), wvend=wvertices.end();
+ wv!=wvend;
+ ++wv){
+ if((*wv)->isBoundary())
+ continue;
+ normalsSet.clear();
+ WVertex::face_iterator fit = (*wv)->faces_begin();
+ WVertex::face_iterator fitend = (*wv)->faces_end();
+ while(fit!=fitend){
+ WFace *face = *fit;
+ normalsSet.insert(face->GetVertexNormal(*wv));
+ if(normalsSet.size()!=1){
+ break;
+ }
+ ++fit;
+ }
+ if(normalsSet.size()!=1){
+ (*wv)->setSmooth(false);
+ }
+ }
+ // Adds the new WShape to the WingedEdge structure
+ _winged_edge->addWShape(&shape);
+}
+
+void WingedEdgeBuilder::buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize) {
+ WVertex *vertex;
+ for (unsigned i = 0; i < vsize; i += 3) {
+ vertex = new WVertex(Vec3r(vertices[i],
+ vertices[i + 1],
+ vertices[i + 2]));
+ vertex->setId(i / 3);
+ shape.AddVertex(vertex);
+ }
+}
+
+void WingedEdgeBuilder::buildTriangleStrip( const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices) {
+ unsigned nDoneVertices = 2; // number of vertices already treated
+ unsigned nTriangle = 0; // number of the triangle currently being treated
+ //int nVertex = 0; // vertex number
+
+ WShape* currentShape = _current_wshape; // the current shape being built
+ vector<WVertex *> triangleVertices;
+ vector<Vec3r> triangleNormals;
+ vector<Vec2r> triangleTexCoords;
+
+ while(nDoneVertices < nvertices)
+ {
+ //clear the vertices list:
+ triangleVertices.clear();
+ //Then rebuild it:
+ if(0 == nTriangle%2) // if nTriangle is even
+ {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]);
+
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]],normals[nindices[nTriangle+1]+1],normals[nindices[nTriangle+1]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]], normals[nindices[nTriangle+2]+1], normals[nindices[nTriangle+2]+2]));
+
+ if(texCoords){
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]],texCoords[tindices[nTriangle+1]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]], texCoords[tindices[nTriangle+2]+1]));
+ }
+ }
+ else // if nTriangle is odd
+ {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]);
+
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]],normals[nindices[nTriangle+2]+1],normals[nindices[nTriangle+2]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]], normals[nindices[nTriangle+1]+1], normals[nindices[nTriangle+1]+2]));
+
+ if(texCoords){
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]],texCoords[tindices[nTriangle+2]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]], texCoords[tindices[nTriangle+1]+1]));
+ }
+ }
+ if(mindices)
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, mindices[nTriangle/3]);
+ else
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, 0);
+ nDoneVertices++; // with a strip, each triangle is one vertex more
+ nTriangle++;
+ }
+}
+
+void WingedEdgeBuilder::buildTriangleFan( const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices) {
+ // Nothing to be done
+}
+
+void WingedEdgeBuilder::buildTriangles(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices) {
+ WShape * currentShape = _current_wshape; // the current shape begin built
+ vector<WVertex *> triangleVertices;
+ vector<Vec3r> triangleNormals;
+ vector<Vec2r> triangleTexCoords;
+
+ // Each triplet of vertices is considered as an independent triangle
+ for(unsigned i = 0; i < nvertices / 3; i++)
+ {
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+1]/3]);
+ triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+2]/3]);
+
+ triangleNormals.push_back(Vec3r(normals[nindices[3*i]],normals[nindices[3*i]+1], normals[nindices[3*i]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[3*i+1]],normals[nindices[3*i+1]+1],normals[nindices[3*i+1]+2]));
+ triangleNormals.push_back(Vec3r(normals[nindices[3*i+2]], normals[nindices[3*i+2]+1], normals[nindices[3*i+2]+2]));
+
+ if(texCoords){
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i]],texCoords[tindices[3*i]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+1]],texCoords[tindices[3*i+1]+1]));
+ triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+2]], texCoords[tindices[3*i+2]+1]));
+ }
+ }
+ if(mindices)
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, mindices[0]);
+ else
+ currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords,0);
+
+}
+
+void WingedEdgeBuilder::transformVertices(const real *vertices,
+ unsigned vsize,
+ const Matrix44r& transform,
+ real *res) {
+ const real *v = vertices;
+ real *pv = res;
+
+ for (unsigned i = 0; i < vsize / 3; i++) {
+ HVec3r hv_tmp(v[0], v[1], v[2]);
+ HVec3r hv(transform * hv_tmp);
+ for (unsigned j = 0; j < 3; j++)
+ pv[j] = hv[j] / hv[3];
+ v += 3;
+ pv += 3;
+ }
+}
+
+void WingedEdgeBuilder::transformNormals(const real *normals,
+ unsigned nsize,
+ const Matrix44r& transform,
+ real* res) {
+ const real *n = normals;
+ real *pn = res;
+
+ for (unsigned i = 0; i < nsize / 3; i++) {
+ Vec3r hn(n[0], n[1], n[2]);
+ hn = GeomUtils::rotateVector(transform, hn);
+ for (unsigned j = 0; j < 3; j++)
+ pn[j] = hn[j];
+ n += 3;
+ pn += 3;
+ }
+}
diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
new file mode 100755
index 00000000000..6bd515aef0b
--- /dev/null
+++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h
@@ -0,0 +1,160 @@
+//
+// Filename : WingedEdgeBuilder.h
+// Author(s) : Stephane Grabli
+// Purpose : Class to render a WingedEdge data structure
+// from a polyhedral data structure organized in
+// nodes of a scene graph
+// Date of creation : 28/05/03
+//
+///////////////////////////////////////////////////////////////////////////////
+
+
+//
+// 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 WINGED_EDGE_BUILDER_H
+# define WINGED_EDGE_BUILDER_H
+
+# include "../system/FreestyleConfig.h"
+# include "../scene_graph/SceneVisitor.h"
+# include "WEdge.h"
+# include "../scene_graph/IndexedFaceSet.h"
+# include "../scene_graph/NodeTransform.h"
+
+class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor
+{
+ public:
+
+ inline WingedEdgeBuilder() : SceneVisitor() {
+ _current_wshape = NULL;
+ _current_frs_material = NULL;
+ _current_matrix = NULL;
+ _winged_edge = new WingedEdge; // Not deleted by the destructor
+ }
+
+ virtual ~WingedEdgeBuilder() {
+ for (vector<Matrix44r*>::iterator it = _matrices_stack.begin();
+ it != _matrices_stack.end();
+ it++)
+ delete *it;
+ _matrices_stack.clear();
+ }
+
+ VISIT_DECL(IndexedFaceSet)
+ VISIT_DECL(NodeShape)
+ VISIT_DECL(NodeTransform)
+
+ virtual void visitNodeTransformAfter(NodeTransform&);
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline WingedEdge* getWingedEdge() {
+ return _winged_edge;
+ }
+
+ inline WShape* getCurrentWShape() {
+ return _current_wshape;
+ }
+
+ inline FrsMaterial* getCurrentFrsMaterial() {
+ return _current_frs_material;
+ }
+
+ inline Matrix44r* getCurrentMatrix() {
+ return _current_matrix;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+
+ inline void setCurrentWShape(WShape* wshape) {
+ _current_wshape = wshape;
+ }
+
+ inline void setCurrentFrsMaterial(FrsMaterial* mat) {
+ _current_frs_material = mat;
+ }
+
+ // inline void setCurrentMatrix(Matrix44r* matrix) {
+ // _current_matrix = matrix;
+ // }
+
+ protected:
+
+ virtual void buildWShape(WShape& shape, IndexedFaceSet& ifs);
+ virtual void buildWVertices(WShape& shape,
+ const real *vertices,
+ unsigned vsize);
+
+ private:
+
+ void buildTriangleStrip(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices);
+
+ void buildTriangleFan(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices);
+
+ void buildTriangles(const real *vertices,
+ const real *normals,
+ vector<FrsMaterial>& iMaterials,
+ const real *texCoords,
+ const unsigned *vindices,
+ const unsigned *nindices,
+ const unsigned *mindices,
+ const unsigned *tindices,
+ const unsigned nvertices);
+
+ void transformVertices(const real *vertices,
+ unsigned vsize,
+ const Matrix44r& transform,
+ real *res);
+
+ void transformNormals(const real *normals,
+ unsigned nsize,
+ const Matrix44r& transform,
+ real *res);
+
+ WShape* _current_wshape;
+ FrsMaterial* _current_frs_material;
+ WingedEdge* _winged_edge;
+ Matrix44r* _current_matrix;
+ vector<Matrix44r*> _matrices_stack;
+};
+
+#endif // WINGED_EDGE_BUILDER_H
diff --git a/source/blender/makesdna/DNA_freestyle_types.h b/source/blender/makesdna/DNA_freestyle_types.h
new file mode 100644
index 00000000000..fb07f33b533
--- /dev/null
+++ b/source/blender/makesdna/DNA_freestyle_types.h
@@ -0,0 +1,31 @@
+#ifndef DNA_FREESTYLE_TYPES_H
+#define DNA_FREESTYLE_TYPES_H
+
+#include "DNA_listBase.h"
+
+#define FREESTYLE_SUGGESTIVE_CONTOURS_FLAG 1
+#define FREESTYLE_RIDGES_AND_VALLEYS_FLAG 2
+
+typedef struct FreestyleModuleConfig {
+ struct FreestyleModuleConfig *next, *prev;
+
+ char module_path[256];
+ short is_displayed;
+ short pad[3];
+
+} FreestyleModuleConfig;
+
+typedef struct FreestyleConfig {
+ ListBase modules;
+
+ int flags;
+ float sphere_radius;
+ float dkr_epsilon;
+ int pad;
+
+} FreestyleConfig;
+
+
+
+#endif
+
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index f8eb6e76693..9d87f618ec4 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -158,7 +158,7 @@ typedef struct Material {
short sss_flag, sss_preset;
int mapto_textured; /* render-time cache to optimise texture lookups */
- int pad4;
+ short vcol_alpha, pad4;
ListBase gpumaterial; /* runtime */
} Material;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 44cf1398495..92c8921b25a 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -40,6 +40,7 @@ extern "C" {
#include "DNA_vec_types.h"
#include "DNA_listBase.h"
#include "DNA_ID.h"
+#include "DNA_freestyle_types.h"
struct Object;
struct World;
@@ -161,6 +162,9 @@ typedef struct SceneRenderLayer {
int passflag; /* pass_xor has to be after passflag */
int pass_xor;
+
+ struct FreestyleConfig freestyleConfig;
+
} SceneRenderLayer;
/* srl->layflag */
@@ -170,6 +174,7 @@ typedef struct SceneRenderLayer {
#define SCE_LAY_EDGE 8
#define SCE_LAY_SKY 16
#define SCE_LAY_STRAND 32
+#define SCE_LAY_FRS 64
/* flags between 32 and 0x8000 are set to 1 already, for future options */
#define SCE_LAY_ALL_Z 0x8000
@@ -853,6 +858,7 @@ typedef struct Scene {
#define R_NO_OVERWRITE 0x400000 /* skip existing files */
#define R_TOUCH 0x800000 /* touch files before rendering */
#define R_SIMPLIFY 0x1000000
+#define R_EDGE_FRS 0x2000000 /* R_EDGE for Freestyle */
/* seq_flag */
#define R_SEQ_GL_PREV 1
diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c
index adcb074461e..5f098f471d4 100644
--- a/source/blender/makesdna/intern/makesdna.c
+++ b/source/blender/makesdna/intern/makesdna.c
@@ -133,6 +133,7 @@ char *includefiles[] = {
"DNA_anim_types.h",
"DNA_boid_types.h",
"DNA_smoke_types.h",
+ "DNA_freestyle_types.h",
// empty string to indicate end of includefiles
""
@@ -1177,4 +1178,5 @@ int main(int argc, char ** argv)
#include "DNA_anim_types.h"
#include "DNA_boid_types.h"
#include "DNA_smoke_types.h"
+#include "DNA_freestyle_types.h"
/* end of list */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 3ee251c4437..03d8268a70e 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -219,6 +219,7 @@ extern StructRNA RNA_FModifierNoise;
extern StructRNA RNA_FModifierPython;
extern StructRNA RNA_FModifierStepped;
extern StructRNA RNA_FollowPathConstraint;
+extern StructRNA RNA_FreestyleModuleSettings;
extern StructRNA RNA_Function;
extern StructRNA RNA_GameBooleanProperty;
extern StructRNA RNA_GameFloatProperty;
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 7e186f0a587..9bc73dddf22 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -1292,6 +1292,12 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ prop= RNA_def_property(srna, "freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "layflag", SCE_LAY_FRS);
+ RNA_def_property_ui_text(prop, "Freestyle", "Render stylized strokes in this Layer.");
+ if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
/* passes */
prop= RNA_def_property(srna, "pass_combined", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "passflag", SCE_PASS_COMBINED);
@@ -1444,6 +1450,62 @@ void rna_def_render_layer_common(StructRNA *srna, int scene)
else RNA_def_property_clear_flag(prop, PROP_EDITABLE);
}
+static void rna_def_freestyle_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ /* FreestyleModuleSettings */
+
+ srna= RNA_def_struct(brna, "FreestyleModuleSettings", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleModuleConfig");
+ RNA_def_struct_ui_text(srna, "Freestyle Module", "Style module configuration for specifying a style module.");
+
+ prop= RNA_def_property(srna, "module_path", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_string_sdna(prop, NULL, "module_path");
+ RNA_def_property_ui_text(prop, "Module Path", "Path to a style module file.");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "is_displayed", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "is_displayed", 1);
+ RNA_def_property_ui_text(prop, "Is Displayed", "Enable this style module during the rendering.");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ /* FreestyleSettings */
+
+ srna= RNA_def_struct(brna, "FreestyleSettings", NULL);
+ RNA_def_struct_sdna(srna, "FreestyleConfig");
+ RNA_def_struct_nested(brna, srna, "SceneRenderLayer");
+ RNA_def_struct_ui_text(srna, "Frestyle Settings", "Freestyle settings for a SceneRenderLayer datablock.");
+
+ prop= RNA_def_property(srna, "modules", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "modules", NULL);
+ RNA_def_property_struct_type(prop, "FreestyleModuleSettings");
+ RNA_def_property_ui_text(prop, "Style modules", "A list of style modules (to be applied from top to bottom).");
+
+ prop= RNA_def_property(srna, "suggestive_contours", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_SUGGESTIVE_CONTOURS_FLAG);
+ RNA_def_property_ui_text(prop, "Suggestive Contours", "Enable suggestive contours.");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "ridges_and_valleys", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_RIDGES_AND_VALLEYS_FLAG);
+ RNA_def_property_ui_text(prop, "Ridges and Valleys", "Enable ridges and valleys.");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "sphere_radius");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Sphere Radius", "*TBD*");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+
+ prop= RNA_def_property(srna, "dkr_epsilon", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "dkr_epsilon");
+ RNA_def_property_range(prop, 0.0, 1000.0);
+ RNA_def_property_ui_text(prop, "Dkr Epsilon", "*TBD*");
+ RNA_def_property_update(prop, NC_SCENE, NULL);
+}
+
static void rna_def_scene_game_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1735,11 +1797,22 @@ static void rna_def_scene_game_data(BlenderRNA *brna)
static void rna_def_scene_render_layer(BlenderRNA *brna)
{
StructRNA *srna;
+ PropertyRNA *prop;
srna= RNA_def_struct(brna, "SceneRenderLayer", NULL);
RNA_def_struct_ui_text(srna, "Scene Render Layer", "Render layer");
rna_def_render_layer_common(srna, 1);
+
+ /* Freestyle */
+
+ rna_def_freestyle_settings(brna);
+
+ prop= RNA_def_property(srna, "freestyle_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_pointer_sdna(prop, NULL, "freestyleConfig");
+ RNA_def_property_struct_type(prop, "FreestyleSettings");
+ RNA_def_property_ui_text(prop, "Freestyle Settings", "");
}
static void rna_def_scene_render_data(BlenderRNA *brna)
@@ -2366,6 +2439,11 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Edge Color", "");
RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+ prop= RNA_def_property(srna, "freestyle", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "mode", R_EDGE_FRS);
+ RNA_def_property_ui_text(prop, "Edge", "Draw stylized strokes using Freestyle.");
+ RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+
/* threads */
prop= RNA_def_property(srna, "threads", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "threads");
@@ -3123,7 +3201,7 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
-
+
/* Transform Orientations */
prop= RNA_def_property(srna, "orientations", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "transform_spaces", NULL);
diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt
index 3c79e9d3056..39c28fe2b94 100644
--- a/source/blender/python/CMakeLists.txt
+++ b/source/blender/python/CMakeLists.txt
@@ -35,6 +35,7 @@ SET(INC
../blenkernel
../windowmanager
../editors/include
+ ../freestyle/intern/python
../../../intern/guardedalloc
${PYTHON_INC}
)
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index ca742a3646a..b4ce9898b1b 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -5,6 +5,7 @@ sources = env.Glob('intern/*.c')
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager'
+incs += ' ../freestyle/intern/python'
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
incs += ' ' + env['BF_PYTHON_INC']
diff --git a/source/blender/python/doc/sphinx_doc_gen.py b/source/blender/python/doc/sphinx_doc_gen.py
index 67cd462b3c1..48c06fb47e9 100644
--- a/source/blender/python/doc/sphinx_doc_gen.py
+++ b/source/blender/python/doc/sphinx_doc_gen.py
@@ -46,6 +46,7 @@ reload(rna_info)
# lame, python wont give some access
MethodDescriptorType = type(dict.get)
GetSetDescriptorType = type(int.real)
+StaticMethodType = type(staticmethod(lambda: None))
EXAMPLE_SET = set()
EXAMPLE_SET_USED = set()
@@ -152,7 +153,7 @@ def py_c_func2sphinx(ident, fw, identifier, py_func, is_class=True):
fw("\n")
else:
fw(ident + ".. function:: %s()\n\n" % identifier)
- fw(ident + " Undocumented function.\n\n" % identifier)
+ fw(ident + " Undocumented function.\n\n")
def pyprop2sphinx(ident, fw, identifier, py_prop):
@@ -252,6 +253,12 @@ def pymodule2sphinx(BASEPATH, module_name, module, title):
if type(descr) == GetSetDescriptorType:
py_descr2sphinx(" ", fw, descr, module_name, type_name, key)
+ for key, descr in descr_items:
+ if type(descr) == StaticMethodType:
+ descr = getattr(value, key)
+ write_indented_lines(" ", fw, descr.__doc__ or "Undocumented", False)
+ fw("\n")
+
fw("\n\n")
file.close()
@@ -333,6 +340,7 @@ def rna2sphinx(BASEPATH):
fw(" bpy.props.rst\n\n")
fw(" mathutils.rst\n\n")
+ fw(" Freestyle.rst\n\n")
fw(" blf.rst\n\n")
file.close()
@@ -375,6 +383,10 @@ def rna2sphinx(BASEPATH):
pymodule2sphinx(BASEPATH, "mathutils", module, "Math Types & Utilities (mathutils)")
del module
+ import Freestyle as module
+ pymodule2sphinx(BASEPATH, "Freestyle", module, "Freestyle Operators & Rules (Freestyle)")
+ del module
+
import blf as module
pymodule2sphinx(BASEPATH, "blf", module, "Blender Font Drawing (blf)")
del module
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 9bd67f678f8..439607a414b 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -40,6 +40,8 @@
#include "../generic/blf_api.h"
#include "../generic/IDProp.h"
+#include "BPy_Freestyle.h"
+
static char bpy_home_paths_doc[] =
".. function:: home_paths(subfolder)\n"
"\n"
@@ -108,6 +110,7 @@ void BPy_init_modules( void )
BGL_Init();
BLF_Init();
IDProp_Init_Types();
+ Freestyle_Init();
mod = PyModule_New("_bpy");
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 5dc89af5632..2f029feec2f 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -29,7 +29,7 @@ FILE(GLOB SRC intern/source/*.c intern/raytrace/*.cpp)
SET(INC
intern/include ../../../intern/guardedalloc ../blenlib ../makesdna
extern/include ../blenkernel ../imbuf
- ../include ../../kernel/gen_messaging ../blenloader
+ ../include ../../kernel/gen_messaging ../blenloader ../freestyle
../../../intern/smoke/extern
../makesrna
)
diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript
index 366f6bd723c..7f80731e26d 100644
--- a/source/blender/render/SConscript
+++ b/source/blender/render/SConscript
@@ -6,7 +6,7 @@ raysources = env.Glob('intern/raytrace/*.cpp')
incs = 'intern/include #/intern/guardedalloc ../blenlib ../makesdna ../makesrna'
incs += ' extern/include ../blenkernel ../radiosity/extern/include ../imbuf'
-incs += ' ../include ../blenloader ../../../intern/smoke/extern'
+incs += ' ../include ../blenloader ../freestyle ../../../intern/smoke/extern'
cflags = env['CCFLAGS']
cxxflags = env['CXXFLAGS']
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 0d8161c9a7a..2838d9f1add 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -210,6 +210,7 @@ void RE_TileProcessor(struct Render *re);
/* only RE_NewRender() needed, main Blender render calls */
void RE_BlenderFrame(struct Render *re, struct Scene *scene, struct SceneRenderLayer *srl, unsigned int lay, int frame);
void RE_BlenderAnim(struct Render *re, struct Scene *scene, unsigned int lay, int sfra, int efra, int tfra, struct ReportList *reports);
+void RE_RenderFreestyleStrokes(struct Render *re, struct Scene *scene);
/* main preview render call */
void RE_PreviewRender(struct Render *re, struct Scene *scene);
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 127fbce20eb..5767b2471ac 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -219,6 +219,8 @@ struct Render
ListBase volumes;
ListBase volume_precache_parts;
+ ListBase freestyle_renders;
+
/* arena for allocating data for use during render, for
* example dynamic TFaces to go in the VlakRen structure.
*/
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 0b7a0119f3e..d1df2677ae2 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -42,6 +42,7 @@
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_object.h"
@@ -67,6 +68,9 @@
#include "RE_pipeline.h"
+#include "FRS_freestyle.h"
+#include "FRS_freestyle_config.h"
+
/* internal */
#include "render_types.h"
#include "renderpipeline.h"
@@ -637,6 +641,7 @@ static RenderResult *new_render_result(Render *re, rcti *partrct, int crop, int
rl->lay= (1<<20) -1;
rl->layflag= 0x7FFF; /* solid ztra halo strand */
rl->passflag= SCE_PASS_COMBINED;
+ FRS_add_freestyle_config( srl );
re->r.actlay= 0;
}
@@ -1738,6 +1743,7 @@ void RE_TileProcessor(Render *re)
/* ************ This part uses API, for rendering Blender scenes ********** */
static int external_render_3d(Render *re, int do_all);
+static void add_freestyle(Render *re);
static void do_render_3d(Render *re)
{
@@ -1762,6 +1768,11 @@ static void do_render_3d(Render *re)
if(!re->test_break(re->tbh))
add_halo_flare(re);
+ /* Freestyle */
+ if( re->r.mode & R_EDGE_FRS && re->r.renderer==R_INTERN)
+ if(!re->test_break(re->tbh))
+ add_freestyle(re);
+
/* free all render verts etc */
RE_Database_Free(re);
}
@@ -2212,6 +2223,64 @@ static void render_composit_stats(void *unused, char *str)
}
+/* invokes Freestyle stroke rendering */
+static void add_freestyle(Render *re)
+{
+ SceneRenderLayer *srl;
+ LinkData *link;
+
+ FRS_init_stroke_rendering(re);
+
+ for(srl= (SceneRenderLayer *)re->scene->r.layers.first; srl; srl= srl->next) {
+
+ link = (LinkData *)MEM_callocN(sizeof(LinkData), "LinkData to Freestyle render");
+ BLI_addtail(&re->freestyle_renders, link);
+
+ if( FRS_is_freestyle_enabled(srl) ) {
+ link->data = (void *)FRS_do_stroke_rendering(re, srl);
+ }
+ }
+}
+
+/* merges the results of Freestyle stroke rendering into a given render result */
+static void composite_freestyle_renders(Render *re, int sample)
+{
+ Render *freestyle_render;
+ SceneRenderLayer *srl;
+ LinkData *link;
+
+ link = (LinkData *)re->freestyle_renders.first;
+ for(srl= (SceneRenderLayer *)re->scene->r.layers.first; srl; srl= srl->next) {
+ if( FRS_is_freestyle_enabled(srl) ) {
+ freestyle_render = (Render *)link->data;
+ read_render_result(freestyle_render, sample);
+ FRS_composite_result(re, srl, freestyle_render);
+ RE_FreeRenderResult(freestyle_render->result);
+ freestyle_render->result = NULL;
+ }
+ link = link->next;
+ }
+}
+
+/* releases temporary scenes and renders for Freestyle stroke rendering */
+static void free_all_freestyle_renders(void)
+{
+ Render *re1, *freestyle_render;
+ LinkData *link;
+
+ for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
+ for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) {
+ if (link->data) {
+ freestyle_render = (Render *)link->data;
+ free_libblock(&G.main->scene, freestyle_render->scene);
+ RE_FreeRender(freestyle_render);
+ }
+ }
+ BLI_freelistN( &re1->freestyle_renders );
+ }
+}
+
+
/* reads all buffers, calls optional composite, merges in first result->rectf */
static void do_merge_fullsample(Render *re, bNodeTree *ntree)
{
@@ -2235,9 +2304,12 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree)
tag_scenes_for_render(re);
for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) {
- if(re1->scene->id.flag & LIB_DOIT)
- if(re1->r.scemode & R_FULL_SAMPLE)
+ if(re1->scene->id.flag & LIB_DOIT) {
+ if(re1->r.scemode & R_FULL_SAMPLE) {
read_render_result(re1, sample);
+ composite_freestyle_renders(re1, sample);
+ }
+ }
}
}
@@ -2387,6 +2459,8 @@ static void do_render_composite_fields_blur_3d(Render *re)
do_merge_fullsample(re, NULL);
}
+ free_all_freestyle_renders();
+
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay= render_get_active_layer(re, re->result);
re->display_draw(re->ddh, re->result, NULL);
@@ -2734,6 +2808,16 @@ void RE_BlenderFrame(Render *re, Scene *scene, SceneRenderLayer *srl, unsigned i
G.rendering= 0;
}
+void RE_RenderFreestyleStrokes(Render *re, Scene *scene)
+{
+ re->result_ok= 0;
+ scene->r.cfra= 1;
+ if(render_initialize_from_scene(re, scene, NULL, scene->lay, 0, 0)) {
+ do_render_fields_blur_3d(re);
+ }
+ re->result_ok= 1;
+}
+
static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports)
{
char name[FILE_MAX];
diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c
index 5938e2ce2e0..3696855a6a3 100644
--- a/source/blender/render/intern/source/shadeinput.c
+++ b/source/blender/render/intern/source/shadeinput.c
@@ -1043,6 +1043,7 @@ void shade_input_set_shade_texco(ShadeInput *shi)
shi->actcol= obr->actmcol;
if(mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) {
+ float alpha[8];
for (i=0; (mcol=RE_vlakren_get_mcol(obr, vlr, i, &name, 0)); i++) {
ShadeInputCol *scol= &shi->col[i];
char *cp1, *cp2, *cp3;
@@ -1057,13 +1058,15 @@ void shade_input_set_shade_texco(ShadeInput *shi)
scol->col[0]= (l*((float)cp3[3]) - u*((float)cp1[3]) - v*((float)cp2[3]))/255.0f;
scol->col[1]= (l*((float)cp3[2]) - u*((float)cp1[2]) - v*((float)cp2[2]))/255.0f;
scol->col[2]= (l*((float)cp3[1]) - u*((float)cp1[1]) - v*((float)cp2[1]))/255.0f;
+
+ alpha[i]= (l*((float)cp3[0]) - u*((float)cp1[0]) - v*((float)cp2[0]))/255.0f;
}
if(shi->totcol) {
shi->vcol[0]= shi->col[shi->actcol].col[0];
shi->vcol[1]= shi->col[shi->actcol].col[1];
shi->vcol[2]= shi->col[shi->actcol].col[2];
- shi->vcol[3]= 1.0f;
+ shi->vcol[3]= shi->mat->vcol_alpha ? alpha[shi->actcol] : 1.0f;
}
else {
shi->vcol[0]= 0.0f;
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index 806cafaf89b..449d3da0b6d 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -1590,7 +1590,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr)
shi->r= shi->vcol[0];
shi->g= shi->vcol[1];
shi->b= shi->vcol[2];
- if(ma->mode & (MA_FACETEXTURE_ALPHA))
+ if((ma->mode & (MA_FACETEXTURE_ALPHA)) || ma->vcol_alpha)
shi->alpha= shi->vcol[3];
}
if(ma->texco)