extend filter by extension

This commit is contained in:
Mario Voigt 2021-11-04 00:53:13 +01:00
parent f47e0b9c40
commit 5935a95345
6 changed files with 83 additions and 36 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Colorize Path Lengths</name>
<name>Colorize Path Lengths/Slants</name>
<id>fablabchemnitz.de.colorize_path_lengths</id>
<param name="selection" type="optiongroup" appearance="combo" gui-text="Selection: ">
<option value="path_lengthselection">Length selection</option>

View File

@ -1,6 +1,6 @@
[
{
"name": "Colorize Path Lengths",
"name": "Colorize Path Lengths/Slants",
"id": "fablabchemnitz.de.colorize_path_lengths",
"path": "colorize_path_lengths",
"dependent_extensions": null,
@ -11,7 +11,7 @@
"comment": "ported to Inkscape v1 manually by Mario Voigt",
"source_url": "https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X/src/branch/master/extensions/fablabchemnitz/colorize_path_lengths",
"fork_url": "http://dp48069596.lolipop.jp/sd/scripts/script_inkscape/pathselection.zip",
"documentation_url": "https://stadtfabrikanten.org/display/IFM/Colorize+Path+Lengths",
"documentation_url": "https://stadtfabrikanten.org/pages/viewpage.action?pageId=55019108",
"inkscape_gallery_url": null,
"main_authors": [
"Sunabe Kazumichi",

View File

@ -19,6 +19,7 @@ Extension for InkScape 1.0+
replacedelement.path = replacedelement.path.to_absolute().to_superpath().to_path()
- maybe option: break apart while keeping relative/absolute commands (more complex and not sure if we have a great advantage having this)
- note: running this extension might leave some empty parent groups in some circumstances. run the clean groups extension separately to fix that
- sort to groups by path type (open, closed, ...)
- important to notice
- this algorithm might be really slow. Reduce flattening quality to speed up

View File

@ -2,7 +2,7 @@
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>Filter By Length/Area</name>
<id>fablabchemnitz.de.filter_by_length_area</id>
<label>Paths with value smaller than the given threshold will be deleted</label>
<label>Applies to paths only! Rectangles and other elements are not supported. If your selection is empty, the whole document will be parsed.</label>
<param name="debug" type="bool" gui-text="Enable debug">false</param>
<param name="unit" gui-text="Unit" type="optiongroup" appearance="combo">
<option value="mm">mm</option>
@ -17,17 +17,25 @@
<param name="nodes_interval" type="float" min="0.000" max="99999.000" precision="3" gui-text="Interval">10.000</param>
<separator/>
<param name="min_filter_enable" type="bool" gui-text="Enable filtering min.">false</param>
<param name="min_threshold" type="float" min="0.000" precision="3" max="10000000.000" gui-text="Min. length/area">1.000</param>
<param name="min_threshold" type="float" min="0.000" precision="3" max="10000000.000" gui-text="Min. length or area">1.000</param>
<param name="min_nodes" type="int" min="0" max="99999" gui-text="Min. nodes/&lt;interval&gt;">2</param>
<param name="max_filter_enable" type="bool" gui-text="Enable filtering max.">false</param>
<param name="max_threshold" type="float" min="0.000" precision="3" max="10000000.000" gui-text="Max. length/area">10000000.000</param>
<param name="max_threshold" type="float" min="0.000" precision="3" max="10000000.000" gui-text="Max. length or area">10000000.000</param>
<param name="max_nodes" type="int" min="0" max="99999" gui-text="Max. nodes/&lt;interval&gt;">10000000</param>
<label appearance="header">Filter</label>
<param name="precision" type="int" min="0" max="16" gui-text="Precision">3</param>
<label>Filter</label>
<param name="measure" type="optiongroup" appearance="combo" gui-text="By">
<option value="length">Length (Unit)</option>
<option value="nodes">Nodes per length (Unit)</option>
<option value="area">Area (Unit^2)</option>
</param>
<label>Actions</label>
<param name="delete" type="bool" gui-text="Delete">false</param>
<param name="colorize" type="bool" gui-text="Colorize">false</param>
<hbox>
<param name="sort_by_asc" type="bool" gui-text="Sort by value">false</param>
<param name="reverse_sort" type="bool" gui-text="Reverse sorting">false</param>
</hbox>
<effect>
<object-type>all</object-type>
<effects-menu>

View File

@ -12,6 +12,7 @@ Last patch: 21.10.2021
License: GNU GPL v3
'''
import colorsys
import inkex
from inkex.bezier import csplength, csparea
@ -27,14 +28,18 @@ class FilterByLengthArea(inkex.EffectExtension):
pars.add_argument('--min_nodes', type=int, default=0, help='Min. nodes/<interval>')
pars.add_argument('--max_nodes', type=int, default=10000000, help='Max. nodes/<interval>')
pars.add_argument('--nodes_interval', type=float, default=10000000.000, help='Interval')
pars.add_argument('--precision', type=int, default=3, help='Precision')
pars.add_argument('--measure', default="length")
def effect(self):
so = self.options
if so.min_filter_enable is False and so.max_filter_enable is False:
inkex.utils.debug("You need to enabled at least one filter rule!")
return
pars.add_argument('--delete', type=inkex.Boolean, default=False)
pars.add_argument('--colorize', type=inkex.Boolean, default=False)
pars.add_argument('--sort_by_asc', type=inkex.Boolean, default=False)
pars.add_argument('--reverse_sort', type=inkex.Boolean, default=False)
def effect(self):
global to_sort, so
to_sort = []
so = self.options
so.min_threshold = self.svg.unittouu(str(so.min_threshold) + self.svg.unit)
so.max_threshold = self.svg.unittouu(str(so.max_threshold) + self.svg.unit)
unit_factor = 1.0 / self.svg.uutounit(1.0, so.unit)
@ -47,41 +52,67 @@ class FilterByLengthArea(inkex.EffectExtension):
else:
elements = self.document.xpath("//svg:path", namespaces=inkex.NSS)
if so.debug is True:
inkex.utils.debug("Collecting elements ...")
for element in elements:
try:
csp = element.path.transform(element.composed_transform()).to_superpath()
if so.measure == "area":
area = -csparea(csp) #is returned as negative value. we need to invert with
if so.debug is True:
inkex.utils.debug("id={}, area={:0.3f}{}^2".format(element.get('id'), area, so.unit))
if so.min_filter_enable is True and area < (so.min_threshold * (unit_factor * unit_factor)):
element.delete()
if so.max_filter_enable is True and area >= (so.max_threshold * (unit_factor * unit_factor)):
element.delete()
area = round(-csparea(csp), so.precision) #is returned as negative value. we need to invert with
if (so.min_filter_enable is True and area < (so.min_threshold * (unit_factor * unit_factor))) or \
(so.max_filter_enable is True and area >= (so.max_threshold * (unit_factor * unit_factor))) or \
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
if so.debug is True:
inkex.utils.debug("id={}, area={:0.3f}{}^2".format(element.get('id'), area, so.unit))
to_sort.append({'element': element, 'value': area})
elif so.measure == "length":
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
if so.debug is True:
inkex.utils.debug("id={}, length={:0.3f}{}".format(element.get('id'), self.svg.uutounit(str(stotal), so.unit), so.unit))
if so.min_filter_enable is True and stotal < (so.min_threshold * unit_factor):
element.delete()
if self.options.max_filter_enable is True and stotal >= (so.max_threshold * unit_factor):
element.delete()
stotal = round(stotal, so.precision)
if (so.min_filter_enable is True and stotal < (so.min_threshold * unit_factor)) or \
(so.max_filter_enable is True and stotal >= (so.max_threshold * unit_factor)) or \
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
if so.debug is True:
inkex.utils.debug("id={}, length={:0.3f}{}".format(element.get('id'), self.svg.uutounit(str(stotal), so.unit), so.unit))
to_sort.append({'element': element, 'value': stotal})
elif so.measure == "nodes":
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
stotal = round(stotal, so.precision)
nodes = len(element.path)
if so.debug is True:
inkex.utils.debug("id={}, length={:0.3f}{}, nodes={}".format(element.get('id'), self.svg.uutounit(str(stotal), so.unit), so.unit, nodes))
if so.min_filter_enable is True and nodes / stotal < so.min_nodes / self.svg.unittouu(str(so.nodes_interval) + so.unit):
element.delete()
if so.max_filter_enable is True and nodes / stotal < so.max_nodes / self.svg.unittouu(str(so.nodes_interval) + so.unit):
element.delete()
if (so.min_filter_enable is True and nodes / stotal < so.min_nodes / self.svg.unittouu(str(so.nodes_interval) + so.unit)) or \
(so.max_filter_enable is True and nodes / stotal < so.max_nodes / self.svg.unittouu(str(so.nodes_interval) + so.unit)) or \
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
if so.debug is True:
inkex.utils.debug("id={}, length={:0.3f}{}, nodes={}".format(element.get('id'), self.svg.uutounit(str(stotal), so.unit), so.unit, nodes))
to_sort.append({'element': element, 'value': nodes})
except Exception as e:
#self.msg(e)
#inkex.utils.debug(e)
pass
for i in range(0, len(to_sort)):
element = to_sort[i].get('element')
if so.delete is True:
element.delete()
if so.delete is True:
return #quit here
if so.sort_by_asc is True:
to_sort.sort(key=lambda x: x.get('value')) #sort by target value
for i in range(0, len(to_sort)):
element = to_sort[i].get('element')
if so.reverse_sort is True:
idx = len(element.getparent())
else:
idx = 0
element.getparent().insert(idx, element)
if so.colorize is True:
color = colorsys.hsv_to_rgb(i / float(len(to_sort)), 1.0, 1.0)
element.style['stroke'] = '#%02x%02x%02x' % tuple(int(x * 255) for x in color)
if __name__ == '__main__':
FilterByLengthArea().run()

View File

@ -16,6 +16,13 @@ class LaserCheck(inkex.EffectExtension):
- number of parts to weed in total; number of parts which are smaller than vector grid
- add some inkex.Desc to all elements which were checked and which have some issue. use special syntax to remove old stuff each time the check is applied again
- this code is horrible ugly stuff
- output time/cost estimations per stroke color
- add check for stroke colors -> make some useful predefinitions like (for default modes)
- black = cutting
- blue = cutting inside
- green = cutting outside
- pink = Vektorgravur
...
'''
def add_arguments(self, pars):