[Bf-blender-cvs] [b408d8a] master: Freestyle Python API: Updates and speedups for the parameter editor

Tamito Kajiyama noreply at git.blender.org
Thu Jul 24 07:29:53 CEST 2014


Commit: b408d8af31c9fba5898e353c97f95f7ce8dc19c1
Author: Tamito Kajiyama
Date:   Thu Jul 24 11:08:04 2014 +0900
Branches: master
https://developer.blender.org/rBb408d8af31c9fba5898e353c97f95f7ce8dc19c1

Freestyle Python API: Updates and speedups for the parameter editor

In addition to D319, this patch updates the parameter editor, the UI of Freestyle.

Using new API functionality and experience gained in making D319, this patch
provides a quite noticable speedup for commonly-used Freestyle linestyle modifiers.

As this patch touches a lot of code (and mainly the foundations) it is likely that
mistakes are made.  The patch has been tested with a regression suite for Freestyle
(https://github.com/folkertdev/freestyle-regression-tests/tree/master), but testing
with scenes used in production is very much appreciated.

Differential revision: https://developer.blender.org/D623

Author: flokkievids (Folkert de Vries)

Reviewed by: kjym3 (Tamito Kajiyama)

===================================================================

M	release/scripts/freestyle/modules/freestyle/functions.py
M	release/scripts/freestyle/modules/freestyle/predicates.py
M	release/scripts/freestyle/modules/freestyle/utils.py
M	release/scripts/freestyle/modules/parameter_editor.py
M	source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp

===================================================================

diff --git a/release/scripts/freestyle/modules/freestyle/functions.py b/release/scripts/freestyle/modules/freestyle/functions.py
index 9e03f8f..8511989 100644
--- a/release/scripts/freestyle/modules/freestyle/functions.py
+++ b/release/scripts/freestyle/modules/freestyle/functions.py
@@ -91,28 +91,26 @@ from freestyle.utils import integrate
 
 from mathutils import Vector
 
-
 # -- Functions for 0D elements (vertices) -- #
 
 
 class CurveMaterialF0D(UnaryFunction0DMaterial):
     """
     A replacement of the built-in MaterialF0D for stroke creation.
-    MaterialF0D does not work with Curves and Strokes.  Line color
+    MaterialF0D does not work with Curves and Strokes. Line color
     priority is used to pick one of the two materials at material
     boundaries.
+
+    Note: expects instances of CurvePoint to be iterated over
     """
     def __call__(self, inter):
-        cp = inter.object
-        assert(isinstance(cp, CurvePoint))
-        fe = cp.first_svertex.get_fedge(cp.second_svertex)
+        fe = inter.object.fedge
         assert(fe is not None), "CurveMaterialF0D: fe is None"
         if fe.is_smooth:
             return fe.material
-        elif fe.material_right.priority > fe.material_left.priority:
-            return fe.material_right
         else:
-            return fe.material_left
+            right, left = fe.material_right, fe.material_left
+            return right if (right.priority > left.priority) else left
 
 
 class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
@@ -131,7 +129,7 @@ class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
 
 class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
     """Estimates the anisotropy of density"""
-    def __init__(self,level):
+    def __init__(self, level):
         UnaryFunction0DDouble.__init__(self)
         self.IsoDensity = ReadCompleteViewMapPixelF0D(level)
         self.d0Density = ReadSteerableViewMapPixelF0D(0, level)
@@ -145,9 +143,9 @@ class pyDensityAnisotropyF0D(UnaryFunction0DDouble):
         c_1 = self.d1Density(inter)
         c_2 = self.d2Density(inter)
         c_3 = self.d3Density(inter)
-        cMax = max(max(c_0,c_1), max(c_2,c_3))
-        cMin = min(min(c_0,c_1), min(c_2,c_3))
-        return 0 if (c_iso == 0) else (cMax-cMin) / c_iso
+        cMax = max(max(c_0, c_1), max(c_2, c_3))
+        cMin = min(min(c_0, c_1), min(c_2, c_3))
+        return 0 if (c_iso == 0) else (cMax - cMin) / c_iso
 
 
 class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
@@ -163,9 +161,9 @@ class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f):
 
     def __call__(self, iter):
         p = iter.object.point_2d
-        gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
+        gx = CF.read_complete_view_map_pixel(self._l, int(p.x + self._step), int(p.y)) - \
              CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
-        gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
+        gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y + self._step)) - \
              CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
         return Vector((gx, gy))
 
@@ -184,7 +182,6 @@ class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
              CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
         return Vector((gx, gy)).length
 
-
 # -- Functions for 1D elements (curves) -- #
 
 
@@ -199,11 +196,11 @@ class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
     def __call__(self, inter):
         func = GetProjectedZF1D()
         z = func(inter)
-        return (1.0 - z*z)
+        return (1.0 - pow(z, 2))
 
 
 class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
-    def __init__(self,level,  integrationType=IntegrationType.MEAN, sampling=2.0):
+    def __init__(self, level, integrationType=IntegrationType.MEAN, sampling=2.0):
         UnaryFunction1DDouble.__init__(self, integrationType)
         self._func = pyDensityAnisotropyF0D(level)
         self._integration = integrationType
@@ -215,7 +212,7 @@ class pyDensityAnisotropyF1D(UnaryFunction1DDouble):
 
 
 class pyViewMapGradientNormF1D(UnaryFunction1DDouble):
-    def __init__(self,l, integrationType, sampling=2.0):
+    def __init__(self, l, integrationType, sampling=2.0):
         UnaryFunction1DDouble.__init__(self, integrationType)
         self._func = pyViewMapGradientNormF0D(l)
         self._integration = integrationType
diff --git a/release/scripts/freestyle/modules/freestyle/predicates.py b/release/scripts/freestyle/modules/freestyle/predicates.py
index fede3e3..e15820b 100644
--- a/release/scripts/freestyle/modules/freestyle/predicates.py
+++ b/release/scripts/freestyle/modules/freestyle/predicates.py
@@ -52,6 +52,7 @@ from freestyle.types import (
     UnaryPredicate0D,
     UnaryPredicate1D,
     Id,
+    Interface0DIterator,
     )
 from freestyle.functions import (
     Curvature2DAngleF0D,
@@ -82,11 +83,10 @@ class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
     def __init__(self, a):
         UnaryPredicate0D.__init__(self)
         self._a = a
+        self.func = Curvature2DAngleF0D()
 
     def __call__(self, inter):
-        func = Curvature2DAngleF0D()
-        a = func(inter)
-        return (a > self._a)
+        return (self.func(inter) > self._a)
 
 
 class pyUEqualsUP0D(UnaryPredicate0D):
@@ -102,7 +102,7 @@ class pyUEqualsUP0D(UnaryPredicate0D):
 
 
 class pyVertexNatureUP0D(UnaryPredicate0D):
-    def __init__(self,nature):
+    def __init__(self, nature):
         UnaryPredicate0D.__init__(self)
         self._nature = nature
 
@@ -127,7 +127,7 @@ class pyBackTVertexUP0D(UnaryPredicate0D):
 
 
 class pyParameterUP0DGoodOne(UnaryPredicate0D):
-    def __init__(self,pmin,pmax):
+    def __init__(self, pmin, pmax):
         UnaryPredicate0D.__init__(self)
         self._m = pmin
         self._M = pmax
@@ -138,7 +138,7 @@ class pyParameterUP0DGoodOne(UnaryPredicate0D):
 
 
 class pyParameterUP0D(UnaryPredicate0D):
-    def __init__(self,pmin,pmax):
+    def __init__(self, pmin, pmax):
         UnaryPredicate0D.__init__(self)
         self._m = pmin
         self._M = pmax
@@ -154,13 +154,13 @@ class pyParameterUP0D(UnaryPredicate0D):
 
 # -- Unary predicates for 1D elements (curves) -- #
 
-
 class AndUP1D(UnaryPredicate1D):
     def __init__(self, *predicates):
         UnaryPredicate1D.__init__(self)
         self.predicates = predicates
-        if len(self.predicates) < 2:
-            raise ValueError("Expected two or more UnaryPredicate1D")
+        # there are cases in which only one predicate is supplied (in the parameter editor)
+        if len(self.predicates) < 1:
+            raise ValueError("Expected two or more UnaryPredicate1D, got ", len(predicates))
 
     def __call__(self, inter):
         return all(pred(inter) for pred in self.predicates)
@@ -170,8 +170,9 @@ class OrUP1D(UnaryPredicate1D):
     def __init__(self, *predicates):
         UnaryPredicate1D.__init__(self)
         self.predicates = predicates
-        if len(self.predicates) < 2:
-            raise ValueError("Expected two or more UnaryPredicate1D")
+        # there are cases in which only one predicate is supplied (in the parameter editor)
+        if len(self.predicates) < 1:
+            raise ValueError("Expected two or more UnaryPredicate1D, got ", len(predicates))
 
     def __call__(self, inter):
         return any(pred(inter) for pred in self.predicates)
@@ -230,7 +231,7 @@ class pyHigherLengthUP1D(UnaryPredicate1D):
 
 
 class pyNatureUP1D(UnaryPredicate1D):
-    def __init__(self,nature):
+    def __init__(self, nature):
         UnaryPredicate1D.__init__(self)
         self._nature = nature
         self._getNature = CurveNatureF1D()
@@ -244,12 +245,14 @@ class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D):
         UnaryPredicate1D.__init__(self)
         self._n = n
         self._a = a
+        self.func = Curvature2DAngleF0D()
 
     def __call__(self, inter):
-        func = Curvature2DAngleF0D()
-        it = inter.vertices_begin()
+        it = Interface0DIterator(inter)
         # sum the turns, check against n
-        return sum(1 for ve in it if func(it) > self._a) > self._n
+        return sum(1 for _ in it if self.func(it) > self._a) > self._n
+        # interesting fact, the line above is 70% faster than:
+        # return sum(self.func(it) > self._a for _ in it) > self._n
 
 
 class pyDensityUP1D(UnaryPredicate1D):
@@ -345,7 +348,7 @@ class pyZSmallerUP1D(UnaryPredicate1D):
 
 
 class pyIsOccludedByUP1D(UnaryPredicate1D):
-    def __init__(self,id):
+    def __init__(self, id):
         UnaryPredicate1D.__init__(self)
         if not isinstance(id, Id):
             raise TypeError("pyIsOccludedByUP1D expected freestyle.types.Id, not " + type(id).__name__)
@@ -376,7 +379,7 @@ class pyIsOccludedByUP1D(UnaryPredicate1D):
 
 
 class pyIsInOccludersListUP1D(UnaryPredicate1D):
-    def __init__(self,id):
+    def __init__(self, id):
         UnaryPredicate1D.__init__(self)
         self._id = id
 
@@ -409,7 +412,7 @@ class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
 
 
 class pyShapeIdListUP1D(UnaryPredicate1D):
-    def __init__(self,idlist):
+    def __init__(self, idlist):
         UnaryPredicate1D.__init__(self)
         self._funcs = tuple(ShapeUP1D(_id, 0) for _id in idlist)
 
@@ -417,7 +420,7 @@ class pyShapeIdListUP1D(UnaryPredicate1D):
         return any(func(inter) for func in self._funcs)
 
 
-## deprecated
+# DEPRECATED
 class pyShapeIdUP1D(UnaryPredicate1D):
     def __init__(self, _id):
         UnaryPredicate1D.__init__(self)
@@ -429,7 +432,7 @@ class pyShapeIdUP1D(UnaryPredicate1D):
 
 
 class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
-    def __init__(self,threshold, level, sampling=2.0):
+    def __init__(self, threshold, level, sampling=2.0):
         UnaryPredicate1D.__init__(self)
         self._l = threshold
         self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling)
@@ -439,7 +442,7 @@ class pyHighDensityAnisotropyUP1D(UnaryPredicate1D):
 
 
 class pyHighViewMapGradientNormUP1D(UnaryPredicate1D):
-    def __init__(self,threshold, l, sampling=2.0):
+    def __init__(self, threshold, l, sampling=2.0):
 

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list