Added "Purge Duplicate Path Nodes"
This commit is contained in:
parent
32e62d2c2b
commit
070ad1e737
22
extensions/fablabchemnitz/removeDuplicateNodes.inx
Normal file
22
extensions/fablabchemnitz/removeDuplicateNodes.inx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?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>
|
||||||
|
<param name="help" type="description">Remove duplicate nodes from selected paths.</param>
|
||||||
|
<param name="minUse" type="boolean" 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="boolean" 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>
|
||||||
|
<param name="unitinfo" type="description">Unit as defined in document (File->Document Properties).</param>
|
||||||
|
<effect>
|
||||||
|
<object-type>path</object-type>
|
||||||
|
<effects-menu>
|
||||||
|
<submenu name="FabLab Chemnitz">
|
||||||
|
<submenu name="Nesting/Cut Optimization"/>
|
||||||
|
</submenu>
|
||||||
|
</effects-menu>
|
||||||
|
</effect>
|
||||||
|
<script>
|
||||||
|
<command location="inx" interpreter="python">removeDuplicateNodes.py</command>
|
||||||
|
</script>
|
||||||
|
</inkscape-extension>
|
101
extensions/fablabchemnitz/removeDuplicateNodes.py
Normal file
101
extensions/fablabchemnitz/removeDuplicateNodes.py
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# coding=utf-8
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 Ellen Wasboe, ellen@wasbo.net
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
"""
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import inkex
|
||||||
|
from inkex import bezier, PathElement, CubicSuperPath
|
||||||
|
|
||||||
|
class removeDuplicateNodes(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
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
removeDuplicateNodes().run()
|
||||||
|
|
Reference in New Issue
Block a user