extend filter by extension
This commit is contained in:
parent
f47e0b9c40
commit
5935a95345
@ -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>
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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/<interval>">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/<interval>">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>
|
||||
|
@ -12,6 +12,7 @@ Last patch: 21.10.2021
|
||||
License: GNU GPL v3
|
||||
'''
|
||||
|
||||
import colorsys
|
||||
import inkex
|
||||
from inkex.bezier import csplength, csparea
|
||||
|
||||
@ -27,13 +28,17 @@ 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")
|
||||
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
|
||||
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
|
||||
|
||||
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)
|
||||
@ -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()
|
@ -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):
|
||||
|
Reference in New Issue
Block a user