blender/release/scripts/freestyle/style_modules/shaders.py
Tamito Kajiyama 156acd3370 Freestyle Python API improvements - part 1.
* The API syntax of StrokeVertex and StrokeAttribute was updated by means of getter/setter
properties instead of class methods.  Python style modules (including the Parameter Editor
implementation) were updated accordingly.

* Code clean-up was done for a few Python style modules, mostly by removing duplicated
definitions of stroke shaders and fixing indentation.
2013-01-27 20:17:49 +00:00

1325 lines
39 KiB
Python

from freestyle_init import *
from PredicatesU0D import *
from PredicatesB1D import *
from PredicatesU1D import *
from logical_operators import *
from ChainingIterators import *
from random import *
from math import *
## thickness modifiers
######################
class pyDepthDiscontinuityThicknessShader(StrokeShader):
def __init__(self, min, max):
StrokeShader.__init__(self)
self.__min = float(min)
self.__max = float(max)
self.__func = ZDiscontinuityF0D()
def getName(self):
return "pyDepthDiscontinuityThicknessShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
z_min=0.0
z_max=1.0
a = (self.__max - self.__min)/(z_max-z_min)
b = (self.__min*z_max-self.__max*z_min)/(z_max-z_min)
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
z = self.__func(it.castToInterface0DIterator())
thickness = a*z+b
it.getObject().attribute.thickness = (thickness, thickness)
it.increment()
class pyConstantThicknessShader(StrokeShader):
def __init__(self, thickness):
StrokeShader.__init__(self)
self._thickness = thickness
def getName(self):
return "pyConstantThicknessShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
t = self._thickness/2.0
it.getObject().attribute.thickness = (t, t)
it.increment()
class pyFXSThicknessShader(StrokeShader):
def __init__(self, thickness):
StrokeShader.__init__(self)
self._thickness = thickness
def getName(self):
return "pyFXSThicknessShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
t = self._thickness/2.0
it.getObject().attribute.thickness = (t, t)
it.increment()
class pyFXSVaryingThicknessWithDensityShader(StrokeShader):
def __init__(self, wsize, threshold_min, threshold_max, thicknessMin, thicknessMax):
StrokeShader.__init__(self)
self.wsize= wsize
self.threshold_min= threshold_min
self.threshold_max= threshold_max
self._thicknessMin = thicknessMin
self._thicknessMax = thicknessMax
def getName(self):
return "pyVaryingThicknessWithDensityShader"
def shade(self, stroke):
n = stroke.strokeVerticesSize()
i = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
func = DensityF0D(self.wsize)
while it.isEnd() == 0:
toto = it.castToInterface0DIterator()
c= func(toto)
if (c < self.threshold_min ):
c = self.threshold_min
if (c > self.threshold_max ):
c = self.threshold_max
## t = (c - self.threshold_min)/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
t = (self.threshold_max - c )/(self.threshold_max - self.threshold_min)*(self._thicknessMax-self._thicknessMin) + self._thicknessMin
it.getObject().attribute.thickness = (t/2.0, t/2.0)
i = i+1
it.increment()
class pyIncreasingThicknessShader(StrokeShader):
def __init__(self, thicknessMin, thicknessMax):
StrokeShader.__init__(self)
self._thicknessMin = thicknessMin
self._thicknessMax = thicknessMax
def getName(self):
return "pyIncreasingThicknessShader"
def shade(self, stroke):
n = stroke.strokeVerticesSize()
i = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
c = float(i)/float(n)
if(i < float(n)/2.0):
t = (1.0 - c)*self._thicknessMin + c * self._thicknessMax
else:
t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
it.getObject().attribute.thickness = (t/2.0, t/2.0)
i = i+1
it.increment()
class pyConstrainedIncreasingThicknessShader(StrokeShader):
def __init__(self, thicknessMin, thicknessMax, ratio):
StrokeShader.__init__(self)
self._thicknessMin = thicknessMin
self._thicknessMax = thicknessMax
self._ratio = ratio
def getName(self):
return "pyConstrainedIncreasingThicknessShader"
def shade(self, stroke):
slength = stroke.getLength2D()
tmp = self._ratio*slength
maxT = 0.0
if(tmp < self._thicknessMax):
maxT = tmp
else:
maxT = self._thicknessMax
n = stroke.strokeVerticesSize()
i = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
att = it.getObject().attribute
c = float(i)/float(n)
if(i < float(n)/2.0):
t = (1.0 - c)*self._thicknessMin + c * maxT
else:
t = (1.0 - c)*maxT + c * self._thicknessMin
att.thickness = (t/2.0, t/2.0)
if(i == n-1):
att.thickness = (self._thicknessMin/2.0, self._thicknessMin/2.0)
i = i+1
it.increment()
class pyDecreasingThicknessShader(StrokeShader):
def __init__(self, thicknessMax, thicknessMin):
StrokeShader.__init__(self)
self._thicknessMin = thicknessMin
self._thicknessMax = thicknessMax
def getName(self):
return "pyDecreasingThicknessShader"
def shade(self, stroke):
l = stroke.getLength2D()
tMax = self._thicknessMax
if(self._thicknessMax > 0.33*l):
tMax = 0.33*l
tMin = self._thicknessMin
if(self._thicknessMin > 0.1*l):
tMin = 0.1*l
n = stroke.strokeVerticesSize()
i = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
c = float(i)/float(n)
t = (1.0 - c)*tMax +c*tMin
it.getObject().attribute.thickness = (t/2.0, t/2.0)
i = i+1
it.increment()
def smoothC( a, exp ):
c = pow(float(a),exp)*pow(2.0,exp)
return c
class pyNonLinearVaryingThicknessShader(StrokeShader):
def __init__(self, thicknessExtremity, thicknessMiddle, exponent):
StrokeShader.__init__(self)
self._thicknessMin = thicknessMiddle
self._thicknessMax = thicknessExtremity
self._exponent = exponent
def getName(self):
return "pyNonLinearVaryingThicknessShader"
def shade(self, stroke):
n = stroke.strokeVerticesSize()
i = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
if(i < float(n)/2.0):
c = float(i)/float(n)
else:
c = float(n-i)/float(n)
c = smoothC(c, self._exponent)
t = (1.0 - c)*self._thicknessMax + c * self._thicknessMin
it.getObject().attribute.thickness = (t/2.0, t/2.0)
i = i+1
it.increment()
## Spherical linear interpolation (cos)
class pySLERPThicknessShader(StrokeShader):
def __init__(self, thicknessMin, thicknessMax, omega=1.2):
StrokeShader.__init__(self)
self._thicknessMin = thicknessMin
self._thicknessMax = thicknessMax
self._omega = omega
def getName(self):
return "pySLERPThicknessShader"
def shade(self, stroke):
slength = stroke.getLength2D()
tmp = 0.33*slength
maxT = self._thicknessMax
if(tmp < self._thicknessMax):
maxT = tmp
n = stroke.strokeVerticesSize()
i = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
c = float(i)/float(n)
if(i < float(n)/2.0):
t = sin((1-c)*self._omega)/sinh(self._omega)*self._thicknessMin + sin(c*self._omega)/sinh(self._omega) * maxT
else:
t = sin((1-c)*self._omega)/sinh(self._omega)*maxT + sin(c*self._omega)/sinh(self._omega) * self._thicknessMin
it.getObject().attribute.thickness = (t/2.0, t/2.0)
i = i+1
it.increment()
class pyTVertexThickenerShader(StrokeShader): ## FIXME
def __init__(self, a=1.5, n=3):
StrokeShader.__init__(self)
self._a = a
self._n = n
def getName(self):
return "pyTVertexThickenerShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
while it.isEnd() == 0:
if(predTVertex(it) == 1):
it2 = StrokeVertexIterator(it)
it2.increment()
if not(it.isBegin() or it2.isEnd()):
it.increment()
continue
n = self._n
a = self._a
if(it.isBegin()):
it3 = StrokeVertexIterator(it)
count = 0
while (it3.isEnd() == 0 and count < n):
att = it3.getObject().attribute
(tr, tl) = att.thickness
r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
#r = (1.0-a)/float(n-1)*count + a
att.thickness = (r*tr, r*tl)
it3.increment()
count = count + 1
if(it2.isEnd()):
it4 = StrokeVertexIterator(it)
count = 0
while (it4.isBegin() == 0 and count < n):
att = it4.getObject().attribute
(tr, tl) = att.thickness
r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
#r = (1.0-a)/float(n-1)*count + a
att.thickness = (r*tr, r*tl)
it4.decrement()
count = count + 1
if ((it4.isBegin() == 1)):
att = it4.getObject().attribute
(tr, tl) = att.thickness
r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1
#r = (1.0-a)/float(n-1)*count + a
att.thickness = (r*tr, r*tl)
it.increment()
class pyImportance2DThicknessShader(StrokeShader):
def __init__(self, x, y, w, kmin, kmax):
StrokeShader.__init__(self)
self._x = x
self._y = y
self._w = float(w)
self._kmin = float(kmin)
self._kmax = float(kmax)
def getName(self):
return "pyImportanceThicknessShader"
def shade(self, stroke):
origin = Vector([self._x, self._y])
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
v = it.getObject()
p = Vector([v.getProjectedX(), v.getProjectedY()])
d = (p-origin).length
if(d>self._w):
k = self._kmin
else:
k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
att = v.attribute
(tr, tl) = att.thickness
att.thickness = (k*tr/2.0, k*tl/2.0)
it.increment()
class pyImportance3DThicknessShader(StrokeShader):
def __init__(self, x, y, z, w, kmin, kmax):
StrokeShader.__init__(self)
self._x = x
self._y = y
self._z = z
self._w = float(w)
self._kmin = float(kmin)
self._kmax = float(kmax)
def getName(self):
return "pyImportance3DThicknessShader"
def shade(self, stroke):
origin = Vector([self._x, self._y, self._z])
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
v = it.getObject()
p = Vector([v.getX(), v.getY(), v.getZ()])
d = (p-origin).length
if(d>self._w):
k = self._kmin
else:
k = (self._kmax*(self._w-d) + self._kmin*d)/self._w
att = v.attribute
(tr, tl) = att.thickness
att.thickness = (k*tr/2.0, k*tl/2.0)
it.increment()
class pyZDependingThicknessShader(StrokeShader):
def __init__(self, min, max):
StrokeShader.__init__(self)
self.__min = min
self.__max = max
self.__func = GetProjectedZF0D()
def getName(self):
return "pyZDependingThicknessShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
z_min = 1
z_max = 0
while it.isEnd() == 0:
z = self.__func(it.castToInterface0DIterator())
if z < z_min:
z_min = z
if z > z_max:
z_max = z
it.increment()
z_diff = 1 / (z_max - z_min)
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
z = (self.__func(it.castToInterface0DIterator()) - z_min) * z_diff
thickness = (1 - z) * self.__max + z * self.__min
it.getObject().attribute.thickness = (thickness, thickness)
it.increment()
## color modifiers
##################
class pyConstantColorShader(StrokeShader):
def __init__(self,r,g,b, a = 1):
StrokeShader.__init__(self)
self._r = r
self._g = g
self._b = b
self._a = a
def getName(self):
return "pyConstantColorShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
att = it.getObject().attribute
att.color = (self._r, self._g, self._b)
att.alpha = self._a
it.increment()
#c1->c2
class pyIncreasingColorShader(StrokeShader):
def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
StrokeShader.__init__(self)
self._c1 = [r1,g1,b1,a1]
self._c2 = [r2,g2,b2,a2]
def getName(self):
return "pyIncreasingColorShader"
def shade(self, stroke):
n = stroke.strokeVerticesSize() - 1
inc = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
att = it.getObject().attribute
c = float(inc)/float(n)
att.color = ((1-c)*self._c1[0] + c*self._c2[0],
(1-c)*self._c1[1] + c*self._c2[1],
(1-c)*self._c1[2] + c*self._c2[2])
att.alpha = (1-c)*self._c1[3] + c*self._c2[3]
inc = inc+1
it.increment()
# c1->c2->c1
class pyInterpolateColorShader(StrokeShader):
def __init__(self,r1,g1,b1,a1, r2,g2,b2,a2):
StrokeShader.__init__(self)
self._c1 = [r1,g1,b1,a1]
self._c2 = [r2,g2,b2,a2]
def getName(self):
return "pyInterpolateColorShader"
def shade(self, stroke):
n = stroke.strokeVerticesSize() - 1
inc = 0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
att = it.getObject().attribute
u = float(inc)/float(n)
c = 1-2*(fabs(u-0.5))
att.color = ((1-c)*self._c1[0] + c*self._c2[0],
(1-c)*self._c1[1] + c*self._c2[1],
(1-c)*self._c1[2] + c*self._c2[2])
att.alpha = (1-c)*self._c1[3] + c*self._c2[3]
inc = inc+1
it.increment()
class pyMaterialColorShader(StrokeShader):
def __init__(self, threshold=50):
StrokeShader.__init__(self)
self._threshold = threshold
def getName(self):
return "pyMaterialColorShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
func = MaterialF0D()
xn = 0.312713
yn = 0.329016
Yn = 1.0
un = 4.* xn/ ( -2.*xn + 12.*yn + 3. )
vn= 9.* yn/ ( -2.*xn + 12.*yn +3. )
while it.isEnd() == 0:
toto = it.castToInterface0DIterator()
mat = func(toto)
r = mat.diffuseR()
g = mat.diffuseG()
b = mat.diffuseB()
X = 0.412453*r + 0.35758 *g + 0.180423*b
Y = 0.212671*r + 0.71516 *g + 0.072169*b
Z = 0.019334*r + 0.119193*g + 0.950227*b
if((X == 0) and (Y == 0) and (Z == 0)):
X = 0.01
Y = 0.01
Z = 0.01
u = 4.*X / (X + 15.*Y + 3.*Z)
v = 9.*Y / (X + 15.*Y + 3.*Z)
L= 116. * pow((Y/Yn),(1./3.)) -16
U = 13. * L * (u - un)
V = 13. * L * (v - vn)
if (L > self._threshold):
L = L/1.3
U = U+10
else:
L = L +2.5*(100-L)/5.
U = U/3.0
V = V/3.0
u = U / (13. * L) + un
v = V / (13. * L) + vn
Y = Yn * pow( ((L+16.)/116.), 3.)
X = -9. * Y * u / ((u - 4.)* v - u * v)
Z = (9. * Y - 15*v*Y - v*X) /( 3. * v)
r = 3.240479 * X - 1.53715 * Y - 0.498535 * Z
g = -0.969256 * X + 1.875991 * Y + 0.041556 * Z
b = 0.055648 * X - 0.204043 * Y + 1.057311 * Z
r = max(0,r)
g = max(0,g)
b = max(0,b)
it.getObject().attribute.color = (r, g, b)
it.increment()
class pyRandomColorShader(StrokeShader):
def getName(self):
return "pyRandomColorShader"
def __init__(self, s=1):
StrokeShader.__init__(self)
seed(s)
def shade(self, stroke):
## pick a random color
c0 = float(uniform(15,75))/100.0
c1 = float(uniform(15,75))/100.0
c2 = float(uniform(15,75))/100.0
print(c0, c1, c2)
it = stroke.strokeVerticesBegin()
while(it.isEnd() == 0):
it.getObject().attribute.color = (c0,c1,c2)
it.increment()
class py2DCurvatureColorShader(StrokeShader):
def getName(self):
return "py2DCurvatureColorShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
func = Curvature2DAngleF0D()
while it.isEnd() == 0:
c = func(it.castToInterface0DIterator())
if c < 0:
print("negative 2D curvature")
color = 10.0 * c/3.1415
it.getObject().attribute.color = (color, color, color)
it.increment()
class pyTimeColorShader(StrokeShader):
def __init__(self, step=0.01):
StrokeShader.__init__(self)
self._t = 0
self._step = step
def shade(self, stroke):
c = self._t*1.0
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
it.getObject().attribute.color = (c,c,c)
it.increment()
self._t = self._t+self._step
## geometry modifiers
class pySamplingShader(StrokeShader):
def __init__(self, sampling):
StrokeShader.__init__(self)
self._sampling = sampling
def getName(self):
return "pySamplingShader"
def shade(self, stroke):
stroke.Resample(float(self._sampling))
stroke.UpdateLength()
class pyBackboneStretcherShader(StrokeShader):
def __init__(self, l):
StrokeShader.__init__(self)
self._l = l
def getName(self):
return "pyBackboneStretcherShader"
def shade(self, stroke):
it0 = stroke.strokeVerticesBegin()
it1 = StrokeVertexIterator(it0)
it1.increment()
itn = stroke.strokeVerticesEnd()
itn.decrement()
itn_1 = StrokeVertexIterator(itn)
itn_1.decrement()
v0 = it0.getObject()
v1 = it1.getObject()
vn_1 = itn_1.getObject()
vn = itn.getObject()
p0 = Vector([v0.getProjectedX(), v0.getProjectedY()])
pn = Vector([vn.getProjectedX(), vn.getProjectedY()])
p1 = Vector([v1.getProjectedX(), v1.getProjectedY()])
pn_1 = Vector([vn_1.getProjectedX(), vn_1.getProjectedY()])
d1 = p0-p1
d1.normalize()
dn = pn-pn_1
dn.normalize()
newFirst = p0+d1*float(self._l)
newLast = pn+dn*float(self._l)
v0.point = newFirst
vn.point = newLast
stroke.UpdateLength()
class pyLengthDependingBackboneStretcherShader(StrokeShader):
def __init__(self, l):
StrokeShader.__init__(self)
self._l = l
def getName(self):
return "pyBackboneStretcherShader"
def shade(self, stroke):
l = stroke.getLength2D()
stretch = self._l*l
it0 = stroke.strokeVerticesBegin()
it1 = StrokeVertexIterator(it0)
it1.increment()
itn = stroke.strokeVerticesEnd()
itn.decrement()
itn_1 = StrokeVertexIterator(itn)
itn_1.decrement()
v0 = it0.getObject()
v1 = it1.getObject()
vn_1 = itn_1.getObject()
vn = itn.getObject()
p0 = Vector([v0.getProjectedX(), v0.getProjectedY()])
pn = Vector([vn.getProjectedX(), vn.getProjectedY()])
p1 = Vector([v1.getProjectedX(), v1.getProjectedY()])
pn_1 = Vector([vn_1.getProjectedX(), vn_1.getProjectedY()])
d1 = p0-p1
d1.normalize()
dn = pn-pn_1
dn.normalize()
newFirst = p0+d1*float(stretch)
newLast = pn+dn*float(stretch)
v0.point = newFirst
vn.point = newLast
stroke.UpdateLength()
## Shader to replace a stroke by its corresponding tangent
class pyGuidingLineShader(StrokeShader):
def getName(self):
return "pyGuidingLineShader"
## shading method
def shade(self, stroke):
it = stroke.strokeVerticesBegin() ## get the first vertex
itlast = stroke.strokeVerticesEnd() ##
itlast.decrement() ## get the last one
t = itlast.getObject().point - it.getObject().point ## tangent direction
itmiddle = StrokeVertexIterator(it) ##
while(itmiddle.getObject().u<0.5): ## look for the stroke middle vertex
itmiddle.increment() ##
it = StrokeVertexIterator(itmiddle)
it.increment()
while(it.isEnd() == 0): ## position all the vertices along the tangent for the right part
it.getObject().point = itmiddle.getObject().point \
+t*(it.getObject().u-itmiddle.getObject().u)
it.increment()
it = StrokeVertexIterator(itmiddle)
it.decrement()
while(it.isBegin() == 0): ## position all the vertices along the tangent for the left part
it.getObject().point = itmiddle.getObject().point \
-t*(itmiddle.getObject().u-it.getObject().u)
it.decrement()
it.getObject().point = itmiddle.getObject().point-t*itmiddle.getObject().u ## first vertex
stroke.UpdateLength()
class pyBackboneStretcherNoCuspShader(StrokeShader):
def __init__(self, l):
StrokeShader.__init__(self)
self._l = l
def getName(self):
return "pyBackboneStretcherNoCuspShader"
def shade(self, stroke):
it0 = stroke.strokeVerticesBegin()
it1 = StrokeVertexIterator(it0)
it1.increment()
itn = stroke.strokeVerticesEnd()
itn.decrement()
itn_1 = StrokeVertexIterator(itn)
itn_1.decrement()
v0 = it0.getObject()
v1 = it1.getObject()
if((v0.getNature() & Nature.CUSP == 0) and (v1.getNature() & Nature.CUSP == 0)):
p0 = v0.point
p1 = v1.point
d1 = p0-p1
d1.normalize()
newFirst = p0+d1*float(self._l)
v0.point = newFirst
vn_1 = itn_1.getObject()
vn = itn.getObject()
if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)):
pn = vn.point
pn_1 = vn_1.point
dn = pn-pn_1
dn.normalize()
newLast = pn+dn*float(self._l)
vn.point = newLast
stroke.UpdateLength()
class pyDiffusion2Shader(StrokeShader):
"""This shader iteratively adds an offset to the position of each
stroke vertex in the direction perpendicular to the stroke direction
at the point. The offset is scaled by the 2D curvature (i.e., how
quickly the stroke curve is) at the point."""
def __init__(self, lambda1, nbIter):
StrokeShader.__init__(self)
self._lambda = lambda1
self._nbIter = nbIter
self._normalInfo = Normal2DF0D()
self._curvatureInfo = Curvature2DAngleF0D()
def getName(self):
return "pyDiffusionShader"
def shade(self, stroke):
for i in range (1, self._nbIter):
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
v=it.getObject()
p1 = v.point
p2 = self._normalInfo(it.castToInterface0DIterator())*self._lambda*self._curvatureInfo(it.castToInterface0DIterator())
v.point = p1+p2
it.increment()
stroke.UpdateLength()
class pyTipRemoverShader(StrokeShader):
def __init__(self, l):
StrokeShader.__init__(self)
self._l = l
def getName(self):
return "pyTipRemoverShader"
def shade(self, stroke):
originalSize = stroke.strokeVerticesSize()
if(originalSize<4):
return
verticesToRemove = []
oldAttributes = []
it = stroke.strokeVerticesBegin()
while(it.isEnd() == 0):
v = it.getObject()
if((v.curvilinear_abscissa < self._l) or (v.stroke_length-v.curvilinear_abscissa < self._l)):
verticesToRemove.append(v)
oldAttributes.append(StrokeAttribute(v.attribute))
it.increment()
if(originalSize-len(verticesToRemove) < 2):
return
for sv in verticesToRemove:
stroke.RemoveVertex(sv)
stroke.UpdateLength()
stroke.Resample(originalSize)
if(stroke.strokeVerticesSize() != originalSize):
print("pyTipRemover: Warning: resampling problem")
it = stroke.strokeVerticesBegin()
for a in oldAttributes:
if(it.isEnd() == 1):
break
it.getObject().attribute = a
it.increment()
stroke.UpdateLength()
class pyTVertexRemoverShader(StrokeShader):
def getName(self):
return "pyTVertexRemoverShader"
def shade(self, stroke):
if(stroke.strokeVerticesSize() <= 3 ):
return
predTVertex = pyVertexNatureUP0D(Nature.T_VERTEX)
it = stroke.strokeVerticesBegin()
itlast = stroke.strokeVerticesEnd()
itlast.decrement()
if(predTVertex(it) == 1):
stroke.RemoveVertex(it.getObject())
if(predTVertex(itlast) == 1):
stroke.RemoveVertex(itlast.getObject())
stroke.UpdateLength()
class pyExtremitiesOrientationShader(StrokeShader):
def __init__(self, x1,y1,x2=0,y2=0):
StrokeShader.__init__(self)
self._v1 = Vector([x1,y1])
self._v2 = Vector([x2,y2])
def getName(self):
return "pyExtremitiesOrientationShader"
def shade(self, stroke):
print(self._v1.x,self._v1.y)
stroke.setBeginningOrientation(self._v1.x,self._v1.y)
stroke.setEndingOrientation(self._v2.x,self._v2.y)
def getFEdge(it1, it2):
return it1.getFEdge(it2)
class pyHLRShader(StrokeShader):
def getName(self):
return "pyHLRShader"
def shade(self, stroke):
originalSize = stroke.strokeVerticesSize()
if(originalSize<4):
return
it = stroke.strokeVerticesBegin()
invisible = 0
it2 = StrokeVertexIterator(it)
it2.increment()
fe = getFEdge(it.getObject(), it2.getObject())
if(fe.viewedge().qi() != 0):
invisible = 1
while(it2.isEnd() == 0):
v = it.getObject()
vnext = it2.getObject()
if(v.getNature() & Nature.VIEW_VERTEX):
#if(v.getNature() & Nature.T_VERTEX):
fe = getFEdge(v,vnext)
qi = fe.viewedge().qi()
if(qi != 0):
invisible = 1
else:
invisible = 0
if(invisible == 1):
v.attribute.visible = False
it.increment()
it2.increment()
class pyTVertexOrientationShader(StrokeShader):
def __init__(self):
StrokeShader.__init__(self)
self._Get2dDirection = Orientation2DF1D()
def getName(self):
return "pyTVertexOrientationShader"
## finds the TVertex orientation from the TVertex and
## the previous or next edge
def findOrientation(self, tv, ve):
mateVE = tv.mate(ve)
if((ve.qi() != 0) or (mateVE.qi() != 0)):
ait = AdjacencyIterator(tv,1,0)
winner = None
incoming = 1
while(ait.isEnd() == 0):
ave = ait.getObject()
if((ave.getId() != ve.getId()) and (ave.getId() != mateVE.getId())):
winner = ait.getObject()
if(ait.isIncoming() == 0):
incoming = 0
break
ait.increment()
if(winner != None):
if(incoming != 0):
direction = self._Get2dDirection(winner.fedgeB())
else:
direction = self._Get2dDirection(winner.fedgeA())
return direction
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
it2 = StrokeVertexIterator(it)
it2.increment()
## case where the first vertex is a TVertex
v = it.getObject()
if(v.getNature() & Nature.T_VERTEX):
tv = v.castToTVertex()
ve = getFEdge(v, it2.getObject()).viewedge()
if(tv != None):
dir = self.findOrientation(tv, ve)
#print(dir.x, dir.y)
v.attribute.setAttributeVec2f("orientation", dir)
while(it2.isEnd() == 0):
vprevious = it.getObject()
v = it2.getObject()
if(v.getNature() & Nature.T_VERTEX):
tv = v.castToTVertex()
ve = getFEdge(vprevious, v).viewedge()
if(tv != None):
dir = self.findOrientation(tv, ve)
#print(dir.x, dir.y)
v.attribute.setAttributeVec2f("orientation", dir)
it.increment()
it2.increment()
## case where the last vertex is a TVertex
v = it.getObject()
if(v.getNature() & Nature.T_VERTEX):
itPrevious = StrokeVertexIterator(it)
itPrevious.decrement()
tv = v.castToTVertex()
ve = getFEdge(itPrevious.getObject(), v).viewedge()
if(tv != None):
dir = self.findOrientation(tv, ve)
#print(dir.x, dir.y)
v.attribute.setAttributeVec2f("orientation", dir)
class pySinusDisplacementShader(StrokeShader):
def __init__(self, f, a):
StrokeShader.__init__(self)
self._f = f
self._a = a
self._getNormal = Normal2DF0D()
def getName(self):
return "pySinusDisplacementShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
v = it.getObject()
#print(self._getNormal.getName())
n = self._getNormal(it.castToInterface0DIterator())
p = v.point
u = v.u
a = self._a*(1-2*(fabs(u-0.5)))
n = n*a*cos(self._f*u*6.28)
#print(n.x, n.y)
v.point = p+n
#v.point = v.point+n*a*cos(f*v.u)
it.increment()
stroke.UpdateLength()
class pyPerlinNoise1DShader(StrokeShader):
def __init__(self, freq = 10, amp = 10, oct = 4, seed = -1):
StrokeShader.__init__(self)
self.__noise = Noise(seed)
self.__freq = freq
self.__amp = amp
self.__oct = oct
def getName(self):
return "pyPerlinNoise1DShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
v = it.getObject()
i = v.getProjectedX() + v.getProjectedY()
nres = self.__noise.turbulence1(i, self.__freq, self.__amp, self.__oct)
v.point = (v.getProjectedX() + nres, v.getProjectedY() + nres)
it.increment()
stroke.UpdateLength()
class pyPerlinNoise2DShader(StrokeShader):
def __init__(self, freq = 10, amp = 10, oct = 4, seed = -1):
StrokeShader.__init__(self)
self.__noise = Noise(seed)
self.__freq = freq
self.__amp = amp
self.__oct = oct
def getName(self):
return "pyPerlinNoise2DShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
v = it.getObject()
vec = Vector([v.getProjectedX(), v.getProjectedY()])
nres = self.__noise.turbulence2(vec, self.__freq, self.__amp, self.__oct)
v.point = (v.getProjectedX() + nres, v.getProjectedY() + nres)
it.increment()
stroke.UpdateLength()
class pyBluePrintCirclesShader(StrokeShader):
def __init__(self, turns = 1, random_radius = 3, random_center = 5):
StrokeShader.__init__(self)
self.__turns = turns
self.__random_center = random_center
self.__random_radius = random_radius
def getName(self):
return "pyBluePrintCirclesShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
if it.isEnd():
return
p_min = Vector(it.getObject().point)
p_max = Vector(it.getObject().point)
while it.isEnd() == 0:
p = it.getObject().point
if (p.x < p_min.x):
p_min.x = p.x
if (p.x > p_max.x):
p_max.x = p.x
if (p.y < p_min.y):
p_min.y = p.y
if (p.y > p_max.y):
p_max.y = p.y
it.increment()
stroke.Resample(32 * self.__turns)
sv_nb = stroke.strokeVerticesSize()
# print("min :", p_min.x, p_min.y) # DEBUG
# print("mean :", p_sum.x, p_sum.y) # DEBUG
# print("max :", p_max.x, p_max.y) # DEBUG
# print("----------------------") # DEBUG
#######################################################
sv_nb = sv_nb // self.__turns
center = (p_min + p_max) / 2
radius = (center.x - p_min.x + center.y - p_min.y) / 2
p_new = Vector([0, 0])
#######################################################
R = self.__random_radius
C = self.__random_center
i = 0
it = stroke.strokeVerticesBegin()
for j in range(self.__turns):
prev_radius = radius
prev_center = center
radius = radius + randint(-R, R)
center = center + Vector([randint(-C, C), randint(-C, C)])
while i < sv_nb and it.isEnd() == 0:
t = float(i) / float(sv_nb - 1)
r = prev_radius + (radius - prev_radius) * t
c = prev_center + (center - prev_center) * t
p_new.x = c.x + r * cos(2 * pi * t)
p_new.y = c.y + r * sin(2 * pi * t)
it.getObject().point = p_new
i = i + 1
it.increment()
i = 1
verticesToRemove = []
while it.isEnd() == 0:
verticesToRemove.append(it.getObject())
it.increment()
for sv in verticesToRemove:
stroke.RemoveVertex(sv)
stroke.UpdateLength()
class pyBluePrintEllipsesShader(StrokeShader):
def __init__(self, turns = 1, random_radius = 3, random_center = 5):
StrokeShader.__init__(self)
self.__turns = turns
self.__random_center = random_center
self.__random_radius = random_radius
def getName(self):
return "pyBluePrintEllipsesShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
if it.isEnd():
return
p_min = Vector(it.getObject().point)
p_max = Vector(it.getObject().point)
while it.isEnd() == 0:
p = it.getObject().point
if (p.x < p_min.x):
p_min.x = p.x
if (p.x > p_max.x):
p_max.x = p.x
if (p.y < p_min.y):
p_min.y = p.y
if (p.y > p_max.y):
p_max.y = p.y
it.increment()
stroke.Resample(32 * self.__turns)
sv_nb = stroke.strokeVerticesSize()
sv_nb = sv_nb // self.__turns
center = (p_min + p_max) / 2
radius = center - p_min
p_new = Vector([0, 0])
#######################################################
R = self.__random_radius
C = self.__random_center
i = 0
it = stroke.strokeVerticesBegin()
for j in range(self.__turns):
prev_radius = radius
prev_center = center
radius = radius + Vector([randint(-R, R), randint(-R, R)])
center = center + Vector([randint(-C, C), randint(-C, C)])
while i < sv_nb and it.isEnd() == 0:
t = float(i) / float(sv_nb - 1)
r = prev_radius + (radius - prev_radius) * t
c = prev_center + (center - prev_center) * t
p_new.x = c.x + r.x * cos(2 * pi * t)
p_new.y = c.y + r.y * sin(2 * pi * t)
it.getObject().point = p_new
i = i + 1
it.increment()
i = 1
verticesToRemove = []
while it.isEnd() == 0:
verticesToRemove.append(it.getObject())
it.increment()
for sv in verticesToRemove:
stroke.RemoveVertex(sv)
stroke.UpdateLength()
class pyBluePrintSquaresShader(StrokeShader):
def __init__(self, turns = 1, bb_len = 10, bb_rand = 0):
StrokeShader.__init__(self)
self.__turns = turns
self.__bb_len = bb_len
self.__bb_rand = bb_rand
def getName(self):
return "pyBluePrintSquaresShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
if it.isEnd():
return
p_min = Vector(it.getObject().point)
p_max = Vector(it.getObject().point)
while it.isEnd() == 0:
p = it.getObject().point
if (p.x < p_min.x):
p_min.x = p.x
if (p.x > p_max.x):
p_max.x = p.x
if (p.y < p_min.y):
p_min.y = p.y
if (p.y > p_max.y):
p_max.y = p.y
it.increment()
stroke.Resample(32 * self.__turns)
sv_nb = stroke.strokeVerticesSize()
#######################################################
sv_nb = sv_nb // self.__turns
first = sv_nb // 4
second = 2 * first
third = 3 * first
fourth = sv_nb
p_first = Vector([p_min.x - self.__bb_len, p_min.y])
p_first_end = Vector([p_max.x + self.__bb_len, p_min.y])
p_second = Vector([p_max.x, p_min.y - self.__bb_len])
p_second_end = Vector([p_max.x, p_max.y + self.__bb_len])
p_third = Vector([p_max.x + self.__bb_len, p_max.y])
p_third_end = Vector([p_min.x - self.__bb_len, p_max.y])
p_fourth = Vector([p_min.x, p_max.y + self.__bb_len])
p_fourth_end = Vector([p_min.x, p_min.y - self.__bb_len])
#######################################################
R = self.__bb_rand
r = self.__bb_rand // 2
it = stroke.strokeVerticesBegin()
visible = 1
for j in range(self.__turns):
p_first = p_first + Vector([randint(-R, R), randint(-r, r)])
p_first_end = p_first_end + Vector([randint(-R, R), randint(-r, r)])
p_second = p_second + Vector([randint(-r, r), randint(-R, R)])
p_second_end = p_second_end + Vector([randint(-r, r), randint(-R, R)])
p_third = p_third + Vector([randint(-R, R), randint(-r, r)])
p_third_end = p_third_end + Vector([randint(-R, R), randint(-r, r)])
p_fourth = p_fourth + Vector([randint(-r, r), randint(-R, R)])
p_fourth_end = p_fourth_end + Vector([randint(-r, r), randint(-R, R)])
vec_first = p_first_end - p_first
vec_second = p_second_end - p_second
vec_third = p_third_end - p_third
vec_fourth = p_fourth_end - p_fourth
i = 0
while i < sv_nb and it.isEnd() == 0:
if i < first:
p_new = p_first + vec_first * float(i)/float(first - 1)
if i == first - 1:
visible = 0
elif i < second:
p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
if i == second - 1:
visible = 0
elif i < third:
p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
if i == third - 1:
visible = 0
else:
p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
if i == fourth - 1:
visible = 0
if it.getObject() == None:
i = i + 1
it.increment()
if visible == 0:
visible = 1
continue
it.getObject().point = p_new
it.getObject().attribute.visible = visible
if visible == 0:
visible = 1
i = i + 1
it.increment()
verticesToRemove = []
while it.isEnd() == 0:
verticesToRemove.append(it.getObject())
it.increment()
for sv in verticesToRemove:
stroke.RemoveVertex(sv)
stroke.UpdateLength()
class pyBluePrintDirectedSquaresShader(StrokeShader):
def __init__(self, turns = 1, bb_len = 10, mult = 1):
StrokeShader.__init__(self)
self.__mult = mult
self.__turns = turns
self.__bb_len = 1 + float(bb_len) / 100
def getName(self):
return "pyBluePrintDirectedSquaresShader"
def shade(self, stroke):
stroke.Resample(32 * self.__turns)
p_mean = Vector([0, 0])
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
p = it.getObject().point
p_mean = p_mean + p
it.increment()
sv_nb = stroke.strokeVerticesSize()
p_mean = p_mean / sv_nb
p_var_xx = 0
p_var_yy = 0
p_var_xy = 0
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
p = it.getObject().point
p_var_xx = p_var_xx + pow(p.x - p_mean.x, 2)
p_var_yy = p_var_yy + pow(p.y - p_mean.y, 2)
p_var_xy = p_var_xy + (p.x - p_mean.x) * (p.y - p_mean.y)
it.increment()
p_var_xx = p_var_xx / sv_nb
p_var_yy = p_var_yy / sv_nb
p_var_xy = p_var_xy / sv_nb
## print(p_var_xx, p_var_yy, p_var_xy)
trace = p_var_xx + p_var_yy
det = p_var_xx * p_var_yy - p_var_xy * p_var_xy
sqrt_coeff = sqrt(trace * trace - 4 * det)
lambda1 = (trace + sqrt_coeff) / 2
lambda2 = (trace - sqrt_coeff) / 2
## print(lambda1, lambda2)
theta = atan(2 * p_var_xy / (p_var_xx - p_var_yy)) / 2
## print(theta)
if p_var_yy > p_var_xx:
e1 = Vector([cos(theta + pi / 2), sin(theta + pi / 2)]) * sqrt(lambda1) * self.__mult
e2 = Vector([cos(theta + pi), sin(theta + pi)]) * sqrt(lambda2) * self.__mult
else:
e1 = Vector([cos(theta), sin(theta)]) * sqrt(lambda1) * self.__mult
e2 = Vector([cos(theta + pi / 2), sin(theta + pi / 2)]) * sqrt(lambda2) * self.__mult
#######################################################
sv_nb = sv_nb // self.__turns
first = sv_nb // 4
second = 2 * first
third = 3 * first
fourth = sv_nb
bb_len1 = self.__bb_len
bb_len2 = 1 + (bb_len1 - 1) * sqrt(lambda1 / lambda2)
p_first = p_mean - e1 - e2 * bb_len2
p_second = p_mean - e1 * bb_len1 + e2
p_third = p_mean + e1 + e2 * bb_len2
p_fourth = p_mean + e1 * bb_len1 - e2
vec_first = e2 * bb_len2 * 2
vec_second = e1 * bb_len1 * 2
vec_third = vec_first * -1
vec_fourth = vec_second * -1
#######################################################
it = stroke.strokeVerticesBegin()
visible = 1
for j in range(self.__turns):
i = 0
while i < sv_nb:
if i < first:
p_new = p_first + vec_first * float(i)/float(first - 1)
if i == first - 1:
visible = 0
elif i < second:
p_new = p_second + vec_second * float(i - first)/float(second - first - 1)
if i == second - 1:
visible = 0
elif i < third:
p_new = p_third + vec_third * float(i - second)/float(third - second - 1)
if i == third - 1:
visible = 0
else:
p_new = p_fourth + vec_fourth * float(i - third)/float(fourth - third - 1)
if i == fourth - 1:
visible = 0
it.getObject().point = p_new
it.getObject().attribute.visible = visible
if visible == 0:
visible = 1
i = i + 1
it.increment()
verticesToRemove = []
while it.isEnd() == 0:
verticesToRemove.append(it.getObject())
it.increment()
for sv in verticesToRemove:
stroke.RemoveVertex(sv)
stroke.UpdateLength()
class pyModulateAlphaShader(StrokeShader):
def __init__(self, min = 0, max = 1):
StrokeShader.__init__(self)
self.__min = min
self.__max = max
def getName(self):
return "pyModulateAlphaShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
while it.isEnd() == 0:
alpha = it.getObject().attribute.alpha
p = it.getObject().point
alpha = alpha * p.y / 400
if alpha < self.__min:
alpha = self.__min
elif alpha > self.__max:
alpha = self.__max
it.getObject().attribute.alpha = alpha
it.increment()
## various
class pyDummyShader(StrokeShader):
def getName(self):
return "pyDummyShader"
def shade(self, stroke):
it = stroke.strokeVerticesBegin()
it_end = stroke.strokeVerticesEnd()
while it.isEnd() == 0:
toto = it.castToInterface0DIterator()
att = it.getObject().attribute
att.color = (0.3, 0.4, 0.4)
att.thickness = (0, 5)
it.increment()
class pyDebugShader(StrokeShader):
def getName(self):
return "pyDebugShader"
def shade(self, stroke):
fe = GetSelectedFEdgeCF()
id1=fe.vertexA().getId()
id2=fe.vertexB().getId()
#print(id1.getFirst(), id1.getSecond())
#print(id2.getFirst(), id2.getSecond())
it = stroke.strokeVerticesBegin()
found = 0
foundfirst = 0
foundsecond = 0
while it.isEnd() == 0:
cp = it.getObject()
if((cp.A().getId() == id1) or (cp.B().getId() == id1)):
foundfirst = 1
if((cp.A().getId() == id2) or (cp.B().getId() == id2)):
foundsecond = 1
if((foundfirst != 0) and (foundsecond != 0)):
found = 1
break
it.increment()
if(found != 0):
print("The selected Stroke id is: ", stroke.getId().getFirst(), stroke.getId().getSecond())