diff options
55 files changed, 4867 insertions, 0 deletions
diff --git a/release/scripts/freestyle/data/env_map/brown00.png b/release/scripts/freestyle/data/env_map/brown00.png Binary files differnew file mode 100755 index 00000000000..855f06f4fb9 --- /dev/null +++ b/release/scripts/freestyle/data/env_map/brown00.png diff --git a/release/scripts/freestyle/data/env_map/gray00.png b/release/scripts/freestyle/data/env_map/gray00.png Binary files differnew file mode 100755 index 00000000000..7c9b1a8149e --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray00.png diff --git a/release/scripts/freestyle/data/env_map/gray01.png b/release/scripts/freestyle/data/env_map/gray01.png Binary files differnew file mode 100755 index 00000000000..06542908e6b --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray01.png diff --git a/release/scripts/freestyle/data/env_map/gray02.png b/release/scripts/freestyle/data/env_map/gray02.png Binary files differnew file mode 100755 index 00000000000..0208f4920d9 --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray02.png diff --git a/release/scripts/freestyle/data/env_map/gray03.png b/release/scripts/freestyle/data/env_map/gray03.png Binary files differnew file mode 100755 index 00000000000..aab9b957c21 --- /dev/null +++ b/release/scripts/freestyle/data/env_map/gray03.png diff --git a/release/scripts/freestyle/style_modules/ChainingIterators.py b/release/scripts/freestyle/style_modules/ChainingIterators.py new file mode 100755 index 00000000000..968b849f0ae --- /dev/null +++ b/release/scripts/freestyle/style_modules/ChainingIterators.py @@ -0,0 +1,731 @@ +# +# Filename : ChainingIterators.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Chaining Iterators to be used with chaining operators +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * + +## the natural chaining iterator +## It follows the edges of same nature following the topology of +## objects with preseance on silhouettes, then borders, +## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice +## You can specify whether to stay in the selection or not. +class pyChainSilhouetteIterator(ChainingIterator): + def __init__(self, stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 1,None,1) + def getExactTypeName(self): + return "pyChainSilhouetteIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = it.getObject() + it.increment() + if(count != 1): + winner = None + break + return winner + +## the natural chaining iterator +## It follows the edges of same nature on the same +## objects with preseance on silhouettes, then borders, +## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice +## You can specify whether to stay in the selection or not. +## You can specify whether to chain iterate over edges that were +## already visited or not. +class pyChainSilhouetteGenericIterator(ChainingIterator): + def __init__(self, stayInSelection=1, stayInUnvisited=1): + ChainingIterator.__init__(self, stayInSelection, stayInUnvisited,None,1) + def getExactTypeName(self): + return "pyChainSilhouetteGenericIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + ve = it.getObject() + if(ve.getId() == self.getCurrentEdge().getId()): + it.increment() + continue + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = ve + it.increment() + if(count != 1): + winner = None + break + return winner + +class pyExternalContourChainingIterator(ChainingIterator): + def __init__(self): + ChainingIterator.__init__(self, 0, 1,None,1) + self._isExternalContour = ExternalContourUP1D() + + def getExactTypeName(self): + return "pyExternalContourIterator" + + def init(self): + self._nEdges = 0 + self._isInSelection = 1 + + def checkViewEdge(self, ve, orientation): + if(orientation != 0): + vertex = ve.B() + else: + vertex = ve.A() + it = AdjacencyIterator(vertex,1,1) + while(it.isEnd() == 0): + ave = it.getObject() + if(self._isExternalContour(ave)): + return 1 + it.increment() + print "pyExternlContourChainingIterator : didn't find next edge" + return 0 + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + while(it.isEnd() == 0): + ve = it.getObject() + if(self._isExternalContour(ve)): + if (ve.getTimeStamp() == GetTimeStampCF()): + winner = ve + it.increment() + + self._nEdges = self._nEdges+1 + if(winner == None): + orient = 1 + it = AdjacencyIterator(iter) + while(it.isEnd() == 0): + ve = it.getObject() + if(it.isIncoming() != 0): + orient = 0 + good = self.checkViewEdge(ve,orient) + if(good != 0): + winner = ve + it.increment() + return winner + +## the natural chaining iterator +## with a sketchy multiple touch +class pySketchyChainSilhouetteIterator(ChainingIterator): + def __init__(self, nRounds=3,stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 0,None,1) + self._timeStamp = GetTimeStampCF()+nRounds + self._nRounds = nRounds + def getExactTypeName(self): + return "pySketchyChainSilhouetteIterator" + def init(self): + self._timeStamp = GetTimeStampCF()+self._nRounds + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + ve = it.getObject() + if(ve.getId() == self.getCurrentEdge().getId()): + it.increment() + continue + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = ve + it.increment() + if(count != 1): + winner = None + break + if(winner == None): + winner = self.getCurrentEdge() + if(winner.getChainingTimeStamp() == self._timeStamp): + winner = None + return winner + + +# Chaining iterator designed for sketchy style. +# can chain several times the same ViewEdge +# in order to produce multiple strokes per ViewEdge. +class pySketchyChainingIterator(ChainingIterator): + def __init__(self, nRounds=3, stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 0,None,1) + self._timeStamp = GetTimeStampCF()+nRounds + self._nRounds = nRounds + def getExactTypeName(self): + return "pySketchyChainingIterator" + + def init(self): + self._timeStamp = GetTimeStampCF()+self._nRounds + + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == self.getCurrentEdge().getId()): + it.increment() + continue + winner = ve + it.increment() + if(winner == None): + winner = self.getCurrentEdge() + if(winner.getChainingTimeStamp() == self._timeStamp): + return None + return winner + + +## Chaining iterator that fills small occlusions +## percent +## The max length of the occluded part +## expressed in % of the total chain length +class pyFillOcclusionsRelativeChainingIterator(ChainingIterator): + def __init__(self, percent): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = 0 + self._percent = float(percent) + def getExactTypeName(self): + return "pyFillOcclusionsChainingIterator" + def init(self): + # each time we're evaluating a chain length + # we try to do it once. Thus we reinit + # the chain length here: + self._length = 0 + def traverse(self, iter): + winner = None + winnerOrientation = 0 + print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond() + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.getTimeStamp() != GetTimeStampCF()): + #print "---", winner.getId().getFirst(), winner.getId().getSecond() + # if not, let's check whether it's short enough with + # respect to the chain made without staying in the selection + #------------------------------------------------------------ + # Did we compute the prospective chain length already ? + if(self._length == 0): + #if not, let's do it + _it = pyChainSilhouetteGenericIterator(0,0) + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + _it.init() + while(_it.isEnd() == 0): + ve = _it.getObject() + #print "--------", ve.getId().getFirst(), ve.getId().getSecond() + self._length = self._length + ve.getLength2D() + _it.increment() + if(_it.isBegin() != 0): + break; + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + if(_it.isBegin() == 0): + _it.decrement() + while ((_it.isEnd() == 0) and (_it.isBegin() == 0)): + ve = _it.getObject() + #print "--------", ve.getId().getFirst(), ve.getId().getSecond() + self._length = self._length + ve.getLength2D() + _it.decrement() + + # let's do the comparison: + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())): + ve = _cit.getObject() + #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond() + connexl = connexl + ve.getLength2D() + _cit.increment() + if(connexl > self._percent * self._length): + winner = None + return winner + +## Chaining iterator that fills small occlusions +## size +## The max length of the occluded part +## expressed in pixels +class pyFillOcclusionsAbsoluteChainingIterator(ChainingIterator): + def __init__(self, length): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = float(length) + def getExactTypeName(self): + return "pySmallFillOcclusionsChainingIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + winnerOrientation = 0 + #print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond() + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.getTimeStamp() != GetTimeStampCF()): + #print "---", winner.getId().getFirst(), winner.getId().getSecond() + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())): + ve = _cit.getObject() + #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond() + connexl = connexl + ve.getLength2D() + _cit.increment() + if(connexl > self._length): + winner = None + return winner + + +## Chaining iterator that fills small occlusions +## percent +## The max length of the occluded part +## expressed in % of the total chain length +class pyFillOcclusionsAbsoluteAndRelativeChainingIterator(ChainingIterator): + def __init__(self, percent, l): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = 0 + self._absLength = l + self._percent = float(percent) + def getExactTypeName(self): + return "pyFillOcclusionsChainingIterator" + def init(self): + # each time we're evaluating a chain length + # we try to do it once. Thus we reinit + # the chain length here: + self._length = 0 + def traverse(self, iter): + winner = None + winnerOrientation = 0 + print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond() + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.getTimeStamp() != GetTimeStampCF()): + #print "---", winner.getId().getFirst(), winner.getId().getSecond() + # if not, let's check whether it's short enough with + # respect to the chain made without staying in the selection + #------------------------------------------------------------ + # Did we compute the prospective chain length already ? + if(self._length == 0): + #if not, let's do it + _it = pyChainSilhouetteGenericIterator(0,0) + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + _it.init() + while(_it.isEnd() == 0): + ve = _it.getObject() + #print "--------", ve.getId().getFirst(), ve.getId().getSecond() + self._length = self._length + ve.getLength2D() + _it.increment() + if(_it.isBegin() != 0): + break; + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + if(_it.isBegin() == 0): + _it.decrement() + while ((_it.isEnd() == 0) and (_it.isBegin() == 0)): + ve = _it.getObject() + #print "--------", ve.getId().getFirst(), ve.getId().getSecond() + self._length = self._length + ve.getLength2D() + _it.decrement() + + # let's do the comparison: + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().getTimeStamp() != GetTimeStampCF())): + ve = _cit.getObject() + #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond() + connexl = connexl + ve.getLength2D() + _cit.increment() + if((connexl > self._percent * self._length) or (connexl > self._absLength)): + winner = None + return winner + +## Chaining iterator that fills small occlusions without caring about the +## actual selection +## percent +## The max length of the occluded part +## expressed in % of the total chain length +class pyFillQi0AbsoluteAndRelativeChainingIterator(ChainingIterator): + def __init__(self, percent, l): + ChainingIterator.__init__(self, 0, 1,None,1) + self._length = 0 + self._absLength = l + self._percent = float(percent) + def getExactTypeName(self): + return "pyFillOcclusionsChainingIterator" + def init(self): + # each time we're evaluating a chain length + # we try to do it once. Thus we reinit + # the chain length here: + self._length = 0 + def traverse(self, iter): + winner = None + winnerOrientation = 0 + print self.getCurrentEdge().getId().getFirst(), self.getCurrentEdge().getId().getSecond() + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getId() == mateVE.getId() ): + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for nat in natures: + if(self.getCurrentEdge().getNature() & nat != 0): + count=0 + while(it.isEnd() == 0): + ve = it.getObject() + if(ve.getNature() & nat != 0): + count = count+1 + winner = ve + if(it.isIncoming() == 0): + winnerOrientation = 1 + else: + winnerOrientation = 0 + it.increment() + if(count != 1): + winner = None + break + if(winner != None): + # check whether this edge was part of the selection + if(winner.qi() != 0): + #print "---", winner.getId().getFirst(), winner.getId().getSecond() + # if not, let's check whether it's short enough with + # respect to the chain made without staying in the selection + #------------------------------------------------------------ + # Did we compute the prospective chain length already ? + if(self._length == 0): + #if not, let's do it + _it = pyChainSilhouetteGenericIterator(0,0) + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + _it.init() + while(_it.isEnd() == 0): + ve = _it.getObject() + #print "--------", ve.getId().getFirst(), ve.getId().getSecond() + self._length = self._length + ve.getLength2D() + _it.increment() + if(_it.isBegin() != 0): + break; + _it.setBegin(winner) + _it.setCurrentEdge(winner) + _it.setOrientation(winnerOrientation) + if(_it.isBegin() == 0): + _it.decrement() + while ((_it.isEnd() == 0) and (_it.isBegin() == 0)): + ve = _it.getObject() + #print "--------", ve.getId().getFirst(), ve.getId().getSecond() + self._length = self._length + ve.getLength2D() + _it.decrement() + + # let's do the comparison: + # nw let's compute the length of this connex non selected part: + connexl = 0 + _cit = pyChainSilhouetteGenericIterator(0,0) + _cit.setBegin(winner) + _cit.setCurrentEdge(winner) + _cit.setOrientation(winnerOrientation) + _cit.init() + while((_cit.isEnd() == 0) and (_cit.getObject().qi() != 0)): + ve = _cit.getObject() + #print "-------- --------", ve.getId().getFirst(), ve.getId().getSecond() + connexl = connexl + ve.getLength2D() + _cit.increment() + if((connexl > self._percent * self._length) or (connexl > self._absLength)): + winner = None + return winner + + +## the natural chaining iterator +## It follows the edges of same nature on the same +## objects with preseance on silhouettes, then borders, +## then suggestive contours, then everything else. It doesn't chain the same ViewEdge twice +## You can specify whether to stay in the selection or not. +class pyNoIdChainSilhouetteIterator(ChainingIterator): + def __init__(self, stayInSelection=1): + ChainingIterator.__init__(self, stayInSelection, 1,None,1) + def getExactTypeName(self): + return "pyChainSilhouetteIterator" + def init(self): + pass + def traverse(self, iter): + winner = None + it = AdjacencyIterator(iter) + tvertex = self.getVertex() + if type(tvertex) is TVertex: + mateVE = tvertex.mate(self.getCurrentEdge()) + while(it.isEnd() == 0): + ve = it.getObject() + feB = self.getCurrentEdge().fedgeB() + feA = ve.fedgeA() + vB = feB.vertexB() + vA = feA.vertexA() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + feA = self.getCurrentEdge().fedgeA() + feB = ve.fedgeB() + vB = feB.vertexB() + vA = feA.vertexA() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + feA = self.getCurrentEdge().fedgeB() + feB = ve.fedgeB() + vB = feB.vertexB() + vA = feA.vertexB() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + feA = self.getCurrentEdge().fedgeA() + feB = ve.fedgeA() + vB = feB.vertexA() + vA = feA.vertexA() + if vA.getId().getFirst() == vB.getId().getFirst(): + winner = ve + break + it.increment() + else: + ## case of NonTVertex + natures = [Nature.SILHOUETTE,Nature.BORDER,Nature.CREASE,Nature.SUGGESTIVE_CONTOUR,Nature.VALLEY,Nature.RIDGE] + for i in range(len(natures)): + currentNature = self.getCurrentEdge().getNature() + if(natures[i] & currentNature): + count=0 + while(it.isEnd() == 0): + visitNext = 0 + oNature = it.getObject().getNature() + if(oNature & natures[i] != 0): + if(natures[i] != oNature): + for j in range(i): + if(natures[j] & oNature != 0): + visitNext = 1 + break + if(visitNext != 0): + break + count = count+1 + winner = it.getObject() + it.increment() + if(count != 1): + winner = None + break + return winner + diff --git a/release/scripts/freestyle/style_modules/Functions0D.py b/release/scripts/freestyle/style_modules/Functions0D.py new file mode 100755 index 00000000000..872b4e10286 --- /dev/null +++ b/release/scripts/freestyle/style_modules/Functions0D.py @@ -0,0 +1,81 @@ +from freestyle_init import * + + +class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble): + def getName(self): + return "InverseCurvature2DAngleF0D" + + def __call__(self, inter): + func = Curvature2DAngleF0D() + c = func(inter) + return (3.1415 - c) + +class pyCurvilinearLengthF0D(UnaryFunction0DDouble): + def getName(self): + return "CurvilinearLengthF0D" + + def __call__(self, inter): + i0d = inter.getObject() + s = i0d.getExactTypeName() + if (string.find(s, "CurvePoint") == -1): + print "CurvilinearLengthF0D: not implemented yet for %s" % (s) + return -1 + cp = castToCurvePoint(i0d) + return cp.t2d() + +## estimate anisotropy of density +class pyDensityAnisotropyF0D(UnaryFunction0DDouble): + def __init__(self,level): + UnaryFunction0DDouble.__init__(self) + self.IsoDensity = ReadCompleteViewMapPixelF0D(level) + self.d0Density = ReadSteerableViewMapPixelF0D(0, level) + self.d1Density = ReadSteerableViewMapPixelF0D(1, level) + self.d2Density = ReadSteerableViewMapPixelF0D(2, level) + self.d3Density = ReadSteerableViewMapPixelF0D(3, level) + def getName(self): + return "pyDensityAnisotropyF0D" + def __call__(self, inter): + c_iso = self.IsoDensity(inter) + c_0 = self.d0Density(inter) + 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)) + if ( c_iso == 0 ): + v = 0 + else: + v = (cMax-cMin)/c_iso + return (v) + +## Returns the gradient vector for a pixel +## l +## the level at which one wants to compute the gradient +class pyViewMapGradientVectorF0D(UnaryFunction0DVec2f): + def __init__(self, l): + UnaryFunction0DVec2f.__init__(self) + self._l = l + self._step = pow(2,self._l) + def getName(self): + return "pyViewMapGradientVectorF0D" + def __call__(self, iter): + p = iter.getObject().getPoint2D() + gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + return Vector(gx, gy) + +class pyViewMapGradientNormF0D(UnaryFunction0DDouble): + def __init__(self, l): + UnaryFunction0DDouble.__init__(self) + self._l = l + self._step = pow(2,self._l) + def getName(self): + return "pyViewMapGradientNormF0D" + def __call__(self, iter): + p = iter.getObject().getPoint2D() + gx = ReadCompleteViewMapPixelCF(self._l, int(p.x()+self._step), int(p.y()))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + gy = ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y()+self._step))- ReadCompleteViewMapPixelCF(self._l, int(p.x()), int(p.y())) + grad = Vector(gx, gy) + return grad.length + + diff --git a/release/scripts/freestyle/style_modules/Functions1D.py b/release/scripts/freestyle/style_modules/Functions1D.py new file mode 100755 index 00000000000..aaf115356cb --- /dev/null +++ b/release/scripts/freestyle/style_modules/Functions1D.py @@ -0,0 +1,45 @@ +from freestyle_init import * +from Functions0D import * +import string + +class pyGetInverseProjectedZF1D(UnaryFunction1DDouble): + def getName(self): + return "pyGetInverseProjectedZF1D" + + def __call__(self, inter): + func = GetProjectedZF1D() + z = func(inter) + return (1.0 - z) + +class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble): + def getName(self): + return "pyGetInverseProjectedZF1D" + + def __call__(self, inter): + func = GetProjectedZF1D() + z = func(inter) + return (1.0 - z*z) + +class pyDensityAnisotropyF1D(UnaryFunction1DDouble): + def __init__(self,level, integrationType=IntegrationType.MEAN, sampling=2.0): + UnaryFunction1DDouble.__init__(self, integrationType) + self._func = pyDensityAnisotropyF0D(level) + self._integration = integrationType + self._sampling = sampling + def getName(self): + return "pyDensityAnisotropyF1D" + def __call__(self, inter): + v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration) + return v + +class pyViewMapGradientNormF1D(UnaryFunction1DDouble): + def __init__(self,l, integrationType, sampling=2.0): + UnaryFunction1DDouble.__init__(self, integrationType) + self._func = pyViewMapGradientNormF0D(l) + self._integration = integrationType + self._sampling = sampling + def getName(self): + return "pyViewMapGradientNormF1D" + def __call__(self, inter): + v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration) + return v diff --git a/release/scripts/freestyle/style_modules/PredicatesB1D.py b/release/scripts/freestyle/style_modules/PredicatesB1D.py new file mode 100755 index 00000000000..d4c1cace3fe --- /dev/null +++ b/release/scripts/freestyle/style_modules/PredicatesB1D.py @@ -0,0 +1,70 @@ +from freestyle_init import * +from Functions1D import * +from random import * + +class pyZBP1D(BinaryPredicate1D): + def getName(self): + return "pyZBP1D" + + def __call__(self, i1, i2): + func = GetZF1D() + return (func(i1) > func(i2)) + +class pyZDiscontinuityBP1D(BinaryPredicate1D): + def __init__(self, iType = IntegrationType.MEAN): + BinaryPredicate1D.__init__(self) + self._GetZDiscontinuity = ZDiscontinuityF1D(iType) + + def getName(self): + return "pyZDiscontinuityBP1D" + + def __call__(self, i1, i2): + return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2)) + +class pyLengthBP1D(BinaryPredicate1D): + def getName(self): + return "LengthBP1D" + + def __call__(self, i1, i2): + return (i1.getLength2D() > i2.getLength2D()) + +class pySilhouetteFirstBP1D(BinaryPredicate1D): + def getName(self): + return "SilhouetteFirstBP1D" + + def __call__(self, inter1, inter2): + bpred = SameShapeIdBP1D() + if (bpred(inter1, inter2) != 1): + return 0 + if (inter1.getNature() & Nature.SILHOUETTE): + return (inter2.getNature() & Nature.SILHOUETTE) + return (inter1.getNature() == inter2.getNature()) + +class pyNatureBP1D(BinaryPredicate1D): + def getName(self): + return "NatureBP1D" + + def __call__(self, inter1, inter2): + return (inter1.getNature() & inter2.getNature()) + +class pyViewMapGradientNormBP1D(BinaryPredicate1D): + def __init__(self,l, sampling=2.0): + BinaryPredicate1D.__init__(self) + self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN) + def getName(self): + return "pyViewMapGradientNormBP1D" + def __call__(self, i1,i2): + print "compare gradient" + return (self._GetGradient(i1) > self._GetGradient(i2)) + +class pyShuffleBP1D(BinaryPredicate1D): + def __init__(self): + BinaryPredicate1D.__init__(self) + seed(1) + def getName(self): + return "pyNearAndContourFirstBP1D" + + def __call__(self, inter1, inter2): + r1 = uniform(0,1) + r2 = uniform(0,1) + return (r1<r2) diff --git a/release/scripts/freestyle/style_modules/PredicatesU0D.py b/release/scripts/freestyle/style_modules/PredicatesU0D.py new file mode 100755 index 00000000000..42cde5c222f --- /dev/null +++ b/release/scripts/freestyle/style_modules/PredicatesU0D.py @@ -0,0 +1,103 @@ +from freestyle_init import * +from Functions0D import * + +class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D): + def __init__(self,a): + UnaryPredicate0D.__init__(self) + self._a = a + + def getName(self): + return "HigherCurvature2DAngleUP0D" + + def __call__(self, inter): + func = Curvature2DAngleF0D() + a = func(inter) + return ( a > self._a) + +class pyUEqualsUP0D(UnaryPredicate0D): + def __init__(self,u, w): + UnaryPredicate0D.__init__(self) + self._u = u + self._w = w + + def getName(self): + return "UEqualsUP0D" + + def __call__(self, inter): + func = pyCurvilinearLengthF0D() + u = func(inter) + return ( ( u > (self._u-self._w) ) and ( u < (self._u+self._w) ) ) + +class pyVertexNatureUP0D(UnaryPredicate0D): + def __init__(self,nature): + UnaryPredicate0D.__init__(self) + self._nature = nature + + def getName(self): + return "pyVertexNatureUP0D" + + def __call__(self, inter): + v = inter.getObject() + nat = v.getNature() + if(nat & self._nature): + return 1; + return 0 + +## check whether an Interface0DIterator +## is a TVertex and is the one that is +## hidden (inferred from the context) +class pyBackTVertexUP0D(UnaryPredicate0D): + def __init__(self): + UnaryPredicate0D.__init__(self) + self._getQI = QuantitativeInvisibilityF0D() + def getName(self): + return "pyBackTVertexUP0D" + def __call__(self, iter): + v = iter.getObject() + nat = v.getNature() + if(nat & Nature.T_VERTEX == 0): + return 0 + next = iter + if(next.isEnd()): + return 0 + if(self._getQI(next) != 0): + return 1 + return 0 + +class pyParameterUP0DGoodOne(UnaryPredicate0D): + def __init__(self,pmin,pmax): + UnaryPredicate0D.__init__(self) + self._m = pmin + self._M = pmax + #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D() + + def getName(self): + return "pyCurvilinearAbscissaHigherThanUP0D" + + def __call__(self, inter): + #s = self.getCurvilinearAbscissa(inter) + u = inter.u() + #print u + return ((u>=self._m) and (u<=self._M)) + +class pyParameterUP0D(UnaryPredicate0D): + def __init__(self,pmin,pmax): + UnaryPredicate0D.__init__(self) + self._m = pmin + self._M = pmax + #self.getCurvilinearAbscissa = GetCurvilinearAbscissaF0D() + + def getName(self): + return "pyCurvilinearAbscissaHigherThanUP0D" + + def __call__(self, inter): + func = Curvature2DAngleF0D() + c = func(inter) + b1 = (c>0.1) + #s = self.getCurvilinearAbscissa(inter) + u = inter.u() + #print u + b = ((u>=self._m) and (u<=self._M)) + return b and b1 + + diff --git a/release/scripts/freestyle/style_modules/PredicatesU1D.py b/release/scripts/freestyle/style_modules/PredicatesU1D.py new file mode 100755 index 00000000000..f39aa99a5a3 --- /dev/null +++ b/release/scripts/freestyle/style_modules/PredicatesU1D.py @@ -0,0 +1,381 @@ +from freestyle_init import * +from Functions1D import * + +count = 0 +class pyNFirstUP1D(UnaryPredicate1D): + def __init__(self, n): + UnaryPredicate1D.__init__(self) + self.__n = n + def __call__(self, inter): + global count + count = count + 1 + if count <= self.__n: + return 1 + return 0 + +class pyHigherLengthUP1D(UnaryPredicate1D): + def __init__(self,l): + UnaryPredicate1D.__init__(self) + self._l = l + + def getName(self): + return "HigherLengthUP1D" + + def __call__(self, inter): + return (inter.getLength2D() > self._l) + +class pyNatureUP1D(UnaryPredicate1D): + def __init__(self,nature): + UnaryPredicate1D.__init__(self) + self._nature = nature + self._getNature = CurveNatureF1D() + + def getName(self): + return "pyNatureUP1D" + + def __call__(self, inter): + if(self._getNature(inter) & self._nature): + return 1 + return 0 + +class pyHigherNumberOfTurnsUP1D(UnaryPredicate1D): + def __init__(self,n,a): + UnaryPredicate1D.__init__(self) + self._n = n + self._a = a + + def getName(self): + return "HigherNumberOfTurnsUP1D" + + def __call__(self, inter): + count = 0 + func = Curvature2DAngleF0D() + it = inter.verticesBegin() + while(it.isEnd() == 0): + if(func(it) > self._a): + count = count+1 + if(count > self._n): + return 1 + it.increment() + return 0 + +class pyDensityUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = threshold + self._integration = integration + self._func = DensityF1D(self._wsize, self._integration, sampling) + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + if(self._func(inter) < self._threshold): + return 1 + return 0 + +class pyLowSteerableViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, level,integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._level = level + self._integration = integration + + def getName(self): + return "pyLowSteerableViewMapDensityUP1D" + + def __call__(self, inter): + func = GetSteerableViewMapDensityF1D(self._level, self._integration) + v = func(inter) + print v + if(v < self._threshold): + return 1 + return 0 + +class pyLowDirectionalViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._orientation = orientation + self._level = level + self._integration = integration + + def getName(self): + return "pyLowDirectionalViewMapDensityUP1D" + + def __call__(self, inter): + func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration) + v = func(inter) + #print v + if(v < self._threshold): + return 1 + return 0 + +class pyHighSteerableViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, level,integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._level = level + self._integration = integration + self._func = GetSteerableViewMapDensityF1D(self._level, self._integration) + def getName(self): + return "pyHighSteerableViewMapDensityUP1D" + + def __call__(self, inter): + + v = self._func(inter) + if(v > self._threshold): + return 1 + return 0 + +class pyHighDirectionalViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, orientation, level,integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._orientation = orientation + self._level = level + self._integration = integration + self._sampling = sampling + def getName(self): + return "pyLowDirectionalViewMapDensityUP1D" + + def __call__(self, inter): + func = GetDirectionalViewMapDensityF1D(self._orientation, self._level, self._integration, self._sampling) + v = func(inter) + if(v > self._threshold): + return 1 + return 0 + +class pyHighViewMapDensityUP1D(UnaryPredicate1D): + def __init__(self,threshold, level,integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._level = level + self._integration = integration + self._sampling = sampling + self._func = GetCompleteViewMapDensityF1D(self._level, self._integration, self._sampling) # 2.0 is the smpling + + def getName(self): + return "pyHighViewMapDensityUP1D" + + def __call__(self, inter): + #print "toto" + #print func.getName() + #print inter.getExactTypeName() + v= self._func(inter) + if(v > self._threshold): + return 1 + return 0 + +class pyDensityFunctorUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, functor, funcmin=0.0, funcmax=1.0, integration = IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = float(threshold) + self._functor = functor + self._funcmin = float(funcmin) + self._funcmax = float(funcmax) + self._integration = integration + + def getName(self): + return "pyDensityFunctorUP1D" + + def __call__(self, inter): + func = DensityF1D(self._wsize, self._integration) + res = self._functor(inter) + k = (res-self._funcmin)/(self._funcmax-self._funcmin) + if(func(inter) < self._threshold*k): + return 1 + return 0 + +class pyZSmallerUP1D(UnaryPredicate1D): + def __init__(self,z, integration=IntegrationType.MEAN): + UnaryPredicate1D.__init__(self) + self._z = z + self._integration = integration + def getName(self): + return "pyZSmallerUP1D" + + def __call__(self, inter): + func = GetProjectedZF1D(self._integration) + if(func(inter) < self._z): + return 1 + return 0 + +class pyIsOccludedByUP1D(UnaryPredicate1D): + def __init__(self,id): + UnaryPredicate1D.__init__(self) + self._id = id + def getName(self): + return "pyIsOccludedByUP1D" + def __call__(self, inter): + func = GetShapeF1D() + shapes = func(inter) + for s in shapes: + if(s.getId() == self._id): + return 0 + it = inter.verticesBegin() + itlast = inter.verticesEnd() + itlast.decrement() + v = it.getObject() + vlast = itlast.getObject() + tvertex = v.viewvertex() + if type(tvertex) is TVertex: + print "TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]" + eit = tvertex.edgesBegin() + while(eit.isEnd() == 0): + ve, incoming = eit.getObject() + if(ve.getId() == self._id): + return 1 + print "-------", ve.getId().getFirst(), "-", ve.getId().getSecond() + eit.increment() + tvertex = vlast.viewvertex() + if type(tvertex) is TVertex: + print "TVertex: [ ", tvertex.getId().getFirst(), ",", tvertex.getId().getSecond()," ]" + eit = tvertex.edgesBegin() + while(eit.isEnd() == 0): + ve, incoming = eit.getObject() + if(ve.getId() == self._id): + return 1 + print "-------", ve.getId().getFirst(), "-", ve.getId().getSecond() + eit.increment() + return 0 + +class pyIsInOccludersListUP1D(UnaryPredicate1D): + def __init__(self,id): + UnaryPredicate1D.__init__(self) + self._id = id + def getName(self): + return "pyIsInOccludersListUP1D" + def __call__(self, inter): + func = GetOccludersF1D() + occluders = func(inter) + for a in occluders: + if(a.getId() == self._id): + return 1 + return 0 + +class pyIsOccludedByItselfUP1D(UnaryPredicate1D): + def __init__(self): + UnaryPredicate1D.__init__(self) + self.__func1 = GetOccludersF1D() + self.__func2 = GetShapeF1D() + def getName(self): + return "pyIsOccludedByItselfUP1D" + def __call__(self, inter): + lst1 = self.__func1(inter) + lst2 = self.__func2(inter) + for vs1 in lst1: + for vs2 in lst2: + if vs1.getId() == vs2.getId(): + return 1 + return 0 + +class pyIsOccludedByIdListUP1D(UnaryPredicate1D): + def __init__(self, idlist): + UnaryPredicate1D.__init__(self) + self._idlist = idlist + self.__func1 = GetOccludersF1D() + def getName(self): + return "pyIsOccludedByIdListUP1D" + def __call__(self, inter): + lst1 = self.__func1(inter) + for vs1 in lst1: + for id in self._idlist: + if vs1.getId() == id: + return 1 + return 0 + +class pyShapeIdListUP1D(UnaryPredicate1D): + def __init__(self,idlist): + UnaryPredicate1D.__init__(self) + self._idlist = idlist + self._funcs = [] + for id in idlist : + self._funcs.append(ShapeUP1D(id.getFirst(), id.getSecond())) + + def getName(self): + return "pyShapeIdUP1D" + def __call__(self, inter): + for func in self._funcs : + if(func(inter) == 1) : + return 1 + return 0 + +## deprecated +class pyShapeIdUP1D(UnaryPredicate1D): + def __init__(self,id): + UnaryPredicate1D.__init__(self) + self._id = id + def getName(self): + return "pyShapeIdUP1D" + def __call__(self, inter): + func = GetShapeF1D() + shapes = func(inter) + for a in shapes: + if(a.getId() == self._id): + return 1 + return 0 + +class pyHighDensityAnisotropyUP1D(UnaryPredicate1D): + def __init__(self,threshold, level, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._l = threshold + self.func = pyDensityAnisotropyF1D(level, IntegrationType.MEAN, sampling) + def getName(self): + return "pyHighDensityAnisotropyUP1D" + def __call__(self, inter): + return (self.func(inter) > self._l) + +class pyHighViewMapGradientNormUP1D(UnaryPredicate1D): + def __init__(self,threshold, l, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._threshold = threshold + self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN) + def getName(self): + return "pyHighViewMapGradientNormUP1D" + def __call__(self, inter): + gn = self._GetGradient(inter) + #print gn + return (gn > self._threshold) + +class pyDensityVariableSigmaUP1D(UnaryPredicate1D): + def __init__(self,functor, sigmaMin,sigmaMax, lmin, lmax, tmin, tmax, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._functor = functor + self._sigmaMin = float(sigmaMin) + self._sigmaMax = float(sigmaMax) + self._lmin = float(lmin) + self._lmax = float(lmax) + self._tmin = tmin + self._tmax = tmax + self._integration = integration + self._sampling = sampling + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + sigma = (self._sigmaMax-self._sigmaMin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._sigmaMin + t = (self._tmax-self._tmin)/(self._lmax-self._lmin)*(self._functor(inter)-self._lmin) + self._tmin + if(sigma<self._sigmaMin): + sigma = self._sigmaMin + self._func = DensityF1D(sigma, self._integration, self._sampling) + d = self._func(inter) + if(d<t): + return 1 + return 0 + +class pyClosedCurveUP1D(UnaryPredicate1D): + def __call__(self, inter): + it = inter.verticesBegin() + itlast = inter.verticesEnd() + itlast.decrement() + vlast = itlast.getObject() + v = it.getObject() + print v.getId().getFirst(), v.getId().getSecond() + print vlast.getId().getFirst(), vlast.getId().getSecond() + if(v.getId() == vlast.getId()): + return 1 + return 0 diff --git a/release/scripts/freestyle/style_modules/anisotropic_diffusion.py b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py new file mode 100755 index 00000000000..7e7ebf647bd --- /dev/null +++ b/release/scripts/freestyle/style_modules/anisotropic_diffusion.py @@ -0,0 +1,74 @@ +# +# Filename : anisotropic_diffusion.py +# Author : Fredo Durand +# Date : 12/08/2004 +# Purpose : Smoothes lines using an anisotropic diffusion scheme +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * +from PredicatesU0D import * +from math import * + +## thickness modifiers + +normalInfo=Normal2DF0D() +curvatureInfo=Curvature2DAngleF0D() + +def edgestopping(x, sigma): + return exp(- x*x/(2*sigma*sigma)) + +class pyDiffusion2Shader(StrokeShader): + def __init__(self, lambda1, nbIter): + StrokeShader.__init__(self) + self._lambda = lambda1 + self._nbIter = nbIter + 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.getPoint() + p2 = normalInfo(it.castToInterface0DIterator())*self._lambda*curvatureInfo(it.castToInterface0DIterator()) + v.setPoint(p1+p2) + it.increment() + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select( upred ) +bpred = TrueBP1D(); +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred) ) +shaders_list = [ + ConstantThicknessShader(4), + StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0), + SamplingShader(2), + pyDiffusion2Shader(-0.03, 30), + IncreasingColorShader(1.0,0.0,0.0,1, 0, 1, 0, 1) + ] +Operators.create(TrueUP1D(), shaders_list) + + + diff --git a/release/scripts/freestyle/style_modules/apriori_and_causal_density.py b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py new file mode 100755 index 00000000000..7cdd4b2fd66 --- /dev/null +++ b/release/scripts/freestyle/style_modules/apriori_and_causal_density.py @@ -0,0 +1,45 @@ +# +# Filename : apriori_and_causal_density.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Selects the lines with high a priori density and +# subjects them to the causal density so as to avoid +# cluttering +# +############################################################################# +# +# 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. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.3, IntegrationType.LAST)) +Operators.select(upred) +bpred = TrueBP1D() +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + ConstantThicknessShader(2), + ConstantColorShader(0.0, 0.0, 0.0,1) + ] +Operators.create(pyDensityUP1D(1,0.1, IntegrationType.MEAN), shaders_list) diff --git a/release/scripts/freestyle/style_modules/apriori_density.py b/release/scripts/freestyle/style_modules/apriori_density.py new file mode 100755 index 00000000000..5ff6c58e77f --- /dev/null +++ b/release/scripts/freestyle/style_modules/apriori_density.py @@ -0,0 +1,43 @@ +# +# Filename : apriori_density.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws lines having a high a priori density +# +############################################################################# +# +# 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. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.1,5))) +bpred = TrueBP1D() +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyHighViewMapDensityUP1D(0.0007,5)) +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + ConstantThicknessShader(2), + ConstantColorShader(0.0, 0.0, 0.0,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/backbone_stretcher.py b/release/scripts/freestyle/style_modules/backbone_stretcher.py new file mode 100755 index 00000000000..8a6b9d71a66 --- /dev/null +++ b/release/scripts/freestyle/style_modules/backbone_stretcher.py @@ -0,0 +1,36 @@ +# +# Filename : backbone_stretcher.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Stretches the geometry of visible lines +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [TextureAssignerShader(4), ConstantColorShader(0.5, 0.5, 0.5), BackboneStretcherShader(20)] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/blueprint_circles.py b/release/scripts/freestyle/style_modules/blueprint_circles.py new file mode 100755 index 00000000000..7f3a7564cfe --- /dev/null +++ b/release/scripts/freestyle/style_modules/blueprint_circles.py @@ -0,0 +1,46 @@ +# +# Filename : blueprint_circles.py +# Author : Emmanuel Turquin +# Date : 04/08/2005 +# Purpose : Produces a blueprint using circular contour strokes +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +bpred = SameShapeIdBP1D() +Operators.select(upred) +Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred)) +Operators.select(pyHigherLengthUP1D(200)) +shaders_list = [ + ConstantThicknessShader(5), + pyBluePrintCirclesShader(3), + pyPerlinNoise1DShader(0.1, 15, 8), + TextureAssignerShader(4), + IncreasingColorShader(0.8, 0.8, 0.3, 0.4, 0.3, 0.3, 0.3, 0.1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/blueprint_ellipses.py b/release/scripts/freestyle/style_modules/blueprint_ellipses.py new file mode 100755 index 00000000000..a5cfe4ec30b --- /dev/null +++ b/release/scripts/freestyle/style_modules/blueprint_ellipses.py @@ -0,0 +1,46 @@ +# +# Filename : blueprint_ellipses.py +# Author : Emmanuel Turquin +# Date : 04/08/2005 +# Purpose : Produces a blueprint using elliptic contour strokes +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +bpred = SameShapeIdBP1D() +Operators.select(upred) +Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred)) +Operators.select(pyHigherLengthUP1D(200)) +shaders_list = [ + ConstantThicknessShader(5), + pyBluePrintEllipsesShader(3), + pyPerlinNoise1DShader(0.1, 10, 8), + TextureAssignerShader(4), + IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.3, 0.3, 0.3, 0.1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/blueprint_squares.py b/release/scripts/freestyle/style_modules/blueprint_squares.py new file mode 100755 index 00000000000..7798acc7d47 --- /dev/null +++ b/release/scripts/freestyle/style_modules/blueprint_squares.py @@ -0,0 +1,45 @@ +# Filename : blueprint_squares.py +# Author : Emmanuel Turquin +# Date : 04/08/2005 +# Purpose : Produces a blueprint using square contour strokes +# +############################################################################# +# +# 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. +# +############################################################################# +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +bpred = SameShapeIdBP1D() +Operators.select(upred) +Operators.bidirectionalChain(ChainPredicateIterator(upred,bpred), NotUP1D(upred)) +Operators.select(pyHigherLengthUP1D(200)) +shaders_list = [ + ConstantThicknessShader(8), + pyBluePrintSquaresShader(2, 20), + pyPerlinNoise1DShader(0.07, 10, 8), + TextureAssignerShader(4), + IncreasingColorShader(0.6, 0.3, 0.3, 0.7, 0.6, 0.3, 0.3, 0.3), + ConstantThicknessShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/cartoon.py b/release/scripts/freestyle/style_modules/cartoon.py new file mode 100755 index 00000000000..6ace7e0585a --- /dev/null +++ b/release/scripts/freestyle/style_modules/cartoon.py @@ -0,0 +1,42 @@ +# +# Filename : cartoon.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws colored lines. The color is automatically +# infered from each object's material in a cartoon-like +# fashion. +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + BezierCurveShader(3), + ConstantThicknessShader(4), + pyMaterialColorShader(0.8) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/contour.py b/release/scripts/freestyle/style_modules/contour.py new file mode 100755 index 00000000000..c4b3a0f0827 --- /dev/null +++ b/release/scripts/freestyle/style_modules/contour.py @@ -0,0 +1,42 @@ +# +# Filename : contour.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws each object's visible contour +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +Operators.select(AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D() ) ) +bpred = SameShapeIdBP1D(); +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ContourUP1D()) +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + ConstantThicknessShader(5.0), + IncreasingColorShader(0.8,0,0,1,0.1,0,0,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/curvature2d.py b/release/scripts/freestyle/style_modules/curvature2d.py new file mode 100755 index 00000000000..f699e2186ef --- /dev/null +++ b/release/scripts/freestyle/style_modules/curvature2d.py @@ -0,0 +1,60 @@ +# +# Filename : curvature2d.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The stroke points are colored in gray levels and depending +# on the 2d curvature value +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +class py2DCurvatureColorShader(StrokeShader): + def getName(self): + return "py2DCurvatureColorShader" + + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + func = Curvature2DAngleF0D() + while it.isEnd() == 0: + it0D = it.castToInterface0DIterator() + sv = it.getObject() + att = sv.attribute() + c = func(it0D) + if (c<0): + print "negative 2D curvature" + color = 10.0 * c/3.1415 + att.setColor(color,color,color); + it.increment() + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0), + ConstantThicknessShader(5), + py2DCurvatureColorShader() + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/external_contour.py b/release/scripts/freestyle/style_modules/external_contour.py new file mode 100755 index 00000000000..2a39b79a410 --- /dev/null +++ b/release/scripts/freestyle/style_modules/external_contour.py @@ -0,0 +1,43 @@ +# +# Filename : external_contour.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the external contour of the scene +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from ChainingIterators import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred ) +bpred = TrueBP1D(); +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred)) +shaders_list = [ + ConstantThicknessShader(3), + ConstantColorShader(0.0, 0.0, 0.0,1) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/external_contour_sketchy.py b/release/scripts/freestyle/style_modules/external_contour_sketchy.py new file mode 100755 index 00000000000..8a4c570b279 --- /dev/null +++ b/release/scripts/freestyle/style_modules/external_contour_sketchy.py @@ -0,0 +1,48 @@ +# +# Filename : external_contour_sketchy.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the external contour of the scene using a sketchy +# chaining iterator (in particular each ViewEdge can be drawn +# several times +# +############################################################################# +# +# 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. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred) +Operators.bidirectionalChain(pySketchyChainingIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(10, 150, 2, 1, 1), + IncreasingThicknessShader(4, 10), + SmoothingShader(400, 0.1, 0, 0.2, 0, 0, 0, 1), + IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/external_contour_smooth.py b/release/scripts/freestyle/style_modules/external_contour_smooth.py new file mode 100755 index 00000000000..201dc271388 --- /dev/null +++ b/release/scripts/freestyle/style_modules/external_contour_smooth.py @@ -0,0 +1,44 @@ +# +# Filename : external_contour_smooth.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws a smooth external contour +# +############################################################################# +# +# 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. +# +############################################################################# +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * +from ChainingIterators import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred) +bpred = TrueBP1D(); +Operators.bidirectionalChain(ChainPredicateIterator(upred, bpred), NotUP1D(upred)) +shaders_list = [ + SamplingShader(2), + IncreasingThicknessShader(4,20), + IncreasingColorShader(1.0, 0.0, 0.5,1, 0.5,1, 0.3, 1), + SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/extra-lines.sml b/release/scripts/freestyle/style_modules/extra-lines.sml new file mode 100755 index 00000000000..c63cd40945d --- /dev/null +++ b/release/scripts/freestyle/style_modules/extra-lines.sml @@ -0,0 +1,3 @@ +1suggestive.py +1ridges.py +1nor_suggestive_or_ridges.py diff --git a/release/scripts/freestyle/style_modules/freestyle_init.py b/release/scripts/freestyle/style_modules/freestyle_init.py new file mode 100644 index 00000000000..5103cde1048 --- /dev/null +++ b/release/scripts/freestyle/style_modules/freestyle_init.py @@ -0,0 +1,2 @@ +from Blender.Freestyle import * +from Blender.Mathutils import Vector diff --git a/release/scripts/freestyle/style_modules/haloing.py b/release/scripts/freestyle/style_modules/haloing.py new file mode 100755 index 00000000000..afa46173d54 --- /dev/null +++ b/release/scripts/freestyle/style_modules/haloing.py @@ -0,0 +1,50 @@ +# +# Filename : haloing.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : This style module selects the lines that +# are connected (in the image) to a specific +# object and trims them in order to produce +# a haloing effect around the target shape +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesB1D import * +from shaders import * + +# id corresponds to the id of the target object +# (accessed by SHIFT+click) +id = Id(3,0) +upred = AndUP1D(QuantitativeInvisibilityUP1D(0) , pyIsOccludedByUP1D(id)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + IncreasingThicknessShader(3, 5), + IncreasingColorShader(1,0,0, 1,0,1,0,1), + SamplingShader(1.0), + pyTVertexRemoverShader(), + TipRemoverShader(3.0) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/ignore_small_occlusions.py b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py new file mode 100755 index 00000000000..ff6efa89ade --- /dev/null +++ b/release/scripts/freestyle/style_modules/ignore_small_occlusions.py @@ -0,0 +1,41 @@ +# +# Filename : ignore_small_oclusions.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The strokes are drawn through small occlusions +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +#Operators.bidirectionalChain(pyFillOcclusionsChainingIterator(0.1)) +Operators.bidirectionalChain(pyFillOcclusionsAbsoluteChainingIterator(12)) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(3), + ConstantColorShader(0.0,0.0,0.0), + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/invisible_lines.py b/release/scripts/freestyle/style_modules/invisible_lines.py new file mode 100755 index 00000000000..ea509463bfd --- /dev/null +++ b/release/scripts/freestyle/style_modules/invisible_lines.py @@ -0,0 +1,42 @@ +# +# Filename : invisible_lines.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws all lines whose Quantitative Invisibility +# is different from 0 +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +upred = NotUP1D(QuantitativeInvisibilityUP1D(0)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(3.0), + ConstantColorShader(0.7,0.7,0.7) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/japanese_bigbrush.py b/release/scripts/freestyle/style_modules/japanese_bigbrush.py new file mode 100755 index 00000000000..7f109598aaa --- /dev/null +++ b/release/scripts/freestyle/style_modules/japanese_bigbrush.py @@ -0,0 +1,60 @@ +# +# Filename : japanese_bigbrush.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Simulates a big brush fr oriental painting +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesB1D import * +from Functions0D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0))) +## Splits strokes at points of highest 2D curavture +## when there are too many abrupt turns in it +func = pyInverseCurvature2DAngleF0D() +Operators.recursiveSplit(func, pyParameterUP0D(0.2,0.8), NotUP1D(pyHigherNumberOfTurnsUP1D(3, 0.5)), 2) +## Keeps only long enough strokes +Operators.select(pyHigherLengthUP1D(100)) +## Sorts so as to draw the longest strokes first +## (this will be done using the causal density) +Operators.sort(pyLengthBP1D()) +shaders_list = [ + pySamplingShader(10), + BezierCurveShader(30), + SamplingShader(50), + ConstantThicknessShader(10), + pyNonLinearVaryingThicknessShader(4,25, 0.6), + TextureAssignerShader(6), + ConstantColorShader(0.2, 0.2, 0.2,1.0), + TipRemoverShader(10) + ] + +## Use the causal density to avoid cluttering +Operators.create(pyDensityUP1D(8,0.4, IntegrationType.MEAN), shaders_list) + + diff --git a/release/scripts/freestyle/style_modules/logical_operators.py b/release/scripts/freestyle/style_modules/logical_operators.py new file mode 100755 index 00000000000..0ecf6623697 --- /dev/null +++ b/release/scripts/freestyle/style_modules/logical_operators.py @@ -0,0 +1,36 @@ +from freestyle_init import * + +class AndUP1D(UnaryPredicate1D): + def __init__(self, pred1, pred2): + UnaryPredicate1D.__init__(self) + self.__pred1 = pred1 + self.__pred2 = pred2 + + def getName(self): + return "AndUP1D" + + def __call__(self, inter): + return self.__pred1(inter) and self.__pred2(inter) + +class OrUP1D(UnaryPredicate1D): + def __init__(self, pred1, pred2): + UnaryPredicate1D.__init__(self) + self.__pred1 = pred1 + self.__pred2 = pred2 + + def getName(self): + return "OrUP1D" + + def __call__(self, inter): + return self.__pred1(inter) or self.__pred2(inter) + +class NotUP1D(UnaryPredicate1D): + def __init__(self, pred): + UnaryPredicate1D.__init__(self) + self.__pred = pred + + def getName(self): + return "NotUP1D" + + def __call__(self, inter): + return self.__pred(inter) == 0 diff --git a/release/scripts/freestyle/style_modules/long_anisotropically_dense.py b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py new file mode 100755 index 00000000000..52bb2dd1170 --- /dev/null +++ b/release/scripts/freestyle/style_modules/long_anisotropically_dense.py @@ -0,0 +1,81 @@ +# +# Filename : long_anisotropically_dense.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Selects the lines that are long and have a high anisotropic +# a priori density and uses causal density +# to draw without cluttering. Ideally, half of the +# selected lines are culled using the causal density. +# +# ********************* WARNING ************************************* +# ******** The Directional a priori density maps must ****** +# ******** have been computed prior to using this style module ****** +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from PredicatesB1D import * +from Functions0D import * +from Functions1D import * +from shaders import * + +## custom density predicate +class pyDensityUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = threshold + self._integration = integration + self._func = DensityF1D(self._wsize, self._integration, sampling) + self._func2 = DensityF1D(self._wsize, IntegrationType.MAX, sampling) + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + c = self._func(inter) + m = self._func2(inter) + if(c < self._threshold): + return 1 + if( m > 4* c ): + if ( c < 1.5*self._threshold ): + return 1 + return 0 + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0))) +Operators.select(pyHigherLengthUP1D(40)) +## selects lines having a high anisotropic a priori density +Operators.select(pyHighDensityAnisotropyUP1D(0.3,4)) +Operators.sort(pyLengthBP1D()) +shaders_list = [ + SamplingShader(2.0), + ConstantThicknessShader(2), + ConstantColorShader(0.2,0.2,0.25,1), + ] +## uniform culling +Operators.create(pyDensityUP1D(3.0,2.0e-2, IntegrationType.MEAN, 0.1), shaders_list) + + diff --git a/release/scripts/freestyle/style_modules/multiple_parameterization.py b/release/scripts/freestyle/style_modules/multiple_parameterization.py new file mode 100755 index 00000000000..3f0409db5fa --- /dev/null +++ b/release/scripts/freestyle/style_modules/multiple_parameterization.py @@ -0,0 +1,51 @@ +# +# Filename : multiple_parameterization.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The thickness and the color of the strokes vary continuously +# independently from occlusions although only +# visible lines are actually drawn. This is equivalent +# to assigning the thickness using a parameterization covering +# the complete silhouette (visible+invisible) and drawing +# the strokes using a second parameterization that only +# covers the visible portions. +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +## Chain following the same nature, but without the restriction +## of staying inside the selection (0). +Operators.bidirectionalChain(ChainSilhouetteIterator(0)) +shaders_list = [ + SamplingShader(20), + IncreasingThicknessShader(1.5, 30), + ConstantColorShader(0.0,0.0,0.0), + IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(-1), + pyHLRShader() ## this shader draws only visible portions + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/nature.py b/release/scripts/freestyle/style_modules/nature.py new file mode 100755 index 00000000000..b5481a8e519 --- /dev/null +++ b/release/scripts/freestyle/style_modules/nature.py @@ -0,0 +1,43 @@ +# +# Filename : nature.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Uses the NatureUP1D predicate to select the lines +# of a given type (among Nature.SILHOUETTE, Nature.CREASE, Nature.SUGGESTIVE_CONTOURS, +# Nature.BORDERS). +# The suggestive contours must have been enabled in the +# options dialog to appear in the View Map. +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(pyNatureUP1D(Nature.SILHOUETTE)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D( pyNatureUP1D( Nature.SILHOUETTE) ) ) +shaders_list = [ + IncreasingThicknessShader(3, 10), + IncreasingColorShader(0.0,0.0,0.0, 1, 0.8,0,0,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/near_lines.py b/release/scripts/freestyle/style_modules/near_lines.py new file mode 100755 index 00000000000..565bca1fe1f --- /dev/null +++ b/release/scripts/freestyle/style_modules/near_lines.py @@ -0,0 +1,44 @@ +# +# Filename : near_lines.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the lines that are "closer" than a threshold +# (between 0 and 1) +# +############################################################################# +# +# 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. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), pyZSmallerUP1D(0.5, IntegrationType.MEAN)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + TextureAssignerShader(-1), + ConstantThicknessShader(5), + ConstantColorShader(0.0, 0.0, 0.0) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/occluded_by_specific_object.py b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py new file mode 100755 index 00000000000..09ce39d5dd6 --- /dev/null +++ b/release/scripts/freestyle/style_modules/occluded_by_specific_object.py @@ -0,0 +1,45 @@ +# +# Filename : occluded_by_specific_object.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws only the lines that are occluded by a given object +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from shaders import * + +## the id of the occluder (use SHIFT+click on the ViewMap to +## retrieve ids) +id = Id(3,0) +upred = AndUP1D(NotUP1D(QuantitativeInvisibilityUP1D(0)), +pyIsInOccludersListUP1D(id)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(5), + ConstantThicknessShader(3), + ConstantColorShader(0.3,0.3,0.3,1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/polygonalize.py b/release/scripts/freestyle/style_modules/polygonalize.py new file mode 100755 index 00000000000..4446c4c1dcc --- /dev/null +++ b/release/scripts/freestyle/style_modules/polygonalize.py @@ -0,0 +1,40 @@ +# +# Filename : polygonalize.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Make the strokes more "polygonal" +# +############################################################################# +# +# 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. +# +############################################################################# +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(),NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(2.0), + ConstantThicknessShader(3), + ConstantColorShader(0.0,0.0,0.0), + PolygonalizationShader(8) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/qi0.py b/release/scripts/freestyle/style_modules/qi0.py new file mode 100755 index 00000000000..d35d23cb7c3 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi0.py @@ -0,0 +1,41 @@ +# +# Filename : qi0.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the visible lines (chaining follows same nature lines) +# (most basic style module) +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(4.0), + ConstantColorShader(0.0,0.0,0.0) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/qi0_not_external_contour.py b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py new file mode 100755 index 00000000000..eed41af32b4 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi0_not_external_contour.py @@ -0,0 +1,43 @@ +# +# Filename : qi0_not_external_contour.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the visible lines (chaining follows same nature lines) +# that do not belong to the external contour of the scene +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * + +upred = AndUP1D(QuantitativeInvisibilityUP1D(0), ExternalContourUP1D()) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(4, 150, 2, True, True), + IncreasingThicknessShader(2, 5), + BackboneStretcherShader(20), + IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/qi1.py b/release/scripts/freestyle/style_modules/qi1.py new file mode 100755 index 00000000000..8d248376138 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi1.py @@ -0,0 +1,42 @@ +# +# Filename : qi1.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws lines hidden by one surface. +# *** Quantitative Invisibility must have been +# enabled in the options dialog to use this style module **** +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(1)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(1))) +shaders_list = [ + SamplingShader(5.0), + ConstantThicknessShader(3), + ConstantColorShader(0.5,0.5,0.5, 1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/qi2.py b/release/scripts/freestyle/style_modules/qi2.py new file mode 100755 index 00000000000..ba5e97b6982 --- /dev/null +++ b/release/scripts/freestyle/style_modules/qi2.py @@ -0,0 +1,42 @@ +# +# Filename : qi2.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws lines hidden by two surfaces. +# *** Quantitative Invisibility must have been +# enabled in the options dialog to use this style module **** +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(2)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(2))) +shaders_list = [ + SamplingShader(10), + ConstantThicknessShader(1.5), + ConstantColorShader(0.7,0.7,0.7, 1) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py new file mode 100755 index 00000000000..53fa03103aa --- /dev/null +++ b/release/scripts/freestyle/style_modules/sequentialsplit_sketchy.py @@ -0,0 +1,68 @@ +# +# Filename : sequentialsplit_sketchy.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Use the sequential split with two different +# predicates to specify respectively the starting and +# the stopping extremities for strokes +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from Functions0D import * + +## Predicate to tell whether a TVertex +## corresponds to a change from 0 to 1 or not. +class pyBackTVertexUP0D(UnaryPredicate0D): + def __init__(self): + UnaryPredicate0D.__init__(self) + self._getQI = QuantitativeInvisibilityF0D() + def getName(self): + return "pyBackTVertexUP0D" + def __call__(self, iter): + v = iter.getObject() + nat = v.getNature() + if(nat & Nature.T_VERTEX == 0): + return 0 + if(self._getQI(iter) != 0): + return 1 + return 0 + + +upred = QuantitativeInvisibilityUP1D(0) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +## starting and stopping predicates: +start = pyVertexNatureUP0D(Nature.NON_T_VERTEX) +stop = pyBackTVertexUP0D() +Operators.sequentialSplit(start, stop, 10) +shaders_list = [ + SpatialNoiseShader(7, 120, 2, True, True), + IncreasingThicknessShader(5, 8), + ConstantColorShader(0.2, 0.2, 0.2, 1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/shaders.py b/release/scripts/freestyle/style_modules/shaders.py new file mode 100755 index 00000000000..f07e5b5ad12 --- /dev/null +++ b/release/scripts/freestyle/style_modules/shaders.py @@ -0,0 +1,1286 @@ +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().setThickness(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: + att = it.getObject().attribute() + t = self._thickness/2.0 + att.setThickness(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: + att = it.getObject().attribute() + t = self._thickness/2.0 + att.setThickness(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: + att = it.getObject().attribute() + 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 + att.setThickness(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: + att = it.getObject().attribute() + 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 + att.setThickness(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.setThickness(t/2.0, t/2.0) + if(i == n-1): + att.setThickness(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: + att = it.getObject().attribute() + c = float(i)/float(n) + t = (1.0 - c)*tMax +c*tMin + att.setThickness(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: + att = it.getObject().attribute() + 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 + att.setThickness(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: + att = it.getObject().attribute() + 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 + att.setThickness(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 = att.getThicknessR(); + tl = att.getThicknessL(); + r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1 + #r = (1.0-a)/float(n-1)*count + a + att.setThickness(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 = att.getThicknessR(); + tl = att.getThicknessL(); + r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1 + #r = (1.0-a)/float(n-1)*count + a + att.setThickness(r*tr, r*tl) + it4.decrement() + count = count + 1 + if ((it4.isBegin() == 1)): + att = it4.getObject().attribute() + tr = att.getThicknessR(); + tl = att.getThicknessL(); + r = (a-1.0)/float(n-1)*(float(n)/float(count+1) - 1) + 1 + #r = (1.0-a)/float(n-1)*count + a + att.setThickness(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 = att.getThicknessR() + tl = att.getThicknessL() + att.setThickness(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 = att.getThicknessR() + tl = att.getThicknessL() + att.setThickness(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 + elif 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().setThickness(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.setColor(self._r, self._g, self._b) + att.setAlpha(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.setColor( (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.setAlpha((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.setColor( (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.setAlpha((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 + + att = it.getObject().attribute() + att.setColor(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().setColor(c0,c1,c2) + it.increment() + +class py2DCurvatureColorShader(StrokeShader): + def getName(self): + return "py2DCurvatureColorShader" + + def shade(self, stroke): + it = stroke.strokeVerticesBegin() + it_end = stroke.strokeVerticesEnd() + func = Curvature2DAngleF0D() + while it.isEnd() == 0: + toto = it.castToInterface0DIterator() + sv = it.getObject() + att = sv.attribute() + c = func(toto) + if (c<0): + print "negative 2D curvature" + color = 10.0 * c/3.1415 + print color + att.setColor(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: + att = it.getObject().attribute() + att.setColor(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)) + +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.setPoint(newFirst) + vn.setPoint(newLast) + +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.setPoint(newFirst) + vn.setPoint(newLast) + + +## 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().getPoint() - it.getObject().getPoint() ## 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().setPoint(itmiddle.getObject().getPoint() \ + +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().setPoint(itmiddle.getObject().getPoint() \ + -t*(itmiddle.getObject().u()-it.getObject().u())) + it.decrement() + it.getObject().setPoint(itmiddle.getObject().getPoint()-t*(itmiddle.getObject().u())) ## first vertex + + +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.getPoint() + p1 = v1.getPoint() + d1 = p0-p1 + d1.normalize() + newFirst = p0+d1*float(self._l) + v0.setPoint(newFirst) + vn_1 = itn_1.getObject() + vn = itn.getObject() + if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)): + pn = vn.getPoint() + pn_1 = vn_1.getPoint() + dn = pn-pn_1 + dn.normalize() + newLast = pn+dn*float(self._l) + vn.setPoint(newLast) + +normalInfo=Normal2DF0D() +curvatureInfo=Curvature2DAngleF0D() + +def edgestopping(x, sigma): + return exp(- x*x/(2*sigma*sigma)) + +class pyDiffusion2Shader(StrokeShader): + 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.getPoint() + p2 = self._normalInfo(it.castToInterface0DIterator())*self._lambda*self._curvatureInfo(it.castToInterface0DIterator()) + v.setPoint(p1+p2) + it.increment() + +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.curvilinearAbscissa() < self._l) or (v.strokeLength()-v.curvilinearAbscissa() < 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.Resample(originalSize) + if(stroke.strokeVerticesSize() != originalSize): + print "pyTipRemover: Warning: resampling problem" + it = stroke.strokeVerticesBegin() + for a in oldAttributes: + if(it.isEnd() == 1): + break + v = it.getObject() + v.setAttribute(a) + it.increment() + +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()) + +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().setVisible(0) + 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.getPoint() + 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.setPoint(p+n) + #v.setPoint(v.getPoint()+n*a*cos(f*v.u())) + it.increment() + +class pyPerlinNoise1DShader(StrokeShader): + def __init__(self, freq = 10, amp = 10, oct = 4): + StrokeShader.__init__(self) + self.__noise = FrsNoise() + self.__freq = freq + self.__amp = amp + self.__oct = oct + def getName(self): + return "pyPerlinNoise1DShader" + def shade(self, stroke): + i = randint(0, 50) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + v = it.getObject() + nres = self.__noise.turbulence1(i, self.__freq, self.__amp, self.__oct) + v.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres) + i = i+1 + it.increment() + +class pyPerlinNoise2DShader(StrokeShader): + def __init__(self, freq = 10, amp = 10, oct = 4): + StrokeShader.__init__(self) + self.__noise = FrsNoise() + 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.setPoint(v.getProjectedX() + nres, v.getProjectedY() + nres) + it.increment() + +class pyBluePrintCirclesShader(StrokeShader): + def __init__(self, turns = 1): + StrokeShader.__init__(self) + self.__turns = turns + def getName(self): + return "pyBluePrintCirclesShader" + def shade(self, stroke): + p_min = Vector(10000, 10000) + p_max = Vector(0, 0) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + 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) +####################################################### + it = stroke.strokeVerticesBegin() + for j in range(self.__turns): + radius = radius + randint(-3, 3) + center.x = center.x + randint(-5, 5) + center.y = center.y + randint(-5, 5) + i = 0 + while i < sv_nb: + p_new.x = center.x + radius * cos(2 * pi * float(i) / float(sv_nb - 1)) + p_new.y = center.y + radius * sin(2 * pi * float(i) / float(sv_nb - 1)) + it.getObject().setPoint(p_new) + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + + +class pyBluePrintEllipsesShader(StrokeShader): + def __init__(self, turns = 1): + StrokeShader.__init__(self) + self.__turns = turns + def getName(self): + return "pyBluePrintEllipsesShader" + def shade(self, stroke): + p_min = Vector(10000, 10000) + p_max = Vector(0, 0) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + 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_x = center.x - p_min.x + radius_y = center.y - p_min.y + p_new = Vector(0, 0) +####################################################### + it = stroke.strokeVerticesBegin() + for j in range(self.__turns): + radius_x = radius_x + randint(-3, 3) + radius_y = radius_y + randint(-3, 3) + center.x = center.x + randint(-5, 5) + center.y = center.y + randint(-5, 5) + i = 0 + while i < sv_nb: + p_new.x = center.x + radius_x * cos(2 * pi * float(i) / float(sv_nb - 1)) + p_new.y = center.y + radius_y * sin(2 * pi * float(i) / float(sv_nb - 1)) + it.getObject().setPoint(p_new) + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + + +class pyBluePrintSquaresShader(StrokeShader): + def __init__(self, turns = 1, bb_len = 10): + StrokeShader.__init__(self) + self.__turns = turns + self.__bb_len = bb_len + def getName(self): + return "pyBluePrintSquaresShader" + def shade(self, stroke): + p_min = Vector(10000, 10000) + p_max = Vector(0, 0) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + 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 + vec_first = Vector(p_max.x - p_min.x + 2 * self.__bb_len, 0) + vec_second = Vector(0, p_max.y - p_min.y + 2 * self.__bb_len) + vec_third = vec_first * -1 + vec_fourth = vec_second * -1 + p_first = Vector(p_min.x - self.__bb_len, p_min.y) + p_second = Vector(p_max.x, p_min.y - self.__bb_len) + p_third = Vector(p_max.x + self.__bb_len, p_max.y) + p_fourth = Vector(p_min.x, p_max.y + self.__bb_len) +####################################################### + 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().setPoint(p_new) + it.getObject().attribute().setVisible(visible) + if visible == 0: + visible = 1 + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + + +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) + p_min = Vector(10000, 10000) + p_max = Vector(0, 0) + it = stroke.strokeVerticesBegin() + while it.isEnd() == 0: + p = it.getObject().getPoint() + p_mean = p_mean + p +## 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() + 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().getPoint() + 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().setPoint(p_new) + it.getObject().attribute().setVisible(visible) + if visible == 0: + visible = 1 + i = i + 1 + it.increment() + while it.isEnd() == 0: + stroke.RemoveVertex(it.getObject()) + it.increment() + +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().getAlpha() + p = it.getObject().getPoint() + alpha = alpha * p.y / 400 + if alpha < self.__min: + alpha = self.__min + elif alpha > self.__max: + alpha = self.__max + it.getObject().attribute().setAlpha(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.setColor(0.3, 0.4, 0.4) + att.setThickness(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() + diff --git a/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py new file mode 100755 index 00000000000..163c891fa90 --- /dev/null +++ b/release/scripts/freestyle/style_modules/sketchy_multiple_parameterization.py @@ -0,0 +1,48 @@ +# +# Filename : sketchy_multiple_parameterization.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Builds sketchy strokes whose topology relies on a +# parameterization that covers the complete lines (visible+invisible) +# whereas only the visible portions are actually drawn +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + + +Operators.select(QuantitativeInvisibilityUP1D(0)) +## 0: don't restrict to selection +Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,0)) +shaders_list = [ + SamplingShader(2), + SpatialNoiseShader(15, 120, 2, 1, 1), + IncreasingThicknessShader(5, 30), + SmoothingShader(100, 0.05, 0, 0.2, 0, 0, 0, 1), + IncreasingColorShader(0,0.2,0,1,0.2,0.7,0.2,1), + TextureAssignerShader(6), + pyHLRShader() + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_broken.py b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py new file mode 100755 index 00000000000..9cbb2725132 --- /dev/null +++ b/release/scripts/freestyle/style_modules/sketchy_topology_broken.py @@ -0,0 +1,89 @@ +# +# Filename : sketchy_topology_broken.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The topology of the strokes is, first, built +# independantly from the 3D topology of objects, +# and, second, so as to chain several times the same ViewEdge. +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +## Backbone stretcher that leaves cusps intact to avoid cracks +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.getPoint() + p1 = v1.getPoint() + d1 = p0-p1 + d1.normalize() + newFirst = p0+d1*float(self._l) + v0.setPoint(newFirst) + else: + print "got a v0 cusp" + vn_1 = itn_1.getObject() + vn = itn.getObject() + if((vn.getNature() & Nature.CUSP == 0) and (vn_1.getNature() & Nature.CUSP == 0)): + pn = vn.getPoint() + pn_1 = vn_1.getPoint() + dn = pn-pn_1 + dn.normalize() + newLast = pn+dn*float(self._l) + vn.setPoint(newLast) + else: + print "got a vn cusp" + + +Operators.select(QuantitativeInvisibilityUP1D(0)) +## Chain 3 times each ViewEdge indpendantly from the +## initial objects topology +Operators.bidirectionalChain(pySketchyChainingIterator(3)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(6, 120, 2, 1, 1), + IncreasingThicknessShader(4, 10), + SmoothingShader(100, 0.1, 0, 0.2, 0, 0, 0, 1), + pyBackboneStretcherNoCuspShader(20), + #ConstantColorShader(0.0,0.0,0.0) + IncreasingColorShader(0.2,0.2,0.2,1,0.5,0.5,0.5,1), + #IncreasingColorShader(1,0,0,1,0,1,0,1), + TextureAssignerShader(4) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py new file mode 100755 index 00000000000..85e11af38b9 --- /dev/null +++ b/release/scripts/freestyle/style_modules/sketchy_topology_preserved.py @@ -0,0 +1,49 @@ +# +# Filename : sketchy_topology_preserved.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : The topology of the strokes is built +# so as to chain several times the same ViewEdge. +# The topology of the objects is preserved +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from PredicatesU1D import * +from shaders import * + +upred = QuantitativeInvisibilityUP1D(0) +Operators.select(upred) +Operators.bidirectionalChain(pySketchyChainSilhouetteIterator(3,1)) +shaders_list = [ + SamplingShader(4), + SpatialNoiseShader(20, 220, 2, 1, 1), + IncreasingThicknessShader(4, 8), + SmoothingShader(300, 0.05, 0, 0.2, 0, 0, 0, 0.5), + ConstantColorShader(0.6,0.2,0.0), + TextureAssignerShader(4), + ] + +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py new file mode 100755 index 00000000000..52cc10a9c60 --- /dev/null +++ b/release/scripts/freestyle/style_modules/split_at_highest_2d_curvatures.py @@ -0,0 +1,41 @@ +# +# Filename : split_at_highest_2d_curvature.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the visible lines (chaining follows same nature lines) +# (most basic style module) +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU0D import * +from PredicatesU1D import * +from Functions0D import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +func = pyInverseCurvature2DAngleF0D() +Operators.recursiveSplit(func, pyParameterUP0D(0.4,0.6), NotUP1D(pyHigherLengthUP1D(100)), 2) +shaders_list = [ConstantThicknessShader(10), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)] +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/split_at_tvertices.py b/release/scripts/freestyle/style_modules/split_at_tvertices.py new file mode 100755 index 00000000000..78f781dd290 --- /dev/null +++ b/release/scripts/freestyle/style_modules/split_at_tvertices.py @@ -0,0 +1,42 @@ +# +# Filename : split_at_tvertices.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws strokes that starts and stops at Tvertices (visible or not) +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from Functions0D import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +start = pyVertexNatureUP0D(Nature.T_VERTEX) +## use the same predicate to decide where to start and where to stop +## the strokes: +Operators.sequentialSplit(start, start, 10) +shaders_list = [ConstantThicknessShader(5), IncreasingColorShader(1,0,0,1,0,1,0,1), TextureAssignerShader(3)] +Operators.create(TrueUP1D(), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/stroke_texture.py b/release/scripts/freestyle/style_modules/stroke_texture.py new file mode 100755 index 00000000000..afebbe30a90 --- /dev/null +++ b/release/scripts/freestyle/style_modules/stroke_texture.py @@ -0,0 +1,43 @@ +# +# Filename : stroke_texture.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws textured strokes (illustrate the StrokeTextureShader shader) +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * +from ChainingIterators import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(3), + BezierCurveShader(4), + StrokeTextureShader("washbrushAlpha.bmp", Stroke.DRY_MEDIUM, 1), + ConstantThicknessShader(40), + ConstantColorShader(0,0,0,1), + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/suggestive.py b/release/scripts/freestyle/style_modules/suggestive.py new file mode 100755 index 00000000000..39d8515ed6c --- /dev/null +++ b/release/scripts/freestyle/style_modules/suggestive.py @@ -0,0 +1,43 @@ +# +# Filename : suggestive.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Draws the suggestive contours. +# ***** The suggestive contours must be enabled +# in the options dialog ***** +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from PredicatesU1D import * +from shaders import * + +upred = AndUP1D(pyNatureUP1D(Nature.SUGGESTIVE_CONTOUR), QuantitativeInvisibilityUP1D(0)) +Operators.select(upred) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(upred)) +shaders_list = [ + IncreasingThicknessShader(1, 3), + ConstantColorShader(0.2,0.2,0.2, 1) + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py new file mode 100755 index 00000000000..21f6c7bdf35 --- /dev/null +++ b/release/scripts/freestyle/style_modules/thickness_fof_depth_discontinuity.py @@ -0,0 +1,62 @@ +# +# Filename : thickness_fof_depth_discontinuity.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Assigns to strokes a thickness that depends on the depth discontinuity +# +############################################################################# +# +# 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. +# +############################################################################# + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +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().setThickness(thickness, thickness) + it.increment() + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(1), + ConstantThicknessShader(3), + ConstantColorShader(0.0,0.0,0.0), + pyDepthDiscontinuityThicknessShader(0.8, 6) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/tipremover.py b/release/scripts/freestyle/style_modules/tipremover.py new file mode 100755 index 00000000000..3e495b7d332 --- /dev/null +++ b/release/scripts/freestyle/style_modules/tipremover.py @@ -0,0 +1,42 @@ +# +# Filename : tipremover.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Removes strokes extremities +# +############################################################################# +# +# 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. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from ChainingIterators import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + SamplingShader(5), + ConstantThicknessShader(3), + ConstantColorShader(0,0,0), + TipRemoverShader(20) + ] +Operators.create(TrueUP1D(), shaders_list)
\ No newline at end of file diff --git a/release/scripts/freestyle/style_modules/tvertex_remover.py b/release/scripts/freestyle/style_modules/tvertex_remover.py new file mode 100755 index 00000000000..c328f4c98ec --- /dev/null +++ b/release/scripts/freestyle/style_modules/tvertex_remover.py @@ -0,0 +1,42 @@ +# +# Filename : tvertex_remover.py +# Author : Stephane Grabli +# Date : 04/08/2005 +# Purpose : Removes TVertices +# +############################################################################# +# +# 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. +# +############################################################################# + + +from freestyle_init import * +from logical_operators import * +from PredicatesB1D import * +from shaders import * + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator(), NotUP1D(QuantitativeInvisibilityUP1D(0))) +shaders_list = [ + IncreasingThicknessShader(3, 5), + ConstantColorShader(0.2,0.2,0.2, 1), + SamplingShader(10.0), + pyTVertexRemoverShader() + ] +Operators.create(TrueUP1D(), shaders_list) diff --git a/release/scripts/freestyle/style_modules/uniformpruning_zsort.py b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py new file mode 100755 index 00000000000..4b1a8bef9df --- /dev/null +++ b/release/scripts/freestyle/style_modules/uniformpruning_zsort.py @@ -0,0 +1,40 @@ +from freestyle_init import * +from logical_operators import * +from PredicatesU1D import * +from PredicatesU0D import * +from PredicatesB1D import * +from Functions0D import * +from Functions1D import * +from shaders import * + +class pyDensityUP1D(UnaryPredicate1D): + def __init__(self,wsize,threshold, integration = IntegrationType.MEAN, sampling=2.0): + UnaryPredicate1D.__init__(self) + self._wsize = wsize + self._threshold = threshold + self._integration = integration + self._func = DensityF1D(self._wsize, self._integration, sampling) + + def getName(self): + return "pyDensityUP1D" + + def __call__(self, inter): + d = self._func(inter) + print "For Chain ", inter.getId().getFirst(), inter.getId().getSecond(), "density is ", d + if(d < self._threshold): + return 1 + return 0 + +Operators.select(QuantitativeInvisibilityUP1D(0)) +Operators.bidirectionalChain(ChainSilhouetteIterator()) +#Operators.sequentialSplit(pyVertexNatureUP0D(Nature.VIEW_VERTEX), 2) +Operators.sort(pyZBP1D()) +shaders_list = [ + StrokeTextureShader("smoothAlpha.bmp", Stroke.OPAQUE_MEDIUM, 0), + ConstantThicknessShader(3), + SamplingShader(5.0), + ConstantColorShader(0,0,0,1) + ] +Operators.create(pyDensityUP1D(2,0.05, IntegrationType.MEAN,4), shaders_list) +#Operators.create(pyDensityFunctorUP1D(8,0.03, pyGetInverseProjectedZF1D(), 0,1, IntegrationType.MEAN), shaders_list) + diff --git a/release/scripts/freestyle/style_modules/vector.py b/release/scripts/freestyle/style_modules/vector.py new file mode 100755 index 00000000000..039f262546b --- /dev/null +++ b/release/scripts/freestyle/style_modules/vector.py @@ -0,0 +1,241 @@ +# This module defines 3d geometrical vectors with the standard +# operations on them. +# +# Written by: Konrad Hinsen +# Last revision: 1996-1-26 +# + +"""This module defines three-dimensional geometrical vectors. Vectors support +the usual mathematical operations (v1, v2: vectors, s: scalar): + v1+v2 addition + v1-v2 subtraction + v1*v2 scalar product + s*v1 multiplication with a scalar + v1/s division by a scalar + v1.cross(v2) cross product + v1.length() length + v1.normal() normal vector in direction of v1 + v1.angle(v2) angle between two vectors + v1.x(), v1[0] first element + v1.y(), v1[1] second element + v1.z(), v1[2] third element + +The module offers the following items for export: + Vec3D(x,y,z) the constructor for vectors + isVector(x) a type check function + ex, ey, ez unit vectors along the x-, y-, and z-axes (predefined constants) + +Note: vector elements can be any kind of numbers on which the operations +addition, subtraction, multiplication, division, comparison, sqrt, and acos +are defined. Integer elements are treated as floating point elements. +""" + +import math, types + +class Vec3: + + isVec3 = 1 + + def __init__(self, x=0., y=0., z=0.): + self.data = [x,y,z] + + def __repr__(self): + return 'Vec3(%s,%s,%s)' % (`self.data[0]`,\ + `self.data[1]`,`self.data[2]`) + + def __str__(self): + return `self.data` + + def __add__(self, other): + return Vec3(self.data[0]+other.data[0],\ + self.data[1]+other.data[1],self.data[2]+other.data[2]) + __radd__ = __add__ + + def __neg__(self): + return Vec3(-self.data[0], -self.data[1], -self.data[2]) + + def __sub__(self, other): + return Vec3(self.data[0]-other.data[0],\ + self.data[1]-other.data[1],self.data[2]-other.data[2]) + + def __rsub__(self, other): + return Vec3(other.data[0]-self.data[0],\ + other.data[1]-self.data[1],other.data[2]-self.data[2]) + + def __mul__(self, other): + if isVec3(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec3(self.data[0]*other, self.data[1]*other, + self.data[2]*other) + + def __rmul__(self, other): + if isVec3(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec3(other*self.data[0], other*self.data[1], + other*self.data[2]) + + def __div__(self, other): + if isVec3(other): + raise TypeError, "Can't divide by a vector" + else: + return Vec3(_div(self.data[0],other), _div(self.data[1],other), + _div(self.data[2],other)) + + def __rdiv__(self, other): + raise TypeError, "Can't divide by a vector" + + def __cmp__(self, other): + return cmp(self.data[0],other.data[0]) \ + or cmp(self.data[1],other.data[1]) \ + or cmp(self.data[2],other.data[2]) + + def __getitem__(self, index): + return self.data[index] + + def x(self): + return self.data[0] + def y(self): + return self.data[1] + def z(self): + return self.data[2] + + def length(self): + return math.sqrt(self*self) + + def normal(self): + len = self.length() + if len == 0: + raise ZeroDivisionError, "Can't normalize a zero-length vector" + return self/len + + def cross(self, other): + if not isVec3(other): + raise TypeError, "Cross product with non-vector" + return Vec3(self.data[1]*other.data[2]-self.data[2]*other.data[1], + self.data[2]*other.data[0]-self.data[0]*other.data[2], + self.data[0]*other.data[1]-self.data[1]*other.data[0]) + + def angle(self, other): + if not isVec3(other): + raise TypeError, "Angle between vector and non-vector" + cosa = (self*other)/(self.length()*other.length()) + cosa = max(-1.,min(1.,cosa)) + return math.acos(cosa) + + +class Vec2: + + isVec2 = 1 + + def __init__(self, x=0., y=0.): + self.data = [x,y] + + def __repr__(self): + return 'Vec2(%s,%s,%s)' % (`self.data[0]`,\ + `self.data[1]`) + + def __str__(self): + return `self.data` + + def __add__(self, other): + return Vec2(self.data[0]+other.data[0],\ + self.data[1]+other.data[1]) + __radd__ = __add__ + + def __neg__(self): + return Vec2(-self.data[0], -self.data[1]) + + def __sub__(self, other): + return Vec2(self.data[0]-other.data[0],\ + self.data[1]-other.data[1]) + + def __rsub__(self, other): + return Vec2(other.data[0]-self.data[0],\ + other.data[1]-self.data[1]) + + def __mul__(self, other): + if isVec2(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec2(self.data[0]*other, self.data[1]*other) + + def __rmul__(self, other): + if isVec2(other): + return reduce(lambda a,b: a+b, + map(lambda a,b: a*b, self.data, other.data)) + else: + return Vec2(other*self.data[0], other*self.data[1]) + + def __div__(self, other): + if isVec2(other): + raise TypeError, "Can't divide by a vector" + else: + return Vec2(_div(self.data[0],other), _div(self.data[1],other)) + + def __rdiv__(self, other): + raise TypeError, "Can't divide by a vector" + + def __cmp__(self, other): + return cmp(self.data[0],other.data[0]) \ + or cmp(self.data[1],other.data[1]) + + def __getitem__(self, index): + return self.data[index] + + def x(self): + return self.data[0] + def y(self): + return self.data[1] + + def length(self): + return math.sqrt(self*self) + + def normal(self): + len = self.length() + if len == 0: + raise ZeroDivisionError, "Can't normalize a zero-length vector" + return self/len + + #def cross(self, other): +# if not isVec2(other): +# raise TypeError, "Cross product with non-vector" +# return Vec2(self.data[1]*other.data[2]-self.data[2]*other.data[1], +# self.data[2]*other.data[0]-self.data[0]*other.data[2], +# self.data[0]*other.data[1]-self.data[1]*other.data[0]) + + def angle(self, other): + if not isVec2(other): + raise TypeError, "Angle between vector and non-vector" + cosa = (self*other)/(self.length()*other.length()) + cosa = max(-1.,min(1.,cosa)) + return math.acos(cosa) + + + +# Type check + +def isVec3(x): + return hasattr(x,'isVec3') + +def isVec2(x): + return hasattr(x,'isVec2') + +# "Correct" division for arbitrary number types + +def _div(a,b): + if type(a) == types.IntType and type(b) == types.IntType: + return float(a)/float(b) + else: + return a/b + + +# Some useful constants + +ex = Vec3(1.,0.,0.) +ey = Vec3(0.,1.,0.) +ez = Vec3(0.,0.,1.) |