update purger for duplicate nodes
This commit is contained in:
parent
5bc8e6e7c1
commit
91efb70e60
@ -1,22 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||
<name>Purge Duplicate Path Nodes</name>
|
||||
<id>fablabchemnitz.de.purge_duplicate_path_nodes</id>
|
||||
<label>Remove duplicate nodes from selected paths.</label>
|
||||
<param name="minUse" type="bool" gui-text="Also remove segments with length less than specified length">false</param>
|
||||
<param name="minlength" indent="6" type="float" precision="1" min="0" max="9999" gui-text="Minimum segment length">0.01</param>
|
||||
<param name="joinEnd" type="bool" gui-text="Join end nodes of each subpath if distance less or equal to">false</param>
|
||||
<param name="maxdist" indent="6" type="float" precision="1" min="0" max="9999" gui-text="Max opening">0.01</param>
|
||||
<label>Unit as defined in document (File->Document Properties).</label>
|
||||
<name>Purge Duplicate Path Nodes</name>
|
||||
<id>fablabchemnitz.de.purge_duplicate_path_nodes</id>
|
||||
<param type="notebook" name="tab">
|
||||
<page name="options" gui-text="Options">
|
||||
<label>Remove duplicate nodes from selected paths.</label>
|
||||
<param name="minUse" type="bool" gui-text="Interpolate nodes of segments with total length less than specified length">false</param>
|
||||
<param name="minlength" indent="4" type="float" precision="2" min="0" max="9999" gui-text="Minimum segment length">0.01</param>
|
||||
<param name="joinEnd" type="bool" gui-text="Close subpaths where start and end node have a distance of less than">false</param>
|
||||
<param name="maxdist" indent="4" type="float" precision="2" min="0" max="9999" gui-text="Limit">0.01</param>
|
||||
<param name="joinEndSub" type="bool" gui-text="Join end nodes of separate subpaths where distance less than">false</param>
|
||||
<param name="maxdist2" indent="4" type="float" precision="2" min="0" max="9999" gui-text="Limit">0.01</param>
|
||||
<param name="allowReverse" indent="4" type="bool" gui-text="Allow reversing direction of subpaths">true</param>
|
||||
<param name="optionJoin" indent="4" type="optiongroup" appearance="combo" gui-text="Join subpaths by">
|
||||
<option value="1">interpolating nodes</option>
|
||||
<option value="2">adding straight line segment</option>
|
||||
</param>
|
||||
<label>Unit as defined in document (File->Document Properties).</label>
|
||||
</page>
|
||||
<page name="help" gui-text="Information">
|
||||
<label xml:space="preserve">
|
||||
Originally created to clean up paths for cutters/plotters removing excessive nodes or small gaps.
|
||||
|
||||
Remove duplicate nodes (with exact same coordinates will always be performed.
|
||||
To join paths, make sure that the paths to consider are already combined (subpath of the same path).
|
||||
To combine paths, select them and press Ctrl+K.
|
||||
|
||||
For more information:
|
||||
https://gitlab.com/EllenWasbo/inkscape-extension-removeduplicatenodes
|
||||
</label>
|
||||
</page>
|
||||
</param>
|
||||
<effect>
|
||||
<object-type>path</object-type>
|
||||
<effects-menu>
|
||||
<submenu name="FabLab Chemnitz">
|
||||
<submenu name="Nesting/Cut Optimization"/>
|
||||
<submenu name="Nesting/Cut Optimization" />
|
||||
</submenu>
|
||||
</effects-menu>
|
||||
</effect>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">purge_duplicate_path_nodes.py</command>
|
||||
</script>
|
||||
<script>
|
||||
<command location="inx" interpreter="python">purge_duplicate_path_nodes.py</command>
|
||||
</script>
|
||||
</inkscape-extension>
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2020 Ellen Wasboe, ellen@wasbo.net
|
||||
#
|
||||
@ -7,7 +6,7 @@
|
||||
# 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
|
||||
@ -17,85 +16,360 @@
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
"""
|
||||
Remove duplicate nodes or join nodes with distance less than specified.
|
||||
Optionally join start node with end node of each subpath if distance less than specified.
|
||||
Remove duplicate nodes or interpolate nodes with distance less than specified.
|
||||
Optionally join start node with end node of each subpath if distance less than specified = close the subpath
|
||||
Optionally join separate subpaths if end nodes closer than a specified distance.
|
||||
Joining subpaths can be done either by interpolating or straight line segment.
|
||||
"""
|
||||
|
||||
import inkex
|
||||
from inkex import bezier, PathElement, CubicSuperPath
|
||||
import numpy as np
|
||||
|
||||
def joinTest(xdiff,ydiff,limDist,idsIncluded):
|
||||
joinFlag=False
|
||||
idJoin=-1
|
||||
dist=np.sqrt(np.add(np.power(xdiff,2),np.power(ydiff,2)))
|
||||
minDist=np.amin(dist)
|
||||
if minDist < limDist:
|
||||
joinFlag=True
|
||||
idMins=np.where(dist==minDist)
|
||||
idMin=idMins[0]
|
||||
idJoin=idsIncluded[idMin[0]]
|
||||
|
||||
return [joinFlag,idJoin]
|
||||
|
||||
def revSub(subPath):
|
||||
subPath=subPath[::-1]
|
||||
for i, s in enumerate(subPath):
|
||||
subPath[i]=s[::-1]
|
||||
return subPath
|
||||
|
||||
def joinSub(sub1,sub2, interpOrLine):
|
||||
if interpOrLine == "1":
|
||||
#interpolate end nodes
|
||||
p1=sub1[-1][-1]
|
||||
p2=sub2[0][0]
|
||||
joinNode=[0.5*(p1[0]+p2[0]),0.5*(p1[1]+p2[1])]
|
||||
#remove end/start + input join
|
||||
sub1[-1][1]=joinNode
|
||||
sub1[-1][2]=sub2[0][2]
|
||||
sub2.pop(0)
|
||||
|
||||
newsub=sub1+sub2
|
||||
|
||||
return newsub
|
||||
|
||||
class PurgeDuplicatePathNodes(inkex.EffectExtension):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--minlength", default="0")
|
||||
pars.add_argument("--minUse", type=inkex.Boolean, default=False)
|
||||
pars.add_argument("--maxdist", default="0")
|
||||
pars.add_argument("--joinEnd", type=inkex.Boolean, default=False)
|
||||
|
||||
"""Remove duplicate nodes"""
|
||||
def effect(self):
|
||||
for id, elem in self.svg.selected.items():
|
||||
minlength=float(self.options.minlength)
|
||||
maxdist=float(self.options.maxdist)
|
||||
if self.options.minUse == False:
|
||||
minlength=0
|
||||
if self.options.joinEnd == False:
|
||||
maxdist=-1
|
||||
|
||||
#register which subpaths are closed
|
||||
dList=str(elem.path).upper().split(' M')
|
||||
closed=[""]
|
||||
l=0
|
||||
for sub in dList:
|
||||
if dList[l].find("Z") > -1:
|
||||
closed.append(" Z ")
|
||||
else:
|
||||
closed.append("")
|
||||
l+=1
|
||||
closed.pop(0)
|
||||
|
||||
new = []
|
||||
s=0
|
||||
for sub in elem.path.to_superpath():
|
||||
new.append([sub[0]])
|
||||
i = 1
|
||||
while i <= len(sub) - 1:
|
||||
length = bezier.cspseglength(new[-1][-1], sub[i]) #curve length
|
||||
if length >= minlength:
|
||||
new[-1].append(sub[i])
|
||||
else:
|
||||
#average last node xy with this node xy and set this further node to last
|
||||
new[-1][-1][1][0]= 0.5*(new[-1][-1][1][0]+sub[i][1][0])
|
||||
new[-1][-1][1][1]= 0.5*(new[-1][-1][1][1]+sub[i][1][1])
|
||||
new[-1][-1][-1]=sub[i][-1]
|
||||
i += 1
|
||||
|
||||
if maxdist > -1:
|
||||
#calculate distance between first and last node
|
||||
#if <= maxdist set closed[i] to "Z "
|
||||
last=new[-1][-1]
|
||||
length = bezier.cspseglength(new[-1][-1], sub[0])
|
||||
if length <= maxdist:
|
||||
newStartEnd=[0.5*(new[-1][-1][-1][0]+new[0][0][0][0]),0.5*(new[-1][-1][-1][1]+new[0][0][0][1])]
|
||||
new[0][0][0]=newStartEnd
|
||||
new[0][0][1]=newStartEnd
|
||||
new[-1][-1][1]=newStartEnd
|
||||
new[-1][-1][2]=newStartEnd
|
||||
closed[s]=" Z "
|
||||
s+=1
|
||||
|
||||
elem.path = CubicSuperPath(new).to_path(curves_only=True)
|
||||
|
||||
#reset z to the originally closed paths (z lost in cubicsuperpath)
|
||||
temppath=str(elem.path.to_absolute()).split('M ')
|
||||
temppath.pop(0)
|
||||
newPath=''
|
||||
l=0
|
||||
for sub in temppath:
|
||||
newPath=newPath+'M '+temppath[l]+closed[l]
|
||||
l+=1
|
||||
elem.path=newPath
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument("--tab", default="options")
|
||||
pars.add_argument("--minlength", default="0")
|
||||
pars.add_argument("--minUse", type=inkex.Boolean, default=False)
|
||||
pars.add_argument("--maxdist", default="0")
|
||||
pars.add_argument("--joinEnd", type=inkex.Boolean, default=False)
|
||||
pars.add_argument("--maxdist2", default="0")
|
||||
pars.add_argument("--joinEndSub", type=inkex.Boolean, default=False)
|
||||
pars.add_argument("--allowReverse", type=inkex.Boolean, default=True)
|
||||
pars.add_argument("--optionJoin", default="1")
|
||||
|
||||
"""Remove duplicate nodes"""
|
||||
def effect(self):
|
||||
|
||||
if not self.svg.selected:
|
||||
raise inkex.AbortExtension("Please select an object.")
|
||||
|
||||
for id, elem in self.svg.selection.id_dict().items():
|
||||
|
||||
minlength=float(self.options.minlength)
|
||||
maxdist=float(self.options.maxdist)
|
||||
maxdist2=float(self.options.maxdist2)
|
||||
if self.options.minUse == False:
|
||||
minlength=0
|
||||
if self.options.joinEnd == False:
|
||||
maxdist=-1
|
||||
if self.options.joinEndSub == False:
|
||||
maxdist2=-1
|
||||
|
||||
pp=elem.path.to_absolute()
|
||||
|
||||
#register which subpaths are closed - to reset closing after missed in to_superpath
|
||||
dList=str(pp).upper().split(' M')
|
||||
closed=[]
|
||||
l=0
|
||||
for sub in dList:
|
||||
if dList[l].find("Z") > -1:
|
||||
closed.append(" Z ")
|
||||
else:
|
||||
closed.append("")
|
||||
l+=1
|
||||
|
||||
new = []
|
||||
nSub=len(closed)
|
||||
|
||||
xStart=np.zeros(nSub)#x start - prepare for joining subpaths
|
||||
yStart=np.copy(xStart)
|
||||
xEnd=np.copy(xStart)
|
||||
yEnd=np.copy(xStart)
|
||||
|
||||
s=0
|
||||
for sub in pp.to_superpath():
|
||||
new.append([sub[0]])
|
||||
if maxdist2 > -1:
|
||||
xStart[s]=sub[0][0][0]
|
||||
yStart[s]=sub[0][0][1]
|
||||
xEnd[s]=sub[-1][-1][0]
|
||||
yEnd[s]=sub[-1][-1][1]
|
||||
#remove segment if segment length is less than minimum set, keep position
|
||||
i=1
|
||||
lastCombined=False
|
||||
while i <= len(sub) - 1:
|
||||
length = bezier.cspseglength(new[-1][-1], sub[i]) #curve length
|
||||
if length >= minlength:
|
||||
new[-1].append(sub[i])#add as is
|
||||
lastCombined=False
|
||||
else:
|
||||
#keep including segments until total length > minlength
|
||||
summedlength=length
|
||||
proceed=True
|
||||
e=0 #extra segments
|
||||
finishedAdding=False
|
||||
while proceed and i+e +1 <= len(sub) -1:
|
||||
nextlength=bezier.cspseglength(sub[i+e], sub[i+e+1]) #curve length
|
||||
if nextlength >= minlength: #don't include the next segment
|
||||
proceed=False
|
||||
if lastCombined == False and i>1: #i.e. this is a small group between long segments then average over the group, first node already added (new -1)
|
||||
new[-1][-1][1][0]= 0.5*(new[-1][-1][1][0]+sub[i+e][1][0])#change position to average
|
||||
new[-1][-1][1][1]= 0.5*(new[-1][-1][1][1]+sub[i+e][1][1])
|
||||
new[-1][-1][2]=sub[i+e][2]#change last controlpoint to that of the last node in group
|
||||
finishedAdding=True
|
||||
else: #end of group with many segments - average over all but last node (which is added separately)
|
||||
new[-1].append(sub[i])#add as is
|
||||
new[-1][-1][1][0]= 0.5*(new[-1][-1][1][0]+sub[i+e-1][1][0])#change position to average first/last
|
||||
new[-1][-1][1][1]= 0.5*(new[-1][-1][1][1]+sub[i+e-1][1][1])
|
||||
new[-1][-1][2]=sub[i+e-1][2]#change last controlpoint to that of the last node in group
|
||||
new[-1].append(sub[i+e])#add as is
|
||||
finishedAdding=True
|
||||
lastCombined=True
|
||||
|
||||
else:
|
||||
summedlength=summedlength+nextlength
|
||||
if summedlength >= minlength:
|
||||
proceed=False
|
||||
e=e+1
|
||||
|
||||
if finishedAdding == False:
|
||||
|
||||
if i == 1:# if first segment keep position of first node, direction of last in group
|
||||
new[-1][-1][2][0]= sub[i+e][2][0]
|
||||
new[-1][-1][2][1]= sub[i+e][2][1]
|
||||
elif i + e == len(sub)-1:#if last segment included keep position of last node, direction of previous
|
||||
new[-1].append(sub[i])#add first node in group
|
||||
if e > 0 :
|
||||
new[-1].append(sub[i+e])#add last node
|
||||
new[-1][-1][0]= sub[i+1][0]#get first controlpoint from i+1
|
||||
else:
|
||||
#average position over first/last in group and keep direction (controlpoint) of first/last node
|
||||
#group within sequence of many close nodes - add new without averaging on previous
|
||||
new[-1].append(sub[i])#add first node in group
|
||||
new[-1][-1][1][0]= 0.5*(new[-1][-1][1][0]+sub[i+e][1][0])#change position to average
|
||||
new[-1][-1][1][1]= 0.5*(new[-1][-1][1][1]+sub[i+e][1][1])
|
||||
new[-1][-1][2]=sub[i+e][2]#change last controlpoint to that of the last node in group
|
||||
|
||||
i=i+e
|
||||
|
||||
i += 1
|
||||
|
||||
if closed[s]==" Z ":
|
||||
#if new[-1][-1][1]==new[-1][-2][1]:#not always precise
|
||||
new[-1].pop(-1)#for some reason tosuperpath adds an extra node for closed paths
|
||||
|
||||
#close each subpath where start/end node is closer than maxdist set (if not already closed)
|
||||
if maxdist > -1:
|
||||
if closed[s] == "": #ignore already closed paths
|
||||
#calculate distance between first and last node, if <= maxdist set closed[i] to " Z "
|
||||
#last=new[-1][-1]
|
||||
length = bezier.cspseglength(new[-1][-1], sub[0])
|
||||
if length < maxdist:
|
||||
newStartEnd=[0.5*(new[-1][-1][-1][0]+new[-1][0][0][0]),0.5*(new[-1][-1][-1][1]+new[-1][0][0][1])]
|
||||
new[-1][0][0]=newStartEnd
|
||||
new[-1][0][1]=newStartEnd
|
||||
new[-1][-1][1]=newStartEnd
|
||||
new[-1][-1][2]=newStartEnd
|
||||
closed[s]=" Z "
|
||||
|
||||
s+=1
|
||||
|
||||
#join different subpaths?
|
||||
closed=np.array(closed)
|
||||
openPaths=np.where(closed=='')
|
||||
closedPaths=np.where(closed==' Z ')
|
||||
if maxdist2 > -1 and openPaths[0].size > 1:
|
||||
#calculate distance between end nodes of the subpaths. If distance < maxdist2 found - join
|
||||
joinStartToEnd=np.ones(nSub, dtype=bool)
|
||||
joinEndToStart=np.copy(joinStartToEnd)
|
||||
joinEndTo=np.full(nSub,-1)
|
||||
joinEndTo[closedPaths]=2*maxdist2#set higher than maxdist2 to avoid join to closedPaths
|
||||
joinStartTo=np.copy(joinEndTo)
|
||||
|
||||
#join end node of current subpath to startnode of any other or start node of current to end node of other (no reverse)
|
||||
s=0
|
||||
while s < nSub:
|
||||
#end of current to start of other
|
||||
if joinEndTo[s]==-1:
|
||||
idsTest=np.where(joinStartTo==-1)#find available start nodes
|
||||
id2Test=np.delete(idsTest[0],np.where(idsTest[0] == s))#avoid join to self
|
||||
if id2Test.size > 0:
|
||||
diff_x=np.subtract(xStart[id2Test],xEnd[s])#calculate distances in x direction
|
||||
diff_y=np.subtract(yStart[id2Test],yEnd[s])#calculate distances in y direction
|
||||
res=joinTest(diff_x,diff_y,maxdist2,id2Test)#find shortest distance if less than minimum
|
||||
if res[0] == True:#if match found flag end of this with id of other and flag start of match to end of this
|
||||
joinEndTo[s]=res[1]
|
||||
joinStartTo[res[1]]=s
|
||||
|
||||
#start of current to end of other
|
||||
if joinStartTo[s]==-1:
|
||||
idsTest=np.where(joinEndTo==-1)
|
||||
id2Test=np.delete(idsTest[0],np.where(idsTest[0] == s))
|
||||
if id2Test.size > 0:
|
||||
diff_x=np.subtract(xEnd[id2Test],xStart[s])
|
||||
diff_y=np.subtract(yEnd[id2Test],yStart[s])
|
||||
res=joinTest(diff_x,diff_y,maxdist2,id2Test)
|
||||
if res[0] == True:
|
||||
joinStartTo[s]=res[1]
|
||||
joinEndTo[res[1]]=s
|
||||
|
||||
if self.options.allowReverse==True:
|
||||
#start to start - if match reverse (reverseSub[s]=True)
|
||||
if joinStartTo[s]==-1:
|
||||
idsTest=np.where(joinStartTo==-1)
|
||||
id2Test=np.delete(idsTest[0],np.where(idsTest[0] == s))
|
||||
if id2Test.size > 0:
|
||||
diff_x=np.subtract(xStart[id2Test],xStart[s])
|
||||
diff_y=np.subtract(yStart[id2Test],yStart[s])
|
||||
res=joinTest(diff_x,diff_y,maxdist2,id2Test)
|
||||
if res[0] == True:
|
||||
jID=res[1]
|
||||
joinStartTo[s]=jID
|
||||
joinStartTo[jID]=s
|
||||
joinStartToEnd[s]=False #false means reverse
|
||||
joinStartToEnd[jID]=False
|
||||
|
||||
#end to end
|
||||
if joinEndTo[s]==-1:
|
||||
idsTest=np.where(joinEndTo==-1)
|
||||
id2Test=np.delete(idsTest[0],np.where(idsTest[0] == s))
|
||||
if id2Test.size > 0:
|
||||
diff_x=np.subtract(xEnd[id2Test],xEnd[s])
|
||||
diff_y=np.subtract(yEnd[id2Test],yEnd[s])
|
||||
res=joinTest(diff_x,diff_y,maxdist2,id2Test)
|
||||
if res[0] == True:
|
||||
jID=res[1]
|
||||
joinEndTo[s]=jID
|
||||
joinEndTo[jID]=s
|
||||
joinEndToStart[s]=False
|
||||
joinEndToStart[jID]=False
|
||||
|
||||
s+=1
|
||||
|
||||
old=new
|
||||
new=[]
|
||||
s=0
|
||||
movedTo=np.arange(nSub)
|
||||
newClosed=[]
|
||||
joinEndTo[closedPaths]=-1#avoid joining to other paths if already closed
|
||||
joinStartTo[closedPaths]=-1
|
||||
|
||||
for s in range(0,nSub):
|
||||
if movedTo[s] == s:#not joined yet
|
||||
if joinEndTo[s] > -1 or joinStartTo[s] > -1:#any join scheduled
|
||||
thisSub=[]
|
||||
closedThis=""
|
||||
if joinEndTo[s] > -1:# join one by one until -1 or back to s (closed)
|
||||
jID=joinEndTo[s]
|
||||
sub1=old[s]
|
||||
sub2=old[jID]
|
||||
rev=True if joinEndToStart[s] == False else False
|
||||
sub2=revSub(sub2) if rev == True else sub2
|
||||
thisSub=joinSub(sub1,sub2,self.options.optionJoin)
|
||||
movedTo[jID]=s
|
||||
prev=s
|
||||
#continue if sub2 joined to more
|
||||
if joinEndTo[jID] > -1 and joinStartTo[jID] > -1:#already joined so both joined if continue
|
||||
proceed=1
|
||||
|
||||
while proceed == 1:
|
||||
nID=joinEndTo[jID] if joinEndTo[jID] != prev else joinStartTo[jID]
|
||||
if movedTo[nID] == s:
|
||||
closedThis=" Z "
|
||||
proceed=0
|
||||
else:
|
||||
sub2=old[nID]
|
||||
if (nID == joinEndTo[jID] and joinStartTo[nID] == jID) or (nID == joinStartTo[jID] and joinEndTo[nID] == jID):
|
||||
pass
|
||||
else:
|
||||
rev = not rev
|
||||
sub2=revSub(sub2) if rev == True else sub2
|
||||
thisSub=joinSub(thisSub,sub2,self.options.optionJoin)
|
||||
movedTo[nID]=s
|
||||
if joinEndTo[nID] > -1 and joinStartTo[nID] > -1:
|
||||
prev=jID
|
||||
jID=nID
|
||||
else:
|
||||
proceed=0
|
||||
|
||||
if joinStartTo[s] > -1 and closedThis =="":
|
||||
jID=joinStartTo[s]
|
||||
sub1=old[jID]
|
||||
rev=True if joinStartToEnd[s] == False else False
|
||||
sub1=revSub(sub1) if rev == True else sub1
|
||||
sub2=thisSub if len(thisSub) > 0 else old[s]
|
||||
thisSub=joinSub(sub1,sub2,self.options.optionJoin)
|
||||
movedTo[jID]=s
|
||||
prev=s
|
||||
#continue if sub1 joined to more
|
||||
if joinEndTo[jID] > -1 and joinStartTo[jID] > -1:
|
||||
proceed=1
|
||||
|
||||
while proceed == 1:
|
||||
nID=joinStartTo[jID] if joinStartTo[jID] != prev else joinEndTo[jID]
|
||||
if movedTo[nID] == s:
|
||||
closedThis=" Z "
|
||||
proceed=0
|
||||
else:
|
||||
sub1=old[nID]
|
||||
if (nID == joinEndTo[jID] and joinStartTo[nID] == jID) or (nID == joinStartTo[jID] and joinEndTo[nID] == jID):
|
||||
pass
|
||||
else:
|
||||
rev = not rev
|
||||
sub1=revSub(sub1) if rev == True else sub1
|
||||
thisSub=joinSub(sub1,thisSub,self.options.optionJoin)
|
||||
movedTo[nID]=s
|
||||
if joinEndTo[nID] > -1 and joinStartTo[nID] > -1:
|
||||
prev=jID
|
||||
jID=nID
|
||||
else:
|
||||
proceed=0
|
||||
|
||||
new.append(thisSub)
|
||||
newClosed.append(closedThis)
|
||||
|
||||
else:
|
||||
new.append(old[s])
|
||||
newClosed.append(closed[s])
|
||||
closed=newClosed
|
||||
|
||||
elem.path = CubicSuperPath(new).to_path(curves_only=True)
|
||||
|
||||
#reset z to the originally closed paths (z lost in cubicsuperpath)
|
||||
temppath=str(elem.path.to_absolute()).split('M ')
|
||||
temppath.pop(0)
|
||||
newPath=''
|
||||
l=0
|
||||
for sub in temppath:
|
||||
newPath=newPath+'M '+temppath[l]+closed[l]
|
||||
l+=1
|
||||
elem.path=newPath
|
||||
|
||||
if __name__ == '__main__':
|
||||
PurgeDuplicatePathNodes().run()
|
||||
|
||||
|
Reference in New Issue
Block a user