Reorganized the Freestyle Python API in a hierarchical package structure.
Both C- and Python-coded API components were rearranged into logical groups. New Python modules are packaged as follows: freestyle - Top-level package freestyle.types - Classes for core data structues (e.g., view map) freestyle.chainingiterators - Pre-defined chaining iterators freestyle.functions - Pre-defined 0D and 1D functions freestyle.predicates - Pre-defined 0D and 1D predicates freestyle.shaders - Pre-defined stroke shaders freestyle.utils - Utility functions The Python modules are installed in scripts/freestyle/modules. Pre-defined styles are installed in scripts/freestyle/styles. To-do: update styles according to the new Freestyle API package structure.
This commit is contained in:
21
release/scripts/freestyle/modules/freestyle/__init__.py
Normal file
21
release/scripts/freestyle/modules/freestyle/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# module members
|
||||||
|
from _freestyle import Operators
|
||||||
|
from . import chainingiterators, functions, predicates, types, utils
|
716
release/scripts/freestyle/modules/freestyle/chainingiterators.py
Normal file
716
release/scripts/freestyle/modules/freestyle/chainingiterators.py
Normal file
@@ -0,0 +1,716 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# module members
|
||||||
|
from _freestyle import (
|
||||||
|
ChainPredicateIterator,
|
||||||
|
ChainSilhouetteIterator,
|
||||||
|
)
|
||||||
|
|
||||||
|
# modules for implementing chaining iterators
|
||||||
|
from freestyle.types import (
|
||||||
|
AdjacencyIterator,
|
||||||
|
ChainingIterator,
|
||||||
|
)
|
||||||
|
from freestyle.utils import ContextFunctions as CF
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
## 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=True):
|
||||||
|
ChainingIterator.__init__(self, stayInSelection, True, None, True)
|
||||||
|
def init(self):
|
||||||
|
pass
|
||||||
|
def traverse(self, iter):
|
||||||
|
winner = None
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
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.current_edge.nature
|
||||||
|
if (natures[i] & currentNature) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
visitNext = 0
|
||||||
|
oNature = it.object.nature
|
||||||
|
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.object
|
||||||
|
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=True, stayInUnvisited=True):
|
||||||
|
ChainingIterator.__init__(self, stayInSelection, stayInUnvisited, None, True)
|
||||||
|
def init(self):
|
||||||
|
pass
|
||||||
|
def traverse(self, iter):
|
||||||
|
winner = None
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
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.current_edge.nature
|
||||||
|
if (natures[i] & currentNature) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
visitNext = 0
|
||||||
|
oNature = it.object.nature
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == self.current_edge.id:
|
||||||
|
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, False, True, None, True)
|
||||||
|
self._isExternalContour = ExternalContourUP1D()
|
||||||
|
def init(self):
|
||||||
|
self._nEdges = 0
|
||||||
|
self._isInSelection = 1
|
||||||
|
def checkViewEdge(self, ve, orientation):
|
||||||
|
if orientation != 0:
|
||||||
|
vertex = ve.second_svertex()
|
||||||
|
else:
|
||||||
|
vertex = ve.first_svertex()
|
||||||
|
it = AdjacencyIterator(vertex,1,1)
|
||||||
|
while not it.is_end:
|
||||||
|
ave = it.object
|
||||||
|
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 not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if self._isExternalContour(ve):
|
||||||
|
if ve.time_stamp == CF.get_time_stamp():
|
||||||
|
winner = ve
|
||||||
|
it.increment()
|
||||||
|
|
||||||
|
self._nEdges = self._nEdges+1
|
||||||
|
if winner is None:
|
||||||
|
orient = 1
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if it.is_incoming:
|
||||||
|
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=True):
|
||||||
|
ChainingIterator.__init__(self, stayInSelection, False, None, True)
|
||||||
|
self._timeStamp = CF.get_time_stamp()+nRounds
|
||||||
|
self._nRounds = nRounds
|
||||||
|
def init(self):
|
||||||
|
self._timeStamp = CF.get_time_stamp()+self._nRounds
|
||||||
|
def traverse(self, iter):
|
||||||
|
winner = None
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
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.current_edge.nature
|
||||||
|
if (natures[i] & currentNature) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
visitNext = 0
|
||||||
|
oNature = it.object.nature
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == self.current_edge.id:
|
||||||
|
it.increment()
|
||||||
|
continue
|
||||||
|
if (oNature & natures[i]) != 0:
|
||||||
|
if (natures[i] != oNature) != 0:
|
||||||
|
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 is None:
|
||||||
|
winner = self.current_edge
|
||||||
|
if winner.chaining_time_stamp == 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=True):
|
||||||
|
ChainingIterator.__init__(self, stayInSelection, False, None, True)
|
||||||
|
self._timeStamp = CF.get_time_stamp()+nRounds
|
||||||
|
self._nRounds = nRounds
|
||||||
|
def init(self):
|
||||||
|
self._timeStamp = CF.get_time_stamp()+self._nRounds
|
||||||
|
def traverse(self, iter):
|
||||||
|
winner = None
|
||||||
|
found = False
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == self.current_edge.id:
|
||||||
|
found = True
|
||||||
|
it.increment()
|
||||||
|
continue
|
||||||
|
winner = ve
|
||||||
|
it.increment()
|
||||||
|
if not found:
|
||||||
|
# This is a fatal error condition: self.current_edge must be found
|
||||||
|
# among the edges seen by the AdjacencyIterator [bug #35695].
|
||||||
|
if bpy.app.debug_freestyle:
|
||||||
|
print('pySketchyChainingIterator: current edge not found')
|
||||||
|
return None
|
||||||
|
if winner is None:
|
||||||
|
winner = self.current_edge
|
||||||
|
if winner.chaining_time_stamp == 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, False, True, None, True)
|
||||||
|
self._length = 0
|
||||||
|
self._percent = float(percent)
|
||||||
|
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.current_edge.id.first, self.current_edge.id.second)
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
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.current_edge.nature & nat) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if (ve.nature & nat) != 0:
|
||||||
|
count = count+1
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
winnerOrientation = 1
|
||||||
|
else:
|
||||||
|
winnerOrientation = 0
|
||||||
|
it.increment()
|
||||||
|
if count != 1:
|
||||||
|
winner = None
|
||||||
|
break
|
||||||
|
if winner is not None:
|
||||||
|
# check whether this edge was part of the selection
|
||||||
|
if winner.time_stamp != CF.get_time_stamp():
|
||||||
|
#print("---", winner.id.first, winner.id.second)
|
||||||
|
# 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.begin = winner
|
||||||
|
_it.current_edge = winner
|
||||||
|
_it.orientation = winnerOrientation
|
||||||
|
_it.init()
|
||||||
|
while not _it.is_end:
|
||||||
|
ve = _it.object
|
||||||
|
#print("--------", ve.id.first, ve.id.second)
|
||||||
|
self._length = self._length + ve.length_2d
|
||||||
|
_it.increment()
|
||||||
|
if _it.is_begin:
|
||||||
|
break;
|
||||||
|
_it.begin = winner
|
||||||
|
_it.current_edge = winner
|
||||||
|
_it.orientation = winnerOrientation
|
||||||
|
if not _it.is_begin:
|
||||||
|
_it.decrement()
|
||||||
|
while (not _it.is_end) and (not _it.is_begin):
|
||||||
|
ve = _it.object
|
||||||
|
#print("--------", ve.id.first, ve.id.second)
|
||||||
|
self._length = self._length + ve.length_2d
|
||||||
|
_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.begin = winner
|
||||||
|
_cit.current_edge = winner
|
||||||
|
_cit.orientation = winnerOrientation
|
||||||
|
_cit.init()
|
||||||
|
while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
|
||||||
|
ve = _cit.object
|
||||||
|
#print("-------- --------", ve.id.first, ve.id.second)
|
||||||
|
connexl = connexl + ve.length_2d
|
||||||
|
_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, False, True, None, True)
|
||||||
|
self._length = float(length)
|
||||||
|
def init(self):
|
||||||
|
pass
|
||||||
|
def traverse(self, iter):
|
||||||
|
winner = None
|
||||||
|
winnerOrientation = 0
|
||||||
|
#print(self.current_edge.id.first, self.current_edge.id.second)
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
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.current_edge.nature & nat) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if (ve.nature & nat) != 0:
|
||||||
|
count = count+1
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
winnerOrientation = 1
|
||||||
|
else:
|
||||||
|
winnerOrientation = 0
|
||||||
|
it.increment()
|
||||||
|
if count != 1:
|
||||||
|
winner = None
|
||||||
|
break
|
||||||
|
if winner is not None:
|
||||||
|
# check whether this edge was part of the selection
|
||||||
|
if winner.time_stamp != CF.get_time_stamp():
|
||||||
|
#print("---", winner.id.first, winner.id.second)
|
||||||
|
# nw let's compute the length of this connex non selected part:
|
||||||
|
connexl = 0
|
||||||
|
_cit = pyChainSilhouetteGenericIterator(0,0)
|
||||||
|
_cit.begin = winner
|
||||||
|
_cit.current_edge = winner
|
||||||
|
_cit.orientation = winnerOrientation
|
||||||
|
_cit.init()
|
||||||
|
while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
|
||||||
|
ve = _cit.object
|
||||||
|
#print("-------- --------", ve.id.first, ve.id.second)
|
||||||
|
connexl = connexl + ve.length_2d
|
||||||
|
_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, False, True, None, True)
|
||||||
|
self._length = 0
|
||||||
|
self._absLength = l
|
||||||
|
self._percent = float(percent)
|
||||||
|
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.current_edge.id.first, self.current_edge.id.second)
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
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.current_edge.nature & nat) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if (ve.nature & nat) != 0:
|
||||||
|
count = count+1
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
winnerOrientation = 1
|
||||||
|
else:
|
||||||
|
winnerOrientation = 0
|
||||||
|
it.increment()
|
||||||
|
if count != 1:
|
||||||
|
winner = None
|
||||||
|
break
|
||||||
|
if winner is not None:
|
||||||
|
# check whether this edge was part of the selection
|
||||||
|
if winner.time_stamp != CF.get_time_stamp():
|
||||||
|
#print("---", winner.id.first, winner.id.second)
|
||||||
|
# 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.begin = winner
|
||||||
|
_it.current_edge = winner
|
||||||
|
_it.orientation = winnerOrientation
|
||||||
|
_it.init()
|
||||||
|
while not _it.is_end:
|
||||||
|
ve = _it.object
|
||||||
|
#print("--------", ve.id.first, ve.id.second)
|
||||||
|
self._length = self._length + ve.length_2d
|
||||||
|
_it.increment()
|
||||||
|
if _it.is_begin:
|
||||||
|
break;
|
||||||
|
_it.begin = winner
|
||||||
|
_it.current_edge = winner
|
||||||
|
_it.orientation = winnerOrientation
|
||||||
|
if not _it.is_begin:
|
||||||
|
_it.decrement()
|
||||||
|
while (not _it.is_end) and (not _it.is_begin):
|
||||||
|
ve = _it.object
|
||||||
|
#print("--------", ve.id.first, ve.id.second)
|
||||||
|
self._length = self._length + ve.length_2d
|
||||||
|
_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.begin = winner
|
||||||
|
_cit.current_edge = winner
|
||||||
|
_cit.orientation = winnerOrientation
|
||||||
|
_cit.init()
|
||||||
|
while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
|
||||||
|
ve = _cit.object
|
||||||
|
#print("-------- --------", ve.id.first, ve.id.second)
|
||||||
|
connexl = connexl + ve.length_2d
|
||||||
|
_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, False, True, None, True)
|
||||||
|
self._length = 0
|
||||||
|
self._absLength = l
|
||||||
|
self._percent = float(percent)
|
||||||
|
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.current_edge.id.first, self.current_edge.id.second)
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if ve.id == mateVE.id:
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
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.current_edge.nature & nat) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
if (ve.nature & nat) != 0:
|
||||||
|
count = count+1
|
||||||
|
winner = ve
|
||||||
|
if not it.is_incoming:
|
||||||
|
winnerOrientation = 1
|
||||||
|
else:
|
||||||
|
winnerOrientation = 0
|
||||||
|
it.increment()
|
||||||
|
if count != 1:
|
||||||
|
winner = None
|
||||||
|
break
|
||||||
|
if winner is not None:
|
||||||
|
# check whether this edge was part of the selection
|
||||||
|
if winner.qi != 0:
|
||||||
|
#print("---", winner.id.first, winner.id.second)
|
||||||
|
# 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.begin = winner
|
||||||
|
_it.current_edge = winner
|
||||||
|
_it.orientation = winnerOrientation
|
||||||
|
_it.init()
|
||||||
|
while not _it.is_end:
|
||||||
|
ve = _it.object
|
||||||
|
#print("--------", ve.id.first, ve.id.second)
|
||||||
|
self._length = self._length + ve.length_2d
|
||||||
|
_it.increment()
|
||||||
|
if _it.is_begin:
|
||||||
|
break;
|
||||||
|
_it.begin = winner
|
||||||
|
_it.current_edge = winner
|
||||||
|
_it.orientation = winnerOrientation
|
||||||
|
if not _it.is_begin:
|
||||||
|
_it.decrement()
|
||||||
|
while (not _it.is_end) and (not _it.is_begin):
|
||||||
|
ve = _it.object
|
||||||
|
#print("--------", ve.id.first, ve.id.second)
|
||||||
|
self._length = self._length + ve.length_2d
|
||||||
|
_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.begin = winner
|
||||||
|
_cit.current_edge = winner
|
||||||
|
_cit.orientation = winnerOrientation
|
||||||
|
_cit.init()
|
||||||
|
while not _cit.is_end and _cit.object.qi != 0:
|
||||||
|
ve = _cit.object
|
||||||
|
#print("-------- --------", ve.id.first, ve.id.second)
|
||||||
|
connexl = connexl + ve.length_2d
|
||||||
|
_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=True):
|
||||||
|
ChainingIterator.__init__(self, stayInSelection, True, None, True)
|
||||||
|
def init(self):
|
||||||
|
pass
|
||||||
|
def traverse(self, iter):
|
||||||
|
winner = None
|
||||||
|
it = AdjacencyIterator(iter)
|
||||||
|
tvertex = self.next_vertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
mateVE = tvertex.get_mate(self.current_edge)
|
||||||
|
while not it.is_end:
|
||||||
|
ve = it.object
|
||||||
|
feB = self.current_edge.last_fedge
|
||||||
|
feA = ve.first_fedge
|
||||||
|
vB = feB.second_svertex
|
||||||
|
vA = feA.first_svertex
|
||||||
|
if vA.id.first == vB.id.first:
|
||||||
|
winner = ve
|
||||||
|
break
|
||||||
|
feA = self.current_edge.first_fedge
|
||||||
|
feB = ve.last_fedge
|
||||||
|
vB = feB.second_svertex
|
||||||
|
vA = feA.first_svertex
|
||||||
|
if vA.id.first == vB.id.first:
|
||||||
|
winner = ve
|
||||||
|
break
|
||||||
|
feA = self.current_edge.last_fedge
|
||||||
|
feB = ve.last_fedge
|
||||||
|
vB = feB.second_svertex
|
||||||
|
vA = feA.second_svertex
|
||||||
|
if vA.id.first == vB.id.first:
|
||||||
|
winner = ve
|
||||||
|
break
|
||||||
|
feA = self.current_edge.first_fedge
|
||||||
|
feB = ve.first_fedge
|
||||||
|
vB = feB.first_svertex
|
||||||
|
vA = feA.first_svertex
|
||||||
|
if vA.id.first == vB.id.first:
|
||||||
|
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.current_edge.nature
|
||||||
|
if (natures[i] & currentNature) != 0:
|
||||||
|
count=0
|
||||||
|
while not it.is_end:
|
||||||
|
visitNext = 0
|
||||||
|
oNature = it.object.nature
|
||||||
|
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.object
|
||||||
|
it.increment()
|
||||||
|
if count != 1:
|
||||||
|
winner = None
|
||||||
|
break
|
||||||
|
return winner
|
197
release/scripts/freestyle/modules/freestyle/functions.py
Normal file
197
release/scripts/freestyle/modules/freestyle/functions.py
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# module members
|
||||||
|
from _freestyle import (
|
||||||
|
ChainingTimeStampF1D,
|
||||||
|
Curvature2DAngleF0D,
|
||||||
|
Curvature2DAngleF1D,
|
||||||
|
CurveNatureF0D,
|
||||||
|
CurveNatureF1D,
|
||||||
|
DensityF0D,
|
||||||
|
DensityF1D,
|
||||||
|
GetCompleteViewMapDensityF1D,
|
||||||
|
GetCurvilinearAbscissaF0D,
|
||||||
|
GetDirectionalViewMapDensityF1D,
|
||||||
|
GetOccludeeF0D,
|
||||||
|
GetOccludeeF1D,
|
||||||
|
GetOccludersF0D,
|
||||||
|
GetOccludersF1D,
|
||||||
|
GetParameterF0D,
|
||||||
|
GetProjectedXF0D,
|
||||||
|
GetProjectedXF1D,
|
||||||
|
GetProjectedYF0D,
|
||||||
|
GetProjectedYF1D,
|
||||||
|
GetProjectedZF0D,
|
||||||
|
GetProjectedZF1D,
|
||||||
|
GetShapeF0D,
|
||||||
|
GetShapeF1D,
|
||||||
|
GetSteerableViewMapDensityF1D,
|
||||||
|
GetViewMapGradientNormF0D,
|
||||||
|
GetViewMapGradientNormF1D,
|
||||||
|
GetXF0D,
|
||||||
|
GetXF1D,
|
||||||
|
GetYF0D,
|
||||||
|
GetYF1D,
|
||||||
|
GetZF0D,
|
||||||
|
GetZF1D,
|
||||||
|
IncrementChainingTimeStampF1D,
|
||||||
|
LocalAverageDepthF0D,
|
||||||
|
LocalAverageDepthF1D,
|
||||||
|
MaterialF0D,
|
||||||
|
Normal2DF0D,
|
||||||
|
Normal2DF1D,
|
||||||
|
Orientation2DF1D,
|
||||||
|
Orientation3DF1D,
|
||||||
|
QuantitativeInvisibilityF0D,
|
||||||
|
QuantitativeInvisibilityF1D,
|
||||||
|
ReadCompleteViewMapPixelF0D,
|
||||||
|
ReadMapPixelF0D,
|
||||||
|
ReadSteerableViewMapPixelF0D,
|
||||||
|
ShapeIdF0D,
|
||||||
|
TimeStampF1D,
|
||||||
|
VertexOrientation2DF0D,
|
||||||
|
VertexOrientation3DF0D,
|
||||||
|
ZDiscontinuityF0D,
|
||||||
|
ZDiscontinuityF1D,
|
||||||
|
)
|
||||||
|
|
||||||
|
# modules for implementing functions
|
||||||
|
from freestyle.types import (
|
||||||
|
IntegrationType,
|
||||||
|
UnaryFunction0DDouble,
|
||||||
|
UnaryFunction0DMaterial,
|
||||||
|
UnaryFunction0DVec2f,
|
||||||
|
UnaryFunction1DDouble,
|
||||||
|
)
|
||||||
|
from freestyle.utils import ContextFunctions as CF
|
||||||
|
import math
|
||||||
|
import mathutils
|
||||||
|
|
||||||
|
## Functions for 0D elements (vertices)
|
||||||
|
#######################################
|
||||||
|
|
||||||
|
class CurveMaterialF0D(UnaryFunction0DMaterial):
|
||||||
|
# A replacement of the built-in MaterialF0D for stroke creation.
|
||||||
|
# MaterialF0D does not work with Curves and Strokes.
|
||||||
|
def __call__(self, inter):
|
||||||
|
cp = inter.object
|
||||||
|
assert(isinstance(cp, CurvePoint))
|
||||||
|
fe = cp.first_svertex.get_fedge(cp.second_svertex)
|
||||||
|
assert(fe is not None)
|
||||||
|
return fe.material if fe.is_smooth else fe.material_left
|
||||||
|
|
||||||
|
class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
|
||||||
|
def __call__(self, inter):
|
||||||
|
func = Curvature2DAngleF0D()
|
||||||
|
c = func(inter)
|
||||||
|
return (3.1415 - c)
|
||||||
|
|
||||||
|
class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
|
||||||
|
def __call__(self, inter):
|
||||||
|
cp = inter.object
|
||||||
|
assert(isinstance(cp, CurvePoint))
|
||||||
|
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 __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 = math.pow(2,self._l)
|
||||||
|
def __call__(self, iter):
|
||||||
|
p = iter.object.point_2d
|
||||||
|
gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
|
||||||
|
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
||||||
|
gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
|
||||||
|
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
||||||
|
return mathutils.Vector([gx, gy])
|
||||||
|
|
||||||
|
class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
|
||||||
|
def __init__(self, l):
|
||||||
|
UnaryFunction0DDouble.__init__(self)
|
||||||
|
self._l = l
|
||||||
|
self._step = math.pow(2,self._l)
|
||||||
|
def __call__(self, iter):
|
||||||
|
p = iter.object.point_2d
|
||||||
|
gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
|
||||||
|
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
||||||
|
gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
|
||||||
|
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
||||||
|
grad = mathutils.Vector([gx, gy])
|
||||||
|
return grad.length
|
||||||
|
|
||||||
|
## Functions for 1D elements (curves)
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
class pyGetInverseProjectedZF1D(UnaryFunction1DDouble):
|
||||||
|
def __call__(self, inter):
|
||||||
|
func = GetProjectedZF1D()
|
||||||
|
z = func(inter)
|
||||||
|
return (1.0 - z)
|
||||||
|
|
||||||
|
class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
|
||||||
|
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 __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 __call__(self, inter):
|
||||||
|
v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
|
||||||
|
return v
|
516
release/scripts/freestyle/modules/freestyle/predicates.py
Normal file
516
release/scripts/freestyle/modules/freestyle/predicates.py
Normal file
@@ -0,0 +1,516 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# module members
|
||||||
|
from _freestyle import (
|
||||||
|
ContourUP1D,
|
||||||
|
DensityLowerThanUP1D,
|
||||||
|
EqualToChainingTimeStampUP1D,
|
||||||
|
EqualToTimeStampUP1D,
|
||||||
|
ExternalContourUP1D,
|
||||||
|
FalseBP1D,
|
||||||
|
FalseUP0D,
|
||||||
|
FalseUP1D,
|
||||||
|
Length2DBP1D,
|
||||||
|
QuantitativeInvisibilityUP1D,
|
||||||
|
SameShapeIdBP1D,
|
||||||
|
ShapeUP1D,
|
||||||
|
TrueBP1D,
|
||||||
|
TrueUP0D,
|
||||||
|
TrueUP1D,
|
||||||
|
ViewMapGradientNormBP1D,
|
||||||
|
WithinImageBoundaryUP1D,
|
||||||
|
)
|
||||||
|
|
||||||
|
# modules for implementing predicates
|
||||||
|
from freestyle.types import (
|
||||||
|
IntegrationType,
|
||||||
|
BinaryPredicate1D,
|
||||||
|
UnaryPredicate0D,
|
||||||
|
UnaryPredicate1D,
|
||||||
|
)
|
||||||
|
from freestyle.functions import (
|
||||||
|
pyCurvilinearLengthF0D,
|
||||||
|
pyDensityAnisotropyF1D,
|
||||||
|
pyViewMapGradientNormF1D,
|
||||||
|
)
|
||||||
|
import random
|
||||||
|
|
||||||
|
## Unary predicates for 0D elements (vertices)
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
|
||||||
|
def __init__(self,a):
|
||||||
|
UnaryPredicate0D.__init__(self)
|
||||||
|
self._a = a
|
||||||
|
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 __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 __call__(self, inter):
|
||||||
|
v = inter.object
|
||||||
|
return (v.nature & self._nature) != 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 __call__(self, iter):
|
||||||
|
if (iter.object.nature & Nature.T_VERTEX) == 0:
|
||||||
|
return 0
|
||||||
|
if iter.is_end:
|
||||||
|
return 0
|
||||||
|
if self._getQI(iter) != 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 __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 __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
|
||||||
|
|
||||||
|
## Unary predicates for 1D elements (curves)
|
||||||
|
############################################
|
||||||
|
|
||||||
|
class AndUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self, pred1, pred2):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self.__pred1 = pred1
|
||||||
|
self.__pred2 = pred2
|
||||||
|
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 __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 __call__(self, inter):
|
||||||
|
return not self.__pred(inter)
|
||||||
|
|
||||||
|
class pyNFirstUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self, n):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self.__n = n
|
||||||
|
self.__count = 0
|
||||||
|
def __call__(self, inter):
|
||||||
|
self.__count = self.__count + 1
|
||||||
|
if self.__count <= self.__n:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class pyHigherLengthUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self,l):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self._l = l
|
||||||
|
def __call__(self, inter):
|
||||||
|
return (inter.length_2d > self._l)
|
||||||
|
|
||||||
|
class pyNatureUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self,nature):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self._nature = nature
|
||||||
|
self._getNature = CurveNatureF1D()
|
||||||
|
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 __call__(self, inter):
|
||||||
|
count = 0
|
||||||
|
func = Curvature2DAngleF0D()
|
||||||
|
it = inter.vertices_begin()
|
||||||
|
while not it.is_end:
|
||||||
|
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 __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 __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 __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 __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 __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 __call__(self, inter):
|
||||||
|
#print("toto")
|
||||||
|
#print(func.name)
|
||||||
|
#print(inter.name)
|
||||||
|
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 __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 __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 __call__(self, inter):
|
||||||
|
func = GetShapeF1D()
|
||||||
|
shapes = func(inter)
|
||||||
|
for s in shapes:
|
||||||
|
if(s.id == self._id):
|
||||||
|
return 0
|
||||||
|
it = inter.vertices_begin()
|
||||||
|
itlast = inter.vertices_end()
|
||||||
|
itlast.decrement()
|
||||||
|
v = it.object
|
||||||
|
vlast = itlast.object
|
||||||
|
tvertex = v.viewvertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
#print("TVertex: [ ", tvertex.id.first, ",", tvertex.id.second," ]")
|
||||||
|
eit = tvertex.edges_begin()
|
||||||
|
while not eit.is_end:
|
||||||
|
ve, incoming = eit.object
|
||||||
|
if ve.id == self._id:
|
||||||
|
return 1
|
||||||
|
#print("-------", ve.id.first, "-", ve.id.second)
|
||||||
|
eit.increment()
|
||||||
|
tvertex = vlast.viewvertex
|
||||||
|
if type(tvertex) is TVertex:
|
||||||
|
#print("TVertex: [ ", tvertex.id.first, ",", tvertex.id.second," ]")
|
||||||
|
eit = tvertex.edges_begin()
|
||||||
|
while not eit.is_end:
|
||||||
|
ve, incoming = eit.object
|
||||||
|
if ve.id == self._id:
|
||||||
|
return 1
|
||||||
|
#print("-------", ve.id.first, "-", ve.id.second)
|
||||||
|
eit.increment()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class pyIsInOccludersListUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self,id):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self._id = id
|
||||||
|
def __call__(self, inter):
|
||||||
|
func = GetOccludersF1D()
|
||||||
|
occluders = func(inter)
|
||||||
|
for a in occluders:
|
||||||
|
if a.id == self._id:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class pyIsOccludedByItselfUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self.__func1 = GetOccludersF1D()
|
||||||
|
self.__func2 = GetShapeF1D()
|
||||||
|
def __call__(self, inter):
|
||||||
|
lst1 = self.__func1(inter)
|
||||||
|
lst2 = self.__func2(inter)
|
||||||
|
for vs1 in lst1:
|
||||||
|
for vs2 in lst2:
|
||||||
|
if vs1.id == vs2.id:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
|
||||||
|
def __init__(self, idlist):
|
||||||
|
UnaryPredicate1D.__init__(self)
|
||||||
|
self._idlist = idlist
|
||||||
|
self.__func1 = GetOccludersF1D()
|
||||||
|
def __call__(self, inter):
|
||||||
|
lst1 = self.__func1(inter)
|
||||||
|
for vs1 in lst1:
|
||||||
|
for _id in self._idlist:
|
||||||
|
if vs1.id == _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.first, _id.second))
|
||||||
|
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 __call__(self, inter):
|
||||||
|
func = GetShapeF1D()
|
||||||
|
shapes = func(inter)
|
||||||
|
for a in shapes:
|
||||||
|
if a.id == 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 __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 __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 __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.vertices_begin()
|
||||||
|
itlast = inter.vertices_end()
|
||||||
|
itlast.decrement()
|
||||||
|
vlast = itlast.object
|
||||||
|
v = it.object
|
||||||
|
#print(v.id.first, v.id.second)
|
||||||
|
#print(vlast.id.first, vlast.id.second)
|
||||||
|
if v.id == vlast.id:
|
||||||
|
return 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
## Binary predicates for 1D elements (curves)
|
||||||
|
#############################################
|
||||||
|
|
||||||
|
class pyZBP1D(BinaryPredicate1D):
|
||||||
|
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 __call__(self, i1, i2):
|
||||||
|
return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2))
|
||||||
|
|
||||||
|
class pyLengthBP1D(BinaryPredicate1D):
|
||||||
|
def __call__(self, i1, i2):
|
||||||
|
return (i1.length_2d > i2.length_2d)
|
||||||
|
|
||||||
|
class pySilhouetteFirstBP1D(BinaryPredicate1D):
|
||||||
|
def __call__(self, inter1, inter2):
|
||||||
|
bpred = SameShapeIdBP1D()
|
||||||
|
if (bpred(inter1, inter2) != 1):
|
||||||
|
return 0
|
||||||
|
if (inter1.nature & Nature.SILHOUETTE):
|
||||||
|
return (inter2.nature & Nature.SILHOUETTE) != 0
|
||||||
|
return (inter1.nature == inter2.nature)
|
||||||
|
|
||||||
|
class pyNatureBP1D(BinaryPredicate1D):
|
||||||
|
def __call__(self, inter1, inter2):
|
||||||
|
return (inter1.nature & inter2.nature)
|
||||||
|
|
||||||
|
class pyViewMapGradientNormBP1D(BinaryPredicate1D):
|
||||||
|
def __init__(self,l, sampling=2.0):
|
||||||
|
BinaryPredicate1D.__init__(self)
|
||||||
|
self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
|
||||||
|
def __call__(self, i1,i2):
|
||||||
|
#print("compare gradient")
|
||||||
|
return (self._GetGradient(i1) > self._GetGradient(i2))
|
||||||
|
|
||||||
|
class pyShuffleBP1D(BinaryPredicate1D):
|
||||||
|
def __init__(self):
|
||||||
|
BinaryPredicate1D.__init__(self)
|
||||||
|
random.seed(1)
|
||||||
|
def __call__(self, inter1, inter2):
|
||||||
|
r1 = random.uniform(0,1)
|
||||||
|
r2 = random.uniform(0,1)
|
||||||
|
return (r1<r2)
|
1249
release/scripts/freestyle/modules/freestyle/shaders.py
Normal file
1249
release/scripts/freestyle/modules/freestyle/shaders.py
Normal file
File diff suppressed because it is too large
Load Diff
81
release/scripts/freestyle/modules/freestyle/types.py
Normal file
81
release/scripts/freestyle/modules/freestyle/types.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# module members
|
||||||
|
from _freestyle import (
|
||||||
|
AdjacencyIterator,
|
||||||
|
BBox,
|
||||||
|
BinaryPredicate0D,
|
||||||
|
BinaryPredicate1D,
|
||||||
|
Chain,
|
||||||
|
ChainingIterator,
|
||||||
|
Curve,
|
||||||
|
CurvePoint,
|
||||||
|
CurvePointIterator,
|
||||||
|
FEdge,
|
||||||
|
FEdgeSharp,
|
||||||
|
FEdgeSmooth,
|
||||||
|
Id,
|
||||||
|
IntegrationType,
|
||||||
|
Interface0D,
|
||||||
|
Interface0DIterator,
|
||||||
|
Interface1D,
|
||||||
|
Iterator,
|
||||||
|
Material,
|
||||||
|
MediumType,
|
||||||
|
Nature,
|
||||||
|
Noise,
|
||||||
|
NonTVertex,
|
||||||
|
SShape,
|
||||||
|
SVertex,
|
||||||
|
SVertexIterator,
|
||||||
|
Stroke,
|
||||||
|
StrokeShader,
|
||||||
|
StrokeAttribute,
|
||||||
|
StrokeVertex,
|
||||||
|
StrokeVertexIterator,
|
||||||
|
TVertex,
|
||||||
|
UnaryFunction0D,
|
||||||
|
UnaryFunction0DDouble,
|
||||||
|
UnaryFunction0DEdgeNature,
|
||||||
|
UnaryFunction0DFloat,
|
||||||
|
UnaryFunction0DId,
|
||||||
|
UnaryFunction0DMaterial,
|
||||||
|
UnaryFunction0DUnsigned,
|
||||||
|
UnaryFunction0DVec2f,
|
||||||
|
UnaryFunction0DVec3f,
|
||||||
|
UnaryFunction0DVectorViewShape,
|
||||||
|
UnaryFunction0DViewShape,
|
||||||
|
UnaryFunction1D,
|
||||||
|
UnaryFunction1DDouble,
|
||||||
|
UnaryFunction1DEdgeNature,
|
||||||
|
UnaryFunction1DFloat,
|
||||||
|
UnaryFunction1DUnsigned,
|
||||||
|
UnaryFunction1DVec2f,
|
||||||
|
UnaryFunction1DVec3f,
|
||||||
|
UnaryFunction1DVectorViewShape,
|
||||||
|
UnaryFunction1DVoid,
|
||||||
|
UnaryPredicate0D,
|
||||||
|
UnaryPredicate1D,
|
||||||
|
ViewEdge,
|
||||||
|
ViewEdgeIterator,
|
||||||
|
ViewMap,
|
||||||
|
ViewShape,
|
||||||
|
ViewVertex,
|
||||||
|
orientedViewEdgeIterator,
|
||||||
|
)
|
24
release/scripts/freestyle/modules/freestyle/utils.py
Normal file
24
release/scripts/freestyle/modules/freestyle/utils.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
# module members
|
||||||
|
from _freestyle import (
|
||||||
|
ContextFunctions,
|
||||||
|
getCurrentScene,
|
||||||
|
integrate,
|
||||||
|
)
|
@@ -26,6 +26,8 @@ import math
|
|||||||
import mathutils
|
import mathutils
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from _freestyle import blendRamp, evaluateColorRamp, evaluateCurveMappingF
|
||||||
|
|
||||||
from ChainingIterators import pySketchyChainSilhouetteIterator, pySketchyChainingIterator
|
from ChainingIterators import pySketchyChainSilhouetteIterator, pySketchyChainingIterator
|
||||||
from freestyle import BackboneStretcherShader, BezierCurveShader, BinaryPredicate1D, ChainPredicateIterator, \
|
from freestyle import BackboneStretcherShader, BezierCurveShader, BinaryPredicate1D, ChainPredicateIterator, \
|
||||||
ChainSilhouetteIterator, ConstantColorShader, ContourUP1D, Curvature2DAngleF0D, ExternalContourUP1D, \
|
ChainSilhouetteIterator, ConstantColorShader, ContourUP1D, Curvature2DAngleF0D, ExternalContourUP1D, \
|
@@ -1,713 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : ChainingIterators.py
|
|
||||||
# Author : Stephane Grabli
|
|
||||||
# Date : 04/08/2005
|
|
||||||
# Purpose : Chaining Iterators to be used with chaining operators
|
|
||||||
|
|
||||||
from freestyle import AdjacencyIterator, ChainingIterator, ExternalContourUP1D, Nature, TVertex
|
|
||||||
from freestyle import ContextFunctions as CF
|
|
||||||
|
|
||||||
import bpy
|
|
||||||
|
|
||||||
## 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=True):
|
|
||||||
ChainingIterator.__init__(self, stayInSelection, True, None, True)
|
|
||||||
def init(self):
|
|
||||||
pass
|
|
||||||
def traverse(self, iter):
|
|
||||||
winner = None
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
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.current_edge.nature
|
|
||||||
if (natures[i] & currentNature) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
visitNext = 0
|
|
||||||
oNature = it.object.nature
|
|
||||||
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.object
|
|
||||||
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=True, stayInUnvisited=True):
|
|
||||||
ChainingIterator.__init__(self, stayInSelection, stayInUnvisited, None, True)
|
|
||||||
def init(self):
|
|
||||||
pass
|
|
||||||
def traverse(self, iter):
|
|
||||||
winner = None
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
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.current_edge.nature
|
|
||||||
if (natures[i] & currentNature) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
visitNext = 0
|
|
||||||
oNature = it.object.nature
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == self.current_edge.id:
|
|
||||||
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, False, True, None, True)
|
|
||||||
self._isExternalContour = ExternalContourUP1D()
|
|
||||||
def init(self):
|
|
||||||
self._nEdges = 0
|
|
||||||
self._isInSelection = 1
|
|
||||||
def checkViewEdge(self, ve, orientation):
|
|
||||||
if orientation != 0:
|
|
||||||
vertex = ve.second_svertex()
|
|
||||||
else:
|
|
||||||
vertex = ve.first_svertex()
|
|
||||||
it = AdjacencyIterator(vertex,1,1)
|
|
||||||
while not it.is_end:
|
|
||||||
ave = it.object
|
|
||||||
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 not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if self._isExternalContour(ve):
|
|
||||||
if ve.time_stamp == CF.get_time_stamp():
|
|
||||||
winner = ve
|
|
||||||
it.increment()
|
|
||||||
|
|
||||||
self._nEdges = self._nEdges+1
|
|
||||||
if winner is None:
|
|
||||||
orient = 1
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if it.is_incoming:
|
|
||||||
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=True):
|
|
||||||
ChainingIterator.__init__(self, stayInSelection, False, None, True)
|
|
||||||
self._timeStamp = CF.get_time_stamp()+nRounds
|
|
||||||
self._nRounds = nRounds
|
|
||||||
def init(self):
|
|
||||||
self._timeStamp = CF.get_time_stamp()+self._nRounds
|
|
||||||
def traverse(self, iter):
|
|
||||||
winner = None
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
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.current_edge.nature
|
|
||||||
if (natures[i] & currentNature) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
visitNext = 0
|
|
||||||
oNature = it.object.nature
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == self.current_edge.id:
|
|
||||||
it.increment()
|
|
||||||
continue
|
|
||||||
if (oNature & natures[i]) != 0:
|
|
||||||
if (natures[i] != oNature) != 0:
|
|
||||||
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 is None:
|
|
||||||
winner = self.current_edge
|
|
||||||
if winner.chaining_time_stamp == 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=True):
|
|
||||||
ChainingIterator.__init__(self, stayInSelection, False, None, True)
|
|
||||||
self._timeStamp = CF.get_time_stamp()+nRounds
|
|
||||||
self._nRounds = nRounds
|
|
||||||
def init(self):
|
|
||||||
self._timeStamp = CF.get_time_stamp()+self._nRounds
|
|
||||||
def traverse(self, iter):
|
|
||||||
winner = None
|
|
||||||
found = False
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == self.current_edge.id:
|
|
||||||
found = True
|
|
||||||
it.increment()
|
|
||||||
continue
|
|
||||||
winner = ve
|
|
||||||
it.increment()
|
|
||||||
if not found:
|
|
||||||
# This is a fatal error condition: self.current_edge must be found
|
|
||||||
# among the edges seen by the AdjacencyIterator [bug #35695].
|
|
||||||
if bpy.app.debug_freestyle:
|
|
||||||
print('pySketchyChainingIterator: current edge not found')
|
|
||||||
return None
|
|
||||||
if winner is None:
|
|
||||||
winner = self.current_edge
|
|
||||||
if winner.chaining_time_stamp == 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, False, True, None, True)
|
|
||||||
self._length = 0
|
|
||||||
self._percent = float(percent)
|
|
||||||
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.current_edge.id.first, self.current_edge.id.second)
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
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.current_edge.nature & nat) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if (ve.nature & nat) != 0:
|
|
||||||
count = count+1
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
winnerOrientation = 1
|
|
||||||
else:
|
|
||||||
winnerOrientation = 0
|
|
||||||
it.increment()
|
|
||||||
if count != 1:
|
|
||||||
winner = None
|
|
||||||
break
|
|
||||||
if winner is not None:
|
|
||||||
# check whether this edge was part of the selection
|
|
||||||
if winner.time_stamp != CF.get_time_stamp():
|
|
||||||
#print("---", winner.id.first, winner.id.second)
|
|
||||||
# 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.begin = winner
|
|
||||||
_it.current_edge = winner
|
|
||||||
_it.orientation = winnerOrientation
|
|
||||||
_it.init()
|
|
||||||
while not _it.is_end:
|
|
||||||
ve = _it.object
|
|
||||||
#print("--------", ve.id.first, ve.id.second)
|
|
||||||
self._length = self._length + ve.length_2d
|
|
||||||
_it.increment()
|
|
||||||
if _it.is_begin:
|
|
||||||
break;
|
|
||||||
_it.begin = winner
|
|
||||||
_it.current_edge = winner
|
|
||||||
_it.orientation = winnerOrientation
|
|
||||||
if not _it.is_begin:
|
|
||||||
_it.decrement()
|
|
||||||
while (not _it.is_end) and (not _it.is_begin):
|
|
||||||
ve = _it.object
|
|
||||||
#print("--------", ve.id.first, ve.id.second)
|
|
||||||
self._length = self._length + ve.length_2d
|
|
||||||
_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.begin = winner
|
|
||||||
_cit.current_edge = winner
|
|
||||||
_cit.orientation = winnerOrientation
|
|
||||||
_cit.init()
|
|
||||||
while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
|
|
||||||
ve = _cit.object
|
|
||||||
#print("-------- --------", ve.id.first, ve.id.second)
|
|
||||||
connexl = connexl + ve.length_2d
|
|
||||||
_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, False, True, None, True)
|
|
||||||
self._length = float(length)
|
|
||||||
def init(self):
|
|
||||||
pass
|
|
||||||
def traverse(self, iter):
|
|
||||||
winner = None
|
|
||||||
winnerOrientation = 0
|
|
||||||
#print(self.current_edge.id.first, self.current_edge.id.second)
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
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.current_edge.nature & nat) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if (ve.nature & nat) != 0:
|
|
||||||
count = count+1
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
winnerOrientation = 1
|
|
||||||
else:
|
|
||||||
winnerOrientation = 0
|
|
||||||
it.increment()
|
|
||||||
if count != 1:
|
|
||||||
winner = None
|
|
||||||
break
|
|
||||||
if winner is not None:
|
|
||||||
# check whether this edge was part of the selection
|
|
||||||
if winner.time_stamp != CF.get_time_stamp():
|
|
||||||
#print("---", winner.id.first, winner.id.second)
|
|
||||||
# nw let's compute the length of this connex non selected part:
|
|
||||||
connexl = 0
|
|
||||||
_cit = pyChainSilhouetteGenericIterator(0,0)
|
|
||||||
_cit.begin = winner
|
|
||||||
_cit.current_edge = winner
|
|
||||||
_cit.orientation = winnerOrientation
|
|
||||||
_cit.init()
|
|
||||||
while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
|
|
||||||
ve = _cit.object
|
|
||||||
#print("-------- --------", ve.id.first, ve.id.second)
|
|
||||||
connexl = connexl + ve.length_2d
|
|
||||||
_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, False, True, None, True)
|
|
||||||
self._length = 0
|
|
||||||
self._absLength = l
|
|
||||||
self._percent = float(percent)
|
|
||||||
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.current_edge.id.first, self.current_edge.id.second)
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
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.current_edge.nature & nat) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if (ve.nature & nat) != 0:
|
|
||||||
count = count+1
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
winnerOrientation = 1
|
|
||||||
else:
|
|
||||||
winnerOrientation = 0
|
|
||||||
it.increment()
|
|
||||||
if count != 1:
|
|
||||||
winner = None
|
|
||||||
break
|
|
||||||
if winner is not None:
|
|
||||||
# check whether this edge was part of the selection
|
|
||||||
if winner.time_stamp != CF.get_time_stamp():
|
|
||||||
#print("---", winner.id.first, winner.id.second)
|
|
||||||
# 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.begin = winner
|
|
||||||
_it.current_edge = winner
|
|
||||||
_it.orientation = winnerOrientation
|
|
||||||
_it.init()
|
|
||||||
while not _it.is_end:
|
|
||||||
ve = _it.object
|
|
||||||
#print("--------", ve.id.first, ve.id.second)
|
|
||||||
self._length = self._length + ve.length_2d
|
|
||||||
_it.increment()
|
|
||||||
if _it.is_begin:
|
|
||||||
break;
|
|
||||||
_it.begin = winner
|
|
||||||
_it.current_edge = winner
|
|
||||||
_it.orientation = winnerOrientation
|
|
||||||
if not _it.is_begin:
|
|
||||||
_it.decrement()
|
|
||||||
while (not _it.is_end) and (not _it.is_begin):
|
|
||||||
ve = _it.object
|
|
||||||
#print("--------", ve.id.first, ve.id.second)
|
|
||||||
self._length = self._length + ve.length_2d
|
|
||||||
_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.begin = winner
|
|
||||||
_cit.current_edge = winner
|
|
||||||
_cit.orientation = winnerOrientation
|
|
||||||
_cit.init()
|
|
||||||
while _cit.is_end == 0 and _cit.object.time_stamp != CF.get_time_stamp():
|
|
||||||
ve = _cit.object
|
|
||||||
#print("-------- --------", ve.id.first, ve.id.second)
|
|
||||||
connexl = connexl + ve.length_2d
|
|
||||||
_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, False, True, None, True)
|
|
||||||
self._length = 0
|
|
||||||
self._absLength = l
|
|
||||||
self._percent = float(percent)
|
|
||||||
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.current_edge.id.first, self.current_edge.id.second)
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if ve.id == mateVE.id:
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
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.current_edge.nature & nat) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
if (ve.nature & nat) != 0:
|
|
||||||
count = count+1
|
|
||||||
winner = ve
|
|
||||||
if not it.is_incoming:
|
|
||||||
winnerOrientation = 1
|
|
||||||
else:
|
|
||||||
winnerOrientation = 0
|
|
||||||
it.increment()
|
|
||||||
if count != 1:
|
|
||||||
winner = None
|
|
||||||
break
|
|
||||||
if winner is not None:
|
|
||||||
# check whether this edge was part of the selection
|
|
||||||
if winner.qi != 0:
|
|
||||||
#print("---", winner.id.first, winner.id.second)
|
|
||||||
# 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.begin = winner
|
|
||||||
_it.current_edge = winner
|
|
||||||
_it.orientation = winnerOrientation
|
|
||||||
_it.init()
|
|
||||||
while not _it.is_end:
|
|
||||||
ve = _it.object
|
|
||||||
#print("--------", ve.id.first, ve.id.second)
|
|
||||||
self._length = self._length + ve.length_2d
|
|
||||||
_it.increment()
|
|
||||||
if _it.is_begin:
|
|
||||||
break;
|
|
||||||
_it.begin = winner
|
|
||||||
_it.current_edge = winner
|
|
||||||
_it.orientation = winnerOrientation
|
|
||||||
if not _it.is_begin:
|
|
||||||
_it.decrement()
|
|
||||||
while (not _it.is_end) and (not _it.is_begin):
|
|
||||||
ve = _it.object
|
|
||||||
#print("--------", ve.id.first, ve.id.second)
|
|
||||||
self._length = self._length + ve.length_2d
|
|
||||||
_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.begin = winner
|
|
||||||
_cit.current_edge = winner
|
|
||||||
_cit.orientation = winnerOrientation
|
|
||||||
_cit.init()
|
|
||||||
while not _cit.is_end and _cit.object.qi != 0:
|
|
||||||
ve = _cit.object
|
|
||||||
#print("-------- --------", ve.id.first, ve.id.second)
|
|
||||||
connexl = connexl + ve.length_2d
|
|
||||||
_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=True):
|
|
||||||
ChainingIterator.__init__(self, stayInSelection, True, None, True)
|
|
||||||
def init(self):
|
|
||||||
pass
|
|
||||||
def traverse(self, iter):
|
|
||||||
winner = None
|
|
||||||
it = AdjacencyIterator(iter)
|
|
||||||
tvertex = self.next_vertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
mateVE = tvertex.get_mate(self.current_edge)
|
|
||||||
while not it.is_end:
|
|
||||||
ve = it.object
|
|
||||||
feB = self.current_edge.last_fedge
|
|
||||||
feA = ve.first_fedge
|
|
||||||
vB = feB.second_svertex
|
|
||||||
vA = feA.first_svertex
|
|
||||||
if vA.id.first == vB.id.first:
|
|
||||||
winner = ve
|
|
||||||
break
|
|
||||||
feA = self.current_edge.first_fedge
|
|
||||||
feB = ve.last_fedge
|
|
||||||
vB = feB.second_svertex
|
|
||||||
vA = feA.first_svertex
|
|
||||||
if vA.id.first == vB.id.first:
|
|
||||||
winner = ve
|
|
||||||
break
|
|
||||||
feA = self.current_edge.last_fedge
|
|
||||||
feB = ve.last_fedge
|
|
||||||
vB = feB.second_svertex
|
|
||||||
vA = feA.second_svertex
|
|
||||||
if vA.id.first == vB.id.first:
|
|
||||||
winner = ve
|
|
||||||
break
|
|
||||||
feA = self.current_edge.first_fedge
|
|
||||||
feB = ve.first_fedge
|
|
||||||
vB = feB.first_svertex
|
|
||||||
vA = feA.first_svertex
|
|
||||||
if vA.id.first == vB.id.first:
|
|
||||||
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.current_edge.nature
|
|
||||||
if (natures[i] & currentNature) != 0:
|
|
||||||
count=0
|
|
||||||
while not it.is_end:
|
|
||||||
visitNext = 0
|
|
||||||
oNature = it.object.nature
|
|
||||||
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.object
|
|
||||||
it.increment()
|
|
||||||
if count != 1:
|
|
||||||
winner = None
|
|
||||||
break
|
|
||||||
return winner
|
|
||||||
|
|
@@ -1,105 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : Functions0D.py
|
|
||||||
# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
|
|
||||||
# Date : 30/06/2005
|
|
||||||
# Purpose : Functions (functors) to be used for 0D elements
|
|
||||||
|
|
||||||
from freestyle import Curvature2DAngleF0D, CurvePoint, ReadCompleteViewMapPixelF0D, \
|
|
||||||
ReadSteerableViewMapPixelF0D, UnaryFunction0DDouble, UnaryFunction0DMaterial, \
|
|
||||||
UnaryFunction0DVec2f
|
|
||||||
from freestyle import ContextFunctions as CF
|
|
||||||
|
|
||||||
import math
|
|
||||||
import mathutils
|
|
||||||
|
|
||||||
class CurveMaterialF0D(UnaryFunction0DMaterial):
|
|
||||||
# A replacement of the built-in MaterialF0D for stroke creation.
|
|
||||||
# MaterialF0D does not work with Curves and Strokes.
|
|
||||||
def __call__(self, inter):
|
|
||||||
cp = inter.object
|
|
||||||
assert(isinstance(cp, CurvePoint))
|
|
||||||
fe = cp.first_svertex.get_fedge(cp.second_svertex)
|
|
||||||
assert(fe is not None)
|
|
||||||
return fe.material if fe.is_smooth else fe.material_left
|
|
||||||
|
|
||||||
class pyInverseCurvature2DAngleF0D(UnaryFunction0DDouble):
|
|
||||||
def __call__(self, inter):
|
|
||||||
func = Curvature2DAngleF0D()
|
|
||||||
c = func(inter)
|
|
||||||
return (3.1415 - c)
|
|
||||||
|
|
||||||
class pyCurvilinearLengthF0D(UnaryFunction0DDouble):
|
|
||||||
def __call__(self, inter):
|
|
||||||
cp = inter.object
|
|
||||||
assert(isinstance(cp, CurvePoint))
|
|
||||||
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 __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 = math.pow(2,self._l)
|
|
||||||
def __call__(self, iter):
|
|
||||||
p = iter.object.point_2d
|
|
||||||
gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
|
|
||||||
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
|
||||||
gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
|
|
||||||
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
|
||||||
return mathutils.Vector([gx, gy])
|
|
||||||
|
|
||||||
class pyViewMapGradientNormF0D(UnaryFunction0DDouble):
|
|
||||||
def __init__(self, l):
|
|
||||||
UnaryFunction0DDouble.__init__(self)
|
|
||||||
self._l = l
|
|
||||||
self._step = math.pow(2,self._l)
|
|
||||||
def __call__(self, iter):
|
|
||||||
p = iter.object.point_2d
|
|
||||||
gx = CF.read_complete_view_map_pixel(self._l, int(p.x+self._step), int(p.y)) - \
|
|
||||||
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
|
||||||
gy = CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y+self._step)) - \
|
|
||||||
CF.read_complete_view_map_pixel(self._l, int(p.x), int(p.y))
|
|
||||||
grad = mathutils.Vector([gx, gy])
|
|
||||||
return grad.length
|
|
@@ -1,58 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : Functions1D.py
|
|
||||||
# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
|
|
||||||
# Date : 08/04/2005
|
|
||||||
# Purpose : Functions (functors) to be used for 1D elements
|
|
||||||
|
|
||||||
from freestyle import GetProjectedZF1D, IntegrationType, UnaryFunction1DDouble, integrate
|
|
||||||
from Functions0D import pyDensityAnisotropyF0D, pyViewMapGradientNormF0D
|
|
||||||
import string
|
|
||||||
|
|
||||||
class pyGetInverseProjectedZF1D(UnaryFunction1DDouble):
|
|
||||||
def __call__(self, inter):
|
|
||||||
func = GetProjectedZF1D()
|
|
||||||
z = func(inter)
|
|
||||||
return (1.0 - z)
|
|
||||||
|
|
||||||
class pyGetSquareInverseProjectedZF1D(UnaryFunction1DDouble):
|
|
||||||
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 __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 __call__(self, inter):
|
|
||||||
v = integrate(self._func, inter.pointsBegin(self._sampling), inter.pointsEnd(self._sampling), self._integration)
|
|
||||||
return v
|
|
@@ -1,73 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : PredicatesB1D.py
|
|
||||||
# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
|
|
||||||
# Date : 08/04/2005
|
|
||||||
# Purpose : Binary predicates (functors) to be used for 1D elements
|
|
||||||
|
|
||||||
from freestyle import BinaryPredicate1D, GetZF1D, IntegrationType, Nature, SameShapeIdBP1D, ZDiscontinuityF1D
|
|
||||||
from Functions1D import pyViewMapGradientNormF1D
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
class pyZBP1D(BinaryPredicate1D):
|
|
||||||
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 __call__(self, i1, i2):
|
|
||||||
return (self._GetZDiscontinuity(i1) > self._GetZDiscontinuity(i2))
|
|
||||||
|
|
||||||
class pyLengthBP1D(BinaryPredicate1D):
|
|
||||||
def __call__(self, i1, i2):
|
|
||||||
return (i1.length_2d > i2.length_2d)
|
|
||||||
|
|
||||||
class pySilhouetteFirstBP1D(BinaryPredicate1D):
|
|
||||||
def __call__(self, inter1, inter2):
|
|
||||||
bpred = SameShapeIdBP1D()
|
|
||||||
if (bpred(inter1, inter2) != 1):
|
|
||||||
return 0
|
|
||||||
if (inter1.nature & Nature.SILHOUETTE):
|
|
||||||
return (inter2.nature & Nature.SILHOUETTE) != 0
|
|
||||||
return (inter1.nature == inter2.nature)
|
|
||||||
|
|
||||||
class pyNatureBP1D(BinaryPredicate1D):
|
|
||||||
def __call__(self, inter1, inter2):
|
|
||||||
return (inter1.nature & inter2.nature)
|
|
||||||
|
|
||||||
class pyViewMapGradientNormBP1D(BinaryPredicate1D):
|
|
||||||
def __init__(self,l, sampling=2.0):
|
|
||||||
BinaryPredicate1D.__init__(self)
|
|
||||||
self._GetGradient = pyViewMapGradientNormF1D(l, IntegrationType.MEAN)
|
|
||||||
def __call__(self, i1,i2):
|
|
||||||
#print("compare gradient")
|
|
||||||
return (self._GetGradient(i1) > self._GetGradient(i2))
|
|
||||||
|
|
||||||
class pyShuffleBP1D(BinaryPredicate1D):
|
|
||||||
def __init__(self):
|
|
||||||
BinaryPredicate1D.__init__(self)
|
|
||||||
random.seed(1)
|
|
||||||
def __call__(self, inter1, inter2):
|
|
||||||
r1 = random.uniform(0,1)
|
|
||||||
r2 = random.uniform(0,1)
|
|
||||||
return (r1<r2)
|
|
@@ -1,96 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : PredicatesU0D.py
|
|
||||||
# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
|
|
||||||
# Date : 08/04/2005
|
|
||||||
# Purpose : Unary predicates (functors) to be used for 0D elements
|
|
||||||
|
|
||||||
from freestyle import Curvature2DAngleF0D, Nature, QuantitativeInvisibilityF0D, UnaryPredicate0D
|
|
||||||
from Functions0D import pyCurvilinearLengthF0D
|
|
||||||
|
|
||||||
class pyHigherCurvature2DAngleUP0D(UnaryPredicate0D):
|
|
||||||
def __init__(self,a):
|
|
||||||
UnaryPredicate0D.__init__(self)
|
|
||||||
self._a = a
|
|
||||||
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 __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 __call__(self, inter):
|
|
||||||
v = inter.object
|
|
||||||
return (v.nature & self._nature) != 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 __call__(self, iter):
|
|
||||||
if (iter.object.nature & Nature.T_VERTEX) == 0:
|
|
||||||
return 0
|
|
||||||
if iter.is_end:
|
|
||||||
return 0
|
|
||||||
if self._getQI(iter) != 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 __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 __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
|
|
@@ -1,342 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : PredicatesU1D.py
|
|
||||||
# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
|
|
||||||
# Date : 08/04/2005
|
|
||||||
# Purpose : Unary predicates (functors) to be used for 1D elements
|
|
||||||
|
|
||||||
from freestyle import Curvature2DAngleF0D, CurveNatureF1D, DensityF1D, GetCompleteViewMapDensityF1D, \
|
|
||||||
GetDirectionalViewMapDensityF1D, GetOccludersF1D, GetProjectedZF1D, GetShapeF1D, GetSteerableViewMapDensityF1D, \
|
|
||||||
IntegrationType, ShapeUP1D, TVertex, UnaryPredicate1D
|
|
||||||
from Functions1D import pyDensityAnisotropyF1D, pyViewMapGradientNormF1D
|
|
||||||
|
|
||||||
class pyNFirstUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self, n):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self.__n = n
|
|
||||||
self.__count = 0
|
|
||||||
def __call__(self, inter):
|
|
||||||
self.__count = self.__count + 1
|
|
||||||
if self.__count <= self.__n:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class pyHigherLengthUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self,l):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self._l = l
|
|
||||||
def __call__(self, inter):
|
|
||||||
return (inter.length_2d > self._l)
|
|
||||||
|
|
||||||
class pyNatureUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self,nature):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self._nature = nature
|
|
||||||
self._getNature = CurveNatureF1D()
|
|
||||||
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 __call__(self, inter):
|
|
||||||
count = 0
|
|
||||||
func = Curvature2DAngleF0D()
|
|
||||||
it = inter.vertices_begin()
|
|
||||||
while not it.is_end:
|
|
||||||
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 __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 __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 __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 __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 __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 __call__(self, inter):
|
|
||||||
#print("toto")
|
|
||||||
#print(func.name)
|
|
||||||
#print(inter.name)
|
|
||||||
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 __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 __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 __call__(self, inter):
|
|
||||||
func = GetShapeF1D()
|
|
||||||
shapes = func(inter)
|
|
||||||
for s in shapes:
|
|
||||||
if(s.id == self._id):
|
|
||||||
return 0
|
|
||||||
it = inter.vertices_begin()
|
|
||||||
itlast = inter.vertices_end()
|
|
||||||
itlast.decrement()
|
|
||||||
v = it.object
|
|
||||||
vlast = itlast.object
|
|
||||||
tvertex = v.viewvertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
#print("TVertex: [ ", tvertex.id.first, ",", tvertex.id.second," ]")
|
|
||||||
eit = tvertex.edges_begin()
|
|
||||||
while not eit.is_end:
|
|
||||||
ve, incoming = eit.object
|
|
||||||
if ve.id == self._id:
|
|
||||||
return 1
|
|
||||||
#print("-------", ve.id.first, "-", ve.id.second)
|
|
||||||
eit.increment()
|
|
||||||
tvertex = vlast.viewvertex
|
|
||||||
if type(tvertex) is TVertex:
|
|
||||||
#print("TVertex: [ ", tvertex.id.first, ",", tvertex.id.second," ]")
|
|
||||||
eit = tvertex.edges_begin()
|
|
||||||
while not eit.is_end:
|
|
||||||
ve, incoming = eit.object
|
|
||||||
if ve.id == self._id:
|
|
||||||
return 1
|
|
||||||
#print("-------", ve.id.first, "-", ve.id.second)
|
|
||||||
eit.increment()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class pyIsInOccludersListUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self,id):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self._id = id
|
|
||||||
def __call__(self, inter):
|
|
||||||
func = GetOccludersF1D()
|
|
||||||
occluders = func(inter)
|
|
||||||
for a in occluders:
|
|
||||||
if a.id == self._id:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class pyIsOccludedByItselfUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self.__func1 = GetOccludersF1D()
|
|
||||||
self.__func2 = GetShapeF1D()
|
|
||||||
def __call__(self, inter):
|
|
||||||
lst1 = self.__func1(inter)
|
|
||||||
lst2 = self.__func2(inter)
|
|
||||||
for vs1 in lst1:
|
|
||||||
for vs2 in lst2:
|
|
||||||
if vs1.id == vs2.id:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
||||||
|
|
||||||
class pyIsOccludedByIdListUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self, idlist):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self._idlist = idlist
|
|
||||||
self.__func1 = GetOccludersF1D()
|
|
||||||
def __call__(self, inter):
|
|
||||||
lst1 = self.__func1(inter)
|
|
||||||
for vs1 in lst1:
|
|
||||||
for _id in self._idlist:
|
|
||||||
if vs1.id == _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.first, _id.second))
|
|
||||||
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 __call__(self, inter):
|
|
||||||
func = GetShapeF1D()
|
|
||||||
shapes = func(inter)
|
|
||||||
for a in shapes:
|
|
||||||
if a.id == 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 __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 __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 __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.vertices_begin()
|
|
||||||
itlast = inter.vertices_end()
|
|
||||||
itlast.decrement()
|
|
||||||
vlast = itlast.object
|
|
||||||
v = it.object
|
|
||||||
#print(v.id.first, v.id.second)
|
|
||||||
#print(vlast.id.first, vlast.id.second)
|
|
||||||
if v.id == vlast.id:
|
|
||||||
return 1
|
|
||||||
return 0
|
|
@@ -1,47 +0,0 @@
|
|||||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU General Public License
|
|
||||||
# as published by the Free Software Foundation; either version 2
|
|
||||||
# of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
#
|
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
|
||||||
|
|
||||||
# Filename : logical_operators.py
|
|
||||||
# Authors : Fredo Durand, Stephane Grabli, Francois Sillion, Emmanuel Turquin
|
|
||||||
# Date : 08/04/2005
|
|
||||||
# Purpose : Logical unary predicates (functors) for 1D elements
|
|
||||||
|
|
||||||
from freestyle import UnaryPredicate1D
|
|
||||||
|
|
||||||
class AndUP1D(UnaryPredicate1D):
|
|
||||||
def __init__(self, pred1, pred2):
|
|
||||||
UnaryPredicate1D.__init__(self)
|
|
||||||
self.__pred1 = pred1
|
|
||||||
self.__pred2 = pred2
|
|
||||||
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 __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 __call__(self, inter):
|
|
||||||
return not self.__pred(inter)
|
|
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,7 @@ void Path::setRootDir(const string& iRootDir)
|
|||||||
string(DIR_SEP.c_str()) + "variation_patterns" + string(DIR_SEP.c_str());
|
string(DIR_SEP.c_str()) + "variation_patterns" + string(DIR_SEP.c_str());
|
||||||
_BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + string(DIR_SEP.c_str()) + "textures" +
|
_BrushesPath = _ProjectDir + string(DIR_SEP.c_str()) + "data" + string(DIR_SEP.c_str()) + "textures" +
|
||||||
string(DIR_SEP.c_str()) + "brushes" + string(DIR_SEP.c_str());
|
string(DIR_SEP.c_str()) + "brushes" + string(DIR_SEP.c_str());
|
||||||
_PythonPath = _ProjectDir + string(DIR_SEP.c_str()) + "style_modules" + string(DIR_SEP.c_str());
|
_PythonPath = _ProjectDir + string(DIR_SEP.c_str()) + "modules" + string(DIR_SEP.c_str());
|
||||||
if (getenv("PYTHONPATH")) {
|
if (getenv("PYTHONPATH")) {
|
||||||
_PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH"));
|
_PythonPath += string(PATH_SEP.c_str()) + string(getenv("PYTHONPATH"));
|
||||||
}
|
}
|
||||||
|
@@ -469,7 +469,7 @@ static PyMethodDef module_functions[] = {
|
|||||||
|
|
||||||
static PyModuleDef module_definition = {
|
static PyModuleDef module_definition = {
|
||||||
PyModuleDef_HEAD_INIT,
|
PyModuleDef_HEAD_INIT,
|
||||||
"freestyle",
|
"_freestyle",
|
||||||
module_docstring,
|
module_docstring,
|
||||||
-1,
|
-1,
|
||||||
module_functions
|
module_functions
|
||||||
|
Reference in New Issue
Block a user