Difference between revisions of "FindMatch"
Jump to navigation
Jump to search
Line 1: | Line 1: | ||
The Find Match inx file | The Find Match inx file | ||
---- | ---- | ||
<pre> | <pre> | ||
<inkscape-extension> | <inkscape-extension> | ||
<_name>Find Match</_name> | <_name>Find Match</_name> | ||
Line 26: | Line 22: | ||
</pre> | </pre> | ||
---- | |||
The python file for Find Match | |||
---- | |||
<pre> | |||
#!/usr/bin/env python | |||
''' | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; either version 2 of the License, or | |||
(at your option) any later version. | |||
---- | This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
''' | |||
import sys | |||
sys.path.append('/usr/share/inkscape/extensions') | |||
# We will use the inkex module with the predefined Effect base class. | |||
import inkex | |||
from simplestyle import * | |||
from simplepath import * | |||
from math import sqrt | |||
color_props_fill=('fill:','stop-color:','flood-color:','lighting-color:') | |||
color_props_stroke=('stroke:',) | |||
color_props = color_props_fill + color_props_stroke | |||
def correlation(xList,yList): | |||
#print yList | |||
n = len(xList) | |||
sumX = 0 | |||
sumXX = 0 | |||
sumY = 0 | |||
sumYY = 0 | |||
sumXY = 0 | |||
for i in range(0,n): | |||
X = xList[i] | |||
sumX += X | |||
sumXX += X*X | |||
Y = yList[i] | |||
sumY += Y | |||
sumYY += Y*Y | |||
sumXY += X*Y | |||
corrnum = (n * sumXY)-(sumX * sumY) | |||
corrden = sqrt( (n * sumXX) - (sumX * sumX) ) * sqrt( (n * sumYY) - (sumY * sumY) ) | |||
corr = corrnum/corrden | |||
return corr | |||
def pathMatch(rPath,cPath): | |||
n = len(rPath) | |||
for i in range(0,n): | |||
rNode = rPath[i] | |||
cNode = cPath[i] | |||
[rCmd,rPoints] = rNode | |||
[cCmd,cPoints] = cNode | |||
if rCmd != cCmd: | |||
#print "not match" | |||
return 0 | |||
#print "Command Match" | |||
return 1 | |||
def pathPullPoints(rPath,cPath): | |||
n = len(rPath) | |||
rPointList = [] | |||
cPointList = [] | |||
for i in range(0,n): | |||
rNode = rPath[i] | |||
cNode = cPath[i] | |||
[rCmd,rPoints] = rNode | |||
[cCmd,cPoints] = cNode | |||
rPointList.extend(rPoints) | |||
cPointList.extend(cPoints) | |||
return [rPointList,cPointList] | |||
def getLayer(svg, layerName): | |||
for g in svg.xpath('//svg:g', namespaces=inkex.NSS): | |||
if (g.get(inkex.addNS('groupmode', 'inkscape')) == 'layer' | |||
and (g.get(inkex.addNS('label', 'inkscape')) | |||
== layerName)): | |||
return g | |||
# Create a new layer. | |||
newLayer = inkex.etree.SubElement(svg, 'g') | |||
newLayer.set(inkex.addNS('label', 'inkscape'), layerName) | |||
newLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') | |||
return newLayer | |||
def compareColors(refNode, compNode): | |||
pass | |||
def getColor(node): | |||
col = {} | |||
if node.attrib.has_key('style'): | |||
style=node.get('style') # fixme: this will break for presentation attributes! | |||
if style!='': | |||
#inkex.debug('old style:'+style) | |||
styles=style.split(';') | |||
for i in range(len(styles)): | |||
for c in range(len(color_props)): | |||
if styles[i].startswith(color_props[c]): | |||
#print "col num %d" % c | |||
#print styles[i][len(color_props[c]):] | |||
col[c] = styles[i][len(color_props[c]):] | |||
return col | |||
def colorMatch(rNode,cNode): | |||
rCol = getColor(rNode) | |||
#print rCol | |||
cCol = getColor(cNode) | |||
#print cCol | |||
if (rCol == cCol): | |||
return 1 | |||
return 0 | |||
class FindMatch(inkex.Effect): | |||
""" | |||
Inkscape effect extension. | |||
Searches for paths that match and places them on the named layer. | |||
""" | |||
def __init__(self): | |||
""" | |||
Constructor. | |||
Defines the "--what" option of a script. | |||
""" | |||
# Call the base class constructor. | |||
inkex.Effect.__init__(self) | |||
self.OptionParser.add_option('-f', '--foundLayer', action = 'store', | |||
type = 'string', dest = 'foundLayer', default = 'Found', | |||
help = 'Name of layer to put found objects on?') | |||
self.OptionParser.add_option("-t", "--threshold", | |||
action="store", type="float", | |||
dest="threshold", default = 0.8, | |||
help="threshold for correlation match") | |||
self.OptionParser.add_option("--matchcolor", | |||
action="store", type="inkbool", | |||
dest="matchcolor", default=True, | |||
help="If True, colors will be matched") | |||
def effect(self): | |||
""" | |||
Effect behaviour. | |||
Search for all paths that match the selected path | |||
""" | |||
foundLayer = self.options.foundLayer | |||
matchcolor = self.options.matchcolor | |||
# Get access to main SVG document element | |||
svg = self.document.getroot() | |||
# get the layer where the found paths will be moved to | |||
layer = getLayer(svg, foundLayer) | |||
# get a list of all path nodes | |||
pathNodes = self.document.xpath('//svg:path',namespaces=inkex.NSS) | |||
# setup stderr so that we can print to it for debugging | |||
saveout = sys.stdout | |||
sys.stdout = sys.stderr | |||
rPathLen = 0 | |||
rPathList = [] | |||
rPathNode = None | |||
if len(self.selected) == 0: | |||
print "Nothing Selected" | |||
sys.stdout = saveout | |||
return | |||
for id, node in self.selected.iteritems(): | |||
#print dir(node) | |||
if node.tag == inkex.addNS('path','svg'): | |||
#print node.attrib['d'] | |||
rPathList = parsePath(node.attrib['d']) | |||
rPathLen = len(rPathList) | |||
rPathNode = node | |||
#print rPathLen | |||
#print rPathList | |||
for cPathNode in pathNodes: | |||
cPathList = parsePath(cPathNode.attrib['d']) | |||
cPathLen = len(cPathList) | |||
#print cPathLen | |||
#print cPathList | |||
if rPathLen == cPathLen: | |||
#print " Found %d in %s" % (rPathLen,cPathNode) | |||
#print matchcolor | |||
colorMatchFlag = (colorMatch(rPathNode,cPathNode) == 1) or not matchcolor | |||
pathMatchFlag = pathMatch(rPathList,cPathList)==1 | |||
if pathMatchFlag and colorMatchFlag: | |||
[rList,cList] = pathPullPoints(rPathList,cPathList) | |||
corVal = correlation(rList,cList) | |||
#print "The correlation was %g" % corVal | |||
if (corVal > 0.80): | |||
layer.append(cPathNode) | |||
#print | |||
#print 'This message will be logged instead of displayed' | |||
sys.stdout = saveout | |||
# Create effect instance and apply it. | |||
effect = FindMatch() | |||
effect.affect() | |||
</pre> |
Revision as of 21:07, 17 December 2008
The Find Match inx file
<inkscape-extension> <_name>Find Match</_name> <id>org.find_match</id> <dependency type="executable" location="extensions">findmatch.py</dependency> <dependency type="executable" location="extensions">inkex.py</dependency> <param name="foundLayer" type="string" _gui-text="Name of layer to put found objects on?">Found</param> <param name="threshold" type="float" min="0.0" max="1.0" _gui-text="Correlation Threshold">0.8</param> <param name="matchcolor" type="boolean" _gui-text="Colors should match">true</param> <effect> <object-type>all</object-type> <effects-menu> <submenu _name="Examples"/> </effects-menu> </effect> <script> <command reldir="extensions" interpreter="python">findmatch.py</command> </script> </inkscape-extension>
The python file for Find Match
#!/usr/bin/env python ''' This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ''' import sys sys.path.append('/usr/share/inkscape/extensions') # We will use the inkex module with the predefined Effect base class. import inkex from simplestyle import * from simplepath import * from math import sqrt color_props_fill=('fill:','stop-color:','flood-color:','lighting-color:') color_props_stroke=('stroke:',) color_props = color_props_fill + color_props_stroke def correlation(xList,yList): #print yList n = len(xList) sumX = 0 sumXX = 0 sumY = 0 sumYY = 0 sumXY = 0 for i in range(0,n): X = xList[i] sumX += X sumXX += X*X Y = yList[i] sumY += Y sumYY += Y*Y sumXY += X*Y corrnum = (n * sumXY)-(sumX * sumY) corrden = sqrt( (n * sumXX) - (sumX * sumX) ) * sqrt( (n * sumYY) - (sumY * sumY) ) corr = corrnum/corrden return corr def pathMatch(rPath,cPath): n = len(rPath) for i in range(0,n): rNode = rPath[i] cNode = cPath[i] [rCmd,rPoints] = rNode [cCmd,cPoints] = cNode if rCmd != cCmd: #print "not match" return 0 #print "Command Match" return 1 def pathPullPoints(rPath,cPath): n = len(rPath) rPointList = [] cPointList = [] for i in range(0,n): rNode = rPath[i] cNode = cPath[i] [rCmd,rPoints] = rNode [cCmd,cPoints] = cNode rPointList.extend(rPoints) cPointList.extend(cPoints) return [rPointList,cPointList] def getLayer(svg, layerName): for g in svg.xpath('//svg:g', namespaces=inkex.NSS): if (g.get(inkex.addNS('groupmode', 'inkscape')) == 'layer' and (g.get(inkex.addNS('label', 'inkscape')) == layerName)): return g # Create a new layer. newLayer = inkex.etree.SubElement(svg, 'g') newLayer.set(inkex.addNS('label', 'inkscape'), layerName) newLayer.set(inkex.addNS('groupmode', 'inkscape'), 'layer') return newLayer def compareColors(refNode, compNode): pass def getColor(node): col = {} if node.attrib.has_key('style'): style=node.get('style') # fixme: this will break for presentation attributes! if style!='': #inkex.debug('old style:'+style) styles=style.split(';') for i in range(len(styles)): for c in range(len(color_props)): if styles[i].startswith(color_props[c]): #print "col num %d" % c #print styles[i][len(color_props[c]):] col[c] = styles[i][len(color_props[c]):] return col def colorMatch(rNode,cNode): rCol = getColor(rNode) #print rCol cCol = getColor(cNode) #print cCol if (rCol == cCol): return 1 return 0 class FindMatch(inkex.Effect): """ Inkscape effect extension. Searches for paths that match and places them on the named layer. """ def __init__(self): """ Constructor. Defines the "--what" option of a script. """ # Call the base class constructor. inkex.Effect.__init__(self) self.OptionParser.add_option('-f', '--foundLayer', action = 'store', type = 'string', dest = 'foundLayer', default = 'Found', help = 'Name of layer to put found objects on?') self.OptionParser.add_option("-t", "--threshold", action="store", type="float", dest="threshold", default = 0.8, help="threshold for correlation match") self.OptionParser.add_option("--matchcolor", action="store", type="inkbool", dest="matchcolor", default=True, help="If True, colors will be matched") def effect(self): """ Effect behaviour. Search for all paths that match the selected path """ foundLayer = self.options.foundLayer matchcolor = self.options.matchcolor # Get access to main SVG document element svg = self.document.getroot() # get the layer where the found paths will be moved to layer = getLayer(svg, foundLayer) # get a list of all path nodes pathNodes = self.document.xpath('//svg:path',namespaces=inkex.NSS) # setup stderr so that we can print to it for debugging saveout = sys.stdout sys.stdout = sys.stderr rPathLen = 0 rPathList = [] rPathNode = None if len(self.selected) == 0: print "Nothing Selected" sys.stdout = saveout return for id, node in self.selected.iteritems(): #print dir(node) if node.tag == inkex.addNS('path','svg'): #print node.attrib['d'] rPathList = parsePath(node.attrib['d']) rPathLen = len(rPathList) rPathNode = node #print rPathLen #print rPathList for cPathNode in pathNodes: cPathList = parsePath(cPathNode.attrib['d']) cPathLen = len(cPathList) #print cPathLen #print cPathList if rPathLen == cPathLen: #print " Found %d in %s" % (rPathLen,cPathNode) #print matchcolor colorMatchFlag = (colorMatch(rPathNode,cPathNode) == 1) or not matchcolor pathMatchFlag = pathMatch(rPathList,cPathList)==1 if pathMatchFlag and colorMatchFlag: [rList,cList] = pathPullPoints(rPathList,cPathList) corVal = correlation(rList,cList) #print "The correlation was %g" % corVal if (corVal > 0.80): layer.append(cPathNode) #print #print 'This message will be logged instead of displayed' sys.stdout = saveout # Create effect instance and apply it. effect = FindMatch() effect.affect()