several addons to filter and some other glitches removed
This commit is contained in:
parent
5935a95345
commit
07490f9349
@ -196,60 +196,22 @@ class LinksCreator(inkex.EffectExtension):
|
|||||||
# check if the element has a style attribute. If not we create a blank one with a black stroke and without fill
|
# check if the element has a style attribute. If not we create a blank one with a black stroke and without fill
|
||||||
style = None
|
style = None
|
||||||
default_fill = 'none'
|
default_fill = 'none'
|
||||||
default_stroke_width = '1px'
|
|
||||||
default_stroke = '#000000'
|
default_stroke = '#000000'
|
||||||
|
default_stroke_width = str(self.svg.unittouu('1px'))
|
||||||
if element.attrib.has_key('style'):
|
if element.attrib.has_key('style'):
|
||||||
style = element.get('style')
|
element.style['stroke-dasharray'] = stroke_dasharray
|
||||||
if style.endswith(';') is False:
|
element.style['stroke-dashoffset'] = stroke_dashoffset
|
||||||
style += ';'
|
|
||||||
|
|
||||||
# if has style attribute and dasharray and/or dashoffset are present we modify it accordingly
|
|
||||||
declarations = style.split(';') # parse the style content and check what we need to adjust
|
|
||||||
for i, decl in enumerate(declarations):
|
|
||||||
parts = decl.split(':', 2)
|
|
||||||
if len(parts) == 2:
|
|
||||||
(prop, val) = parts
|
|
||||||
prop = prop.strip().lower()
|
|
||||||
#if prop == 'fill':
|
|
||||||
# declarations[i] = prop + ':{}'.format(default_fill)
|
|
||||||
#if prop == 'stroke':
|
|
||||||
# declarations[i] = prop + ':{}'.format(default_stroke)
|
|
||||||
#if prop == 'stroke-width':
|
|
||||||
# declarations[i] = prop + ':{}'.format(default_stroke_width)
|
|
||||||
if prop == 'stroke-dasharray': #comma separated list of one or more float values
|
|
||||||
declarations[i] = prop + ':{}'.format(stroke_dasharray)
|
|
||||||
if prop == 'stroke-dashoffset':
|
|
||||||
declarations[i] = prop + ':{}'.format(stroke_dashoffset)
|
|
||||||
element.set('style', ';'.join(declarations)) #apply new style to element
|
|
||||||
|
|
||||||
#if has style attribute but the style attribute does not contain fill, stroke, stroke-width, stroke-dasharray or stroke-dashoffset yet
|
#if has style attribute but the style attribute does not contain fill, stroke, stroke-width, stroke-dasharray or stroke-dashoffset yet
|
||||||
style = element.style
|
if element.style.get('fill') is None: element.style['fill'] = default_fill
|
||||||
if re.search('fill:(.*?)(;|$)', str(style)) is None:
|
if element.style.get('stroke') is None: element.style['stroke'] = default_stroke
|
||||||
style += 'fill:{};'.format(default_fill)
|
if element.style.get('stroke-width') is None: element.style['stroke-width'] = default_stroke_width
|
||||||
if re.search('(;|^)stroke:(.*?)(;|$)', str(style)) is None: #if "stroke" is None, add one. We need to distinguish because there's also attribute "-inkscape-stroke" that's why we check starting with ^ or ;
|
|
||||||
style += 'stroke:{};'.format(default_stroke)
|
|
||||||
if not 'stroke-width' in style:
|
|
||||||
style += 'stroke-width:{};'.format(default_stroke_width)
|
|
||||||
if not 'stroke-dasharray' in style:
|
|
||||||
style += 'stroke-dasharray:{};'.format(stroke_dasharray)
|
|
||||||
if not 'stroke-dashoffset' in style:
|
|
||||||
style += 'stroke-dashoffset:{};'.format(stroke_dashoffset)
|
|
||||||
element.set('style', style)
|
|
||||||
else:
|
else:
|
||||||
style = 'fill:{};stroke:{};stroke-width:{};stroke-dasharray:{};stroke-dashoffset:{};'.format(default_fill, default_stroke, default_stroke_width, stroke_dasharray, stroke_dashoffset)
|
element.style = 'fill:{};stroke:{};stroke-width:{};stroke-dasharray:{};stroke-dashoffset:{};'.format(
|
||||||
element.set('style', style)
|
default_fill, default_stroke, default_stroke_width, stroke_dasharray, stroke_dashoffset)
|
||||||
|
|
||||||
#if enabled, we override stroke color with blue (now, as the element definitely has a style)
|
#if enabled, we override stroke color with blue (now, as the element definitely has a style)
|
||||||
if self.options.weakening_mode is True and self.options.switch_pattern is True:
|
if self.options.weakening_mode is True and self.options.switch_pattern is True:
|
||||||
declarations = element.get('style').split(';')
|
element.style['stroke'] = "#0000ff"
|
||||||
for i, decl in enumerate(declarations):
|
|
||||||
parts = decl.split(':', 2)
|
|
||||||
if len(parts) == 2:
|
|
||||||
(prop, val) = parts
|
|
||||||
prop = prop.strip().lower()
|
|
||||||
if prop == 'stroke':
|
|
||||||
declarations[i] = prop + ':{}'.format("#0000ff")
|
|
||||||
element.set('style', ';'.join(declarations)) #apply new style to element
|
|
||||||
|
|
||||||
# Print some info about values
|
# Print some info about values
|
||||||
if self.options.show_info is True:
|
if self.options.show_info is True:
|
||||||
|
@ -2,9 +2,15 @@
|
|||||||
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
|
||||||
<name>Filter By Length/Area</name>
|
<name>Filter By Length/Area</name>
|
||||||
<id>fablabchemnitz.de.filter_by_length_area</id>
|
<id>fablabchemnitz.de.filter_by_length_area</id>
|
||||||
<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="tab" type="notebook">
|
||||||
|
<page name="tab_settings" gui-text="Filter By Length/Area">
|
||||||
|
<label appearance="header">General Settings</label>
|
||||||
<param name="debug" type="bool" gui-text="Enable debug">false</param>
|
<param name="debug" type="bool" gui-text="Enable debug">false</param>
|
||||||
<param name="unit" gui-text="Unit" type="optiongroup" appearance="combo">
|
<param name="apply_transformations" type="bool" gui-text="Apply transformations (requires separate extension)" gui-description="This will call the extension 'Apply Transformations'. Helps avoiding geometry shifting">false</param>
|
||||||
|
<hbox>
|
||||||
|
<vbox>
|
||||||
|
<label appearance="header">Threshold</label>
|
||||||
|
<param name="unit" gui-text="Unit" type="optiongroup" appearance="combo" gui-description="The unit applies to interval and thresholds">
|
||||||
<option value="mm">mm</option>
|
<option value="mm">mm</option>
|
||||||
<option value="cm">cm</option>
|
<option value="cm">cm</option>
|
||||||
<option value="px">px</option>
|
<option value="px">px</option>
|
||||||
@ -12,8 +18,6 @@
|
|||||||
<option value="pc">pc</option>
|
<option value="pc">pc</option>
|
||||||
<option value="in">in</option>
|
<option value="in">in</option>
|
||||||
</param>
|
</param>
|
||||||
<label>The unit applies to interval and thresholds</label>
|
|
||||||
<label appearance="header">Threshold</label>
|
|
||||||
<param name="nodes_interval" type="float" min="0.000" max="99999.000" precision="3" gui-text="Interval">10.000</param>
|
<param name="nodes_interval" type="float" min="0.000" max="99999.000" precision="3" gui-text="Interval">10.000</param>
|
||||||
<separator/>
|
<separator/>
|
||||||
<param name="min_filter_enable" type="bool" gui-text="Enable filtering min.">false</param>
|
<param name="min_filter_enable" type="bool" gui-text="Enable filtering min.">false</param>
|
||||||
@ -23,19 +27,73 @@
|
|||||||
<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_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>
|
<param name="max_nodes" type="int" min="0" max="99999" gui-text="Max. nodes/<interval>">10000000</param>
|
||||||
<param name="precision" type="int" min="0" max="16" gui-text="Precision">3</param>
|
<param name="precision" type="int" min="0" max="16" gui-text="Precision">3</param>
|
||||||
<label>Filter</label>
|
</vbox>
|
||||||
|
<separator/>
|
||||||
|
<vbox>
|
||||||
|
<label appearance="header">Filter</label>
|
||||||
<param name="measure" type="optiongroup" appearance="combo" gui-text="By">
|
<param name="measure" type="optiongroup" appearance="combo" gui-text="By">
|
||||||
<option value="length">Length (Unit)</option>
|
<option value="length">Length (Unit)</option>
|
||||||
<option value="nodes">Nodes per length (Unit)</option>
|
<option value="nodes">Nodes per length (Unit)</option>
|
||||||
<option value="area">Area (Unit^2)</option>
|
<option value="area">Area (Unit^2)</option>
|
||||||
</param>
|
</param>
|
||||||
<label>Actions</label>
|
<label appearance="header">Actions</label>
|
||||||
<param name="delete" type="bool" gui-text="Delete">false</param>
|
<param name="delete" type="bool" gui-text="Delete">false</param>
|
||||||
<param name="colorize" type="bool" gui-text="Colorize">false</param>
|
|
||||||
<hbox>
|
<hbox>
|
||||||
<param name="sort_by_asc" type="bool" gui-text="Sort by value">false</param>
|
<param name="color_mode" type="optiongroup" appearance="combo" gui-text="Color mode">
|
||||||
<param name="reverse_sort" type="bool" gui-text="Reverse sorting">false</param>
|
<option value="none">None</option>
|
||||||
|
<option value="colorize_rainbow">Colorize (Rainbow effect)</option>
|
||||||
|
<option value="colorize_single">Colorize (Single color)</option>
|
||||||
|
</param>
|
||||||
|
<param name="color_single" type="color" appearance="colorbutton" gui-text="Single color">0xff00ffff</param>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
<hbox>
|
||||||
|
<param name="sort_by_value" type="bool" gui-text="Sort by value">false</param>
|
||||||
|
<param name="reverse_sort_value" type="bool" gui-text="Reverse">false</param>
|
||||||
|
</hbox>
|
||||||
|
<hbox>
|
||||||
|
<param name="sort_by_id" type="bool" gui-text="Sort by Id">false</param>
|
||||||
|
<param name="reverse_sort_id" type="bool" gui-text="Reverse">false</param>
|
||||||
|
</hbox>
|
||||||
|
<param name="rename_ids" type="bool" gui-text="Rename (IDs)">false</param>
|
||||||
|
<hbox>
|
||||||
|
<param name="set_labels" type="bool" gui-text="Set labels" gui-description="Adds type and value to the element's label">false</param>
|
||||||
|
<param name="remove_labels" type="bool" gui-text="Remove labels" gui-description="Remove labels (cleaning option for previous applications)">false</param>
|
||||||
|
</hbox>
|
||||||
|
<param name="group" type="bool" gui-text="Group elements">false</param>
|
||||||
|
<param name="cleanup" type="bool" gui-text="Cleanup unused groups/layers" gui-description="This will call the extension 'Remove Empty Groups' if available">false</param>
|
||||||
|
</vbox>
|
||||||
|
</hbox>
|
||||||
|
<label appearance="header">Tips</label>
|
||||||
|
<label>Applies to paths only! Rectangles and other elements are not supported. If your selection is empty, the whole document will be parsed.
|
||||||
|
If you did not enable any filter, the actions are applied either to the whole selection or the complete document too.</label>
|
||||||
|
</page>
|
||||||
|
<page name="tab_about" gui-text="About">
|
||||||
|
<label appearance="header">Filter By Length/Area</label>
|
||||||
|
<label>A tool to filter for paths by different filters. Allows multiple actions to perform on.</label>
|
||||||
|
<label>2020 - 2021 / written by Mario Voigt (Stadtfabrikanten e.V. / FabLab Chemnitz)</label>
|
||||||
|
<spacer/>
|
||||||
|
<label appearance="header">Online Documentation</label>
|
||||||
|
<label appearance="url">https://y.stadtfabrikanten.org/filterbylengtharea</label>
|
||||||
|
<spacer/>
|
||||||
|
<label appearance="header">Contributing</label>
|
||||||
|
<label appearance="url">https://gitea.fablabchemnitz.de/FabLab_Chemnitz/mightyscape-1.X</label>
|
||||||
|
<label appearance="url">mailto:mario.voigt@stadtfabrikanten.org</label>
|
||||||
|
<spacer/>
|
||||||
|
<label appearance="header">MightyScape Extension Collection</label>
|
||||||
|
<label>This piece of software is part of the MightyScape for Inkscape Extension Collection and is licensed under GNU GPL v3</label>
|
||||||
|
<label appearance="url">https://y.stadtfabrikanten.org/mightyscape-overview</label>
|
||||||
|
</page>
|
||||||
|
<page name="tab_donate" gui-text="Donate">
|
||||||
|
<label appearance="header">Coffee + Pizza</label>
|
||||||
|
<label>We are the Stadtfabrikanten, running the FabLab Chemnitz since 2016. A FabLab is an open workshop that gives people access to machines and digital tools like 3D printers, laser cutters and CNC milling machines.</label>
|
||||||
|
<spacer/>
|
||||||
|
<label>You like our work and want to support us? You can donate to our non-profit organization by different ways:</label>
|
||||||
|
<label appearance="url">https://y.stadtfabrikanten.org/donate</label>
|
||||||
|
<spacer/>
|
||||||
|
<label>Thanks for using our extension and helping us!</label>
|
||||||
|
<image>../000_about_fablabchemnitz.svg</image>
|
||||||
|
</page>
|
||||||
|
</param>
|
||||||
<effect>
|
<effect>
|
||||||
<object-type>all</object-type>
|
<object-type>all</object-type>
|
||||||
<effects-menu>
|
<effects-menu>
|
||||||
|
@ -1,25 +1,35 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Extension for InkScape 1.0
|
Extension for InkScape 1.0+
|
||||||
Features
|
|
||||||
- Filter paths which are smaller/bigger than a given length or area
|
|
||||||
|
|
||||||
Author: Mario Voigt / FabLab Chemnitz
|
Author: Mario Voigt / FabLab Chemnitz
|
||||||
Mail: mario.voigt@stadtfabrikanten.org
|
Mail: mario.voigt@stadtfabrikanten.org
|
||||||
Date: 03.08.2020
|
Date: 03.08.2020
|
||||||
Last patch: 21.10.2021
|
Last patch: 04.11.2021
|
||||||
License: GNU GPL v3
|
License: GNU GPL v3
|
||||||
|
|
||||||
|
ToDo:
|
||||||
|
- id sorting: handle ids with/without numbers and sort by number
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import sys
|
||||||
import colorsys
|
import colorsys
|
||||||
import inkex
|
import inkex
|
||||||
|
from inkex import Color
|
||||||
from inkex.bezier import csplength, csparea
|
from inkex.bezier import csplength, csparea
|
||||||
|
|
||||||
|
sys.path.append("../remove_empty_groups")
|
||||||
|
sys.path.append("../apply_transformations")
|
||||||
|
|
||||||
class FilterByLengthArea(inkex.EffectExtension):
|
class FilterByLengthArea(inkex.EffectExtension):
|
||||||
|
|
||||||
def add_arguments(self, pars):
|
def add_arguments(self, pars):
|
||||||
|
pars.add_argument('--tab')
|
||||||
pars.add_argument('--debug', type=inkex.Boolean, default=False)
|
pars.add_argument('--debug', type=inkex.Boolean, default=False)
|
||||||
|
pars.add_argument("--apply_transformations", type=inkex.Boolean, default=False, help="Run 'Apply Transformations' extension before running vpype. Helps avoiding geometry shifting")
|
||||||
|
pars.add_argument("--cleanup", type=inkex.Boolean, default = True, help = "Cleanup all unused groups/layers (requires separate extension)")
|
||||||
pars.add_argument('--unit')
|
pars.add_argument('--unit')
|
||||||
pars.add_argument('--min_filter_enable', type=inkex.Boolean, default=True, help='Enable filtering min.')
|
pars.add_argument('--min_filter_enable', type=inkex.Boolean, default=True, help='Enable filtering min.')
|
||||||
pars.add_argument('--min_threshold', type=float, default=0.000, help='Remove paths with an threshold smaller than this value')
|
pars.add_argument('--min_threshold', type=float, default=0.000, help='Remove paths with an threshold smaller than this value')
|
||||||
@ -31,15 +41,30 @@ class FilterByLengthArea(inkex.EffectExtension):
|
|||||||
pars.add_argument('--precision', type=int, default=3, help='Precision')
|
pars.add_argument('--precision', type=int, default=3, help='Precision')
|
||||||
pars.add_argument('--measure', default="length")
|
pars.add_argument('--measure', default="length")
|
||||||
pars.add_argument('--delete', type=inkex.Boolean, default=False)
|
pars.add_argument('--delete', type=inkex.Boolean, default=False)
|
||||||
pars.add_argument('--colorize', type=inkex.Boolean, default=False)
|
pars.add_argument('--color_mode', default="none")
|
||||||
pars.add_argument('--sort_by_asc', type=inkex.Boolean, default=False)
|
pars.add_argument('--color_single', type=Color, default='0xff00ffff')
|
||||||
pars.add_argument('--reverse_sort', type=inkex.Boolean, default=False)
|
pars.add_argument('--sort_by_value', type=inkex.Boolean, default=False)
|
||||||
|
pars.add_argument('--reverse_sort_value', type=inkex.Boolean, default=False)
|
||||||
|
pars.add_argument('--sort_by_id', type=inkex.Boolean, default=False)
|
||||||
|
pars.add_argument('--reverse_sort_id', type=inkex.Boolean, default=False)
|
||||||
|
pars.add_argument('--rename_ids', type=inkex.Boolean, default=False)
|
||||||
|
pars.add_argument('--set_labels', type=inkex.Boolean, default=False, help="Adds type and value to the element's label")
|
||||||
|
pars.add_argument('--remove_labels', type=inkex.Boolean, default=False, help="Remove labels (cleaning option for previous applications)")
|
||||||
|
pars.add_argument('--group', type=inkex.Boolean, default=False)
|
||||||
|
|
||||||
def effect(self):
|
def effect(self):
|
||||||
global to_sort, so
|
global to_sort, so
|
||||||
to_sort = []
|
to_sort = []
|
||||||
so = self.options
|
so = self.options
|
||||||
|
|
||||||
|
applyTransformationsAvailable = False # at first we apply external extension
|
||||||
|
try:
|
||||||
|
import apply_transformations
|
||||||
|
applyTransformationsAvailable = True
|
||||||
|
except Exception as e:
|
||||||
|
# self.msg(e)
|
||||||
|
self.msg("Calling 'Apply Transformations' extension failed. Maybe the extension is not installed. You can download it from official InkScape Gallery. Skipping ...")
|
||||||
|
|
||||||
so.min_threshold = self.svg.unittouu(str(so.min_threshold) + self.svg.unit)
|
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)
|
so.max_threshold = self.svg.unittouu(str(so.max_threshold) + self.svg.unit)
|
||||||
unit_factor = 1.0 / self.svg.uutounit(1.0, so.unit)
|
unit_factor = 1.0 / self.svg.uutounit(1.0, so.unit)
|
||||||
@ -48,13 +73,18 @@ class FilterByLengthArea(inkex.EffectExtension):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if len(self.svg.selected) > 0:
|
if len(self.svg.selected) > 0:
|
||||||
elements = self.svg.selection.filter(inkex.PathElement).values()
|
elements = self.svg.selection.filter().values()
|
||||||
else:
|
else:
|
||||||
elements = self.document.xpath("//svg:path", namespaces=inkex.NSS)
|
elements = self.document.xpath("//svg:path", namespaces=inkex.NSS)
|
||||||
|
|
||||||
if so.debug is True:
|
if so.debug is True:
|
||||||
inkex.utils.debug("Collecting elements ...")
|
inkex.utils.debug("Collecting elements ...")
|
||||||
|
|
||||||
for element in elements:
|
for element in elements:
|
||||||
|
# additional option to apply transformations. As we clear up some groups to form new layers, we might lose translations, rotations, etc.
|
||||||
|
if so.apply_transformations is True and applyTransformationsAvailable is True:
|
||||||
|
apply_transformations.ApplyTransformations().recursiveFuseTransform(element)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
csp = element.path.transform(element.composed_transform()).to_superpath()
|
csp = element.path.transform(element.composed_transform()).to_superpath()
|
||||||
|
|
||||||
@ -65,7 +95,7 @@ class FilterByLengthArea(inkex.EffectExtension):
|
|||||||
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
|
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
|
||||||
if so.debug is True:
|
if so.debug is True:
|
||||||
inkex.utils.debug("id={}, area={:0.3f}{}^2".format(element.get('id'), area, so.unit))
|
inkex.utils.debug("id={}, area={:0.3f}{}^2".format(element.get('id'), area, so.unit))
|
||||||
to_sort.append({'element': element, 'value': area})
|
to_sort.append({'element': element, 'value': area, 'type': 'area'})
|
||||||
|
|
||||||
elif so.measure == "length":
|
elif so.measure == "length":
|
||||||
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
||||||
@ -75,7 +105,7 @@ class FilterByLengthArea(inkex.EffectExtension):
|
|||||||
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
|
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
|
||||||
if so.debug is True:
|
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))
|
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})
|
to_sort.append({'element': element, 'value': stotal, 'type': 'length'})
|
||||||
|
|
||||||
elif so.measure == "nodes":
|
elif so.measure == "nodes":
|
||||||
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
||||||
@ -86,7 +116,7 @@ class FilterByLengthArea(inkex.EffectExtension):
|
|||||||
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
|
(so.min_filter_enable is False and so.max_filter_enable is False): #complete selection
|
||||||
if so.debug is True:
|
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))
|
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})
|
to_sort.append({'element': element, 'value': nodes, 'type': 'nodes'})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
#inkex.utils.debug(e)
|
#inkex.utils.debug(e)
|
||||||
@ -96,23 +126,77 @@ class FilterByLengthArea(inkex.EffectExtension):
|
|||||||
element = to_sort[i].get('element')
|
element = to_sort[i].get('element')
|
||||||
if so.delete is True:
|
if so.delete is True:
|
||||||
element.delete()
|
element.delete()
|
||||||
|
|
||||||
if so.delete is True:
|
if so.delete is True:
|
||||||
return #quit here
|
return #quit here
|
||||||
|
|
||||||
if so.sort_by_asc is True:
|
if so.sort_by_value is True:
|
||||||
to_sort.sort(key=lambda x: x.get('value')) #sort by target value
|
to_sort.sort(key=lambda x: x.get('value')) #sort by target value
|
||||||
|
|
||||||
|
if so.sort_by_id is True:
|
||||||
|
to_sort.sort(key=lambda x: x.get('element').get('id')) #sort by id. will override previous value sort
|
||||||
|
|
||||||
|
if so.group is True:
|
||||||
|
group = inkex.Group(id=self.svg.get_unique_id("filtered"))
|
||||||
|
self.svg.get_current_layer().add(group)
|
||||||
|
|
||||||
|
allIds = self.svg.get_ids()
|
||||||
|
newIds = [] #we pre-populate this
|
||||||
|
for i in range(0, len(to_sort)):
|
||||||
|
newIds.append("{}{}".format(element.tag.replace('{http://www.w3.org/2000/svg}',''), i)) #should be element tag 'path'
|
||||||
|
|
||||||
for i in range(0, len(to_sort)):
|
for i in range(0, len(to_sort)):
|
||||||
element = to_sort[i].get('element')
|
element = to_sort[i].get('element')
|
||||||
if so.reverse_sort is True:
|
|
||||||
|
if so.rename_ids is True:
|
||||||
|
if newIds[i] in allIds: #already exist. lets rename that one before using it's id for the recent element
|
||||||
|
try:
|
||||||
|
renameIdPre = element.get('id') + "-"
|
||||||
|
renameId = self.svg.get_unique_id(renameIdPre)
|
||||||
|
#inkex.utils.debug("Trying to rename {} to {}".format(element.get('id'), renameId))
|
||||||
|
originalElement = self.svg.getElementById(newIds[i])
|
||||||
|
originalElement.set('id', renameId)
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
#inkex.utils.debug(e)
|
||||||
|
element.set('id', newIds[i])
|
||||||
|
|
||||||
|
if so.sort_by_value is True:
|
||||||
|
if so.reverse_sort_value is True:
|
||||||
idx = len(element.getparent())
|
idx = len(element.getparent())
|
||||||
else:
|
else:
|
||||||
idx = 0
|
idx = 0
|
||||||
element.getparent().insert(idx, element)
|
element.getparent().insert(idx, element)
|
||||||
if so.colorize is True:
|
|
||||||
|
if so.sort_by_id is True:
|
||||||
|
if so.reverse_sort_id is True:
|
||||||
|
idx = len(element.getparent())
|
||||||
|
else:
|
||||||
|
idx = 0
|
||||||
|
element.getparent().insert(idx, element)
|
||||||
|
|
||||||
|
if so.color_mode == "colorize_rainbow":
|
||||||
color = colorsys.hsv_to_rgb(i / float(len(to_sort)), 1.0, 1.0)
|
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)
|
element.style['stroke'] = '#%02x%02x%02x' % tuple(int(x * 255) for x in color)
|
||||||
|
|
||||||
|
if so.color_mode == "colorize_single":
|
||||||
|
element.style['stroke'] = so.color_single
|
||||||
|
|
||||||
|
if so.set_labels is True:
|
||||||
|
element.set('inkscape:label', "{}={}".format(to_sort[i].get('type'), to_sort[i].get('value')))
|
||||||
|
|
||||||
|
if so.remove_labels is True:
|
||||||
|
element.pop('inkscape:label')
|
||||||
|
|
||||||
|
if so.group is True:
|
||||||
|
group.append(element)
|
||||||
|
|
||||||
|
if so.cleanup == True:
|
||||||
|
try:
|
||||||
|
import remove_empty_groups
|
||||||
|
remove_empty_groups.RemoveEmptyGroups.effect(self)
|
||||||
|
except:
|
||||||
|
self.msg("Calling 'Remove Empty Groups' extension failed. Maybe the extension is not installed. You can download it from official InkScape Gallery. Skipping ...")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
FilterByLengthArea().run()
|
FilterByLengthArea().run()
|
@ -3,7 +3,10 @@
|
|||||||
"name": "Filter By Length/Area",
|
"name": "Filter By Length/Area",
|
||||||
"id": "fablabchemnitz.de.filter_by_length_area",
|
"id": "fablabchemnitz.de.filter_by_length_area",
|
||||||
"path": "filter_by_length_area",
|
"path": "filter_by_length_area",
|
||||||
"dependent_extensions": null,
|
"dependent_extensions": [
|
||||||
|
"apply_transformations",
|
||||||
|
"remove_empty_groups"
|
||||||
|
],
|
||||||
"original_name": "Filter By Length/Area",
|
"original_name": "Filter By Length/Area",
|
||||||
"original_id": "com.filter_by_length_area",
|
"original_id": "com.filter_by_length_area",
|
||||||
"license": "GNU GPL v3",
|
"license": "GNU GPL v3",
|
||||||
|
@ -50,7 +50,7 @@ class StylesToLayers(inkex.EffectExtension):
|
|||||||
pars.add_argument("--parsecolors",default = "hexval", help = "Sort colors by")
|
pars.add_argument("--parsecolors",default = "hexval", help = "Sort colors by")
|
||||||
pars.add_argument("--subdividethreshold", type=int, default = 1, help = "Threshold for splitting into sub layers")
|
pars.add_argument("--subdividethreshold", type=int, default = 1, help = "Threshold for splitting into sub layers")
|
||||||
pars.add_argument("--decimals", type=int, default = 1, help = "Decimal tolerance")
|
pars.add_argument("--decimals", type=int, default = 1, help = "Decimal tolerance")
|
||||||
pars.add_argument("--cleanup", type=inkex.Boolean, default = True, help = "Decimal tolerance")
|
pars.add_argument("--cleanup", type=inkex.Boolean, default = True, help = "Cleanup all unused groups/layers (requires separate extension)")
|
||||||
pars.add_argument("--put_unfiltered", type=inkex.Boolean, default = False, help = "Put unfiltered elements to a separate layer")
|
pars.add_argument("--put_unfiltered", type=inkex.Boolean, default = False, help = "Put unfiltered elements to a separate layer")
|
||||||
pars.add_argument("--show_info", type=inkex.Boolean, default = False, help = "Show elements which have no style attributes to filter")
|
pars.add_argument("--show_info", type=inkex.Boolean, default = False, help = "Show elements which have no style attributes to filter")
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user