more features for filter by extension, add some outside canvas checker
to lasercheck
This commit is contained in:
parent
8694cf108f
commit
f98e9719ab
@ -3,6 +3,7 @@
|
||||
<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>
|
||||
<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>
|
||||
<option value="cm">cm</option>
|
||||
@ -11,14 +12,20 @@
|
||||
<option value="pc">pc</option>
|
||||
<option value="in">in</option>
|
||||
</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>
|
||||
<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.">1.000</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_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.">10000000.000</param>
|
||||
<label appearance="header">Equation</label>
|
||||
<param name="measure" type="optiongroup" appearance="combo" gui-text="Measure by">
|
||||
<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_nodes" type="int" min="0" max="99999" gui-text="Max. nodes/<interval>">10000000</param>
|
||||
<label appearance="header">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>
|
||||
<effect>
|
||||
|
@ -18,23 +18,27 @@ from inkex.bezier import csplength, csparea
|
||||
class FilterByLengthArea(inkex.EffectExtension):
|
||||
|
||||
def add_arguments(self, pars):
|
||||
pars.add_argument('--debug', type=inkex.Boolean, default=False)
|
||||
pars.add_argument('--unit')
|
||||
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('--max_filter_enable', type=inkex.Boolean, default=False, help='Enable filtering max.')
|
||||
pars.add_argument('--max_threshold', type=float, default=10000000.000, help='Remove paths with an threshold bigger than this value')
|
||||
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('--measure', default="length")
|
||||
|
||||
def effect(self):
|
||||
|
||||
if self.options.min_filter_enable is False and self.options.max_filter_enable is False:
|
||||
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
|
||||
|
||||
self.options.min_threshold = self.svg.unittouu(str(self.options.min_threshold) + self.svg.unit)
|
||||
self.options.max_threshold = self.svg.unittouu(str(self.options.max_threshold) + self.svg.unit)
|
||||
unit_factor = 1.0 / self.svg.uutounit(1.0,self.options.unit)
|
||||
if self.options.min_threshold == 0 or self.options.max_threshold == 0:
|
||||
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)
|
||||
if so.min_threshold == 0 or so.max_threshold == 0:
|
||||
inkex.utils.debug("One or both tresholds are zero. Please adjust.")
|
||||
return
|
||||
|
||||
@ -47,21 +51,36 @@ class FilterByLengthArea(inkex.EffectExtension):
|
||||
try:
|
||||
csp = element.path.transform(element.composed_transform()).to_superpath()
|
||||
|
||||
if self.options.measure == "area":
|
||||
area = -csparea(csp) #is returned as negative value. we need to invert with -
|
||||
if self.options.min_filter_enable is True and area < (self.options.min_threshold * (unit_factor * unit_factor)):
|
||||
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 self.options.max_filter_enable is True and area >= (self.options.max_threshold * (unit_factor * unit_factor)):
|
||||
if so.max_filter_enable is True and area >= (so.max_threshold * (unit_factor * unit_factor)):
|
||||
element.delete()
|
||||
|
||||
elif self.options.measure == "length":
|
||||
elif so.measure == "length":
|
||||
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
||||
if self.options.min_filter_enable is True and stotal < (self.options.min_threshold * unit_factor):
|
||||
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 >= (self.options.max_threshold * unit_factor):
|
||||
if self.options.max_filter_enable is True and stotal >= (so.max_threshold * unit_factor):
|
||||
element.delete()
|
||||
|
||||
|
||||
elif so.measure == "nodes":
|
||||
slengths, stotal = csplength(csp) #get segment lengths and total length of path in document's internal unit
|
||||
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()
|
||||
|
||||
except Exception as e:
|
||||
#self.msg(e)
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -23,6 +23,7 @@
|
||||
<option value="1219x914">1219 x 914 mm (Fusion Pro 48)</option>
|
||||
</param>
|
||||
<separator/>
|
||||
<param name="elements_outside_canvas" type="bool" gui-text="Elements outside canvas">false</param>
|
||||
<param name="groups_and_layers" type="bool" gui-text="Groups and layers">false</param>
|
||||
<param name="clones" type="bool" gui-text="Clones">false</param>
|
||||
<param name="clippaths" type="bool" gui-text="Clippings">false</param>
|
||||
|
@ -11,6 +11,7 @@ class LaserCheck(inkex.EffectExtension):
|
||||
'''
|
||||
ToDos:
|
||||
- check for old styles which should be upgraded
|
||||
- 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
|
||||
'''
|
||||
|
||||
@ -20,7 +21,8 @@ class LaserCheck(inkex.EffectExtension):
|
||||
pars.add_argument('--show_issues_only', type=inkex.Boolean, default=False)
|
||||
pars.add_argument('--bbox', type=inkex.Boolean, default=False)
|
||||
pars.add_argument('--bbox_offset', type=float, default=5.000)
|
||||
pars.add_argument("--machine_size", default="812x508")
|
||||
pars.add_argument('--machine_size', default="812x508")
|
||||
pars.add_argument('--elements_outside_canvas', type=inkex.Boolean, default=False)
|
||||
pars.add_argument('--groups_and_layers', type=inkex.Boolean, default=False)
|
||||
pars.add_argument('--clones', type=inkex.Boolean, default=False)
|
||||
pars.add_argument('--clippaths', type=inkex.Boolean, default=False)
|
||||
@ -538,9 +540,56 @@ class LaserCheck(inkex.EffectExtension):
|
||||
round(self.svg.uutounit(str(heavyPath[2]), "mm"), 3),
|
||||
round(heavyPath[1] / self.svg.uutounit(str(heavyPath[2]), "mm"), 3)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
'''
|
||||
Elements outside canvas or touching the border. These are critical because they won't be lasered
|
||||
'''
|
||||
if so.checks == "check_all" or so.elements_outside_canvas is True:
|
||||
inkex.utils.debug("\n---------- Elements outside canvas or touching the border")
|
||||
elementsOutside = []
|
||||
for element in shapes:
|
||||
if element.tag != inkex.addNS('g', 'svg'):
|
||||
ebbox = element.bounding_box()
|
||||
precision = 3
|
||||
#inkex.utils.debug("{} | bbox: left = {:0.3f} right = {:0.3f} top = {:0.3f} bottom = {:0.3f}".format(element.get('id'), ebbox.left, ebbox.right, ebbox.top, ebbox.bottom))
|
||||
pagew = round(self.svg.unittouu(self.svg.get('width')), precision)
|
||||
pageh = round(self.svg.unittouu(self.svg.get('height')), precision)
|
||||
if round(ebbox.right, precision) == 0 or \
|
||||
round(ebbox.left, precision) == pagew or \
|
||||
round(ebbox.top, precision) == 0 or \
|
||||
round(ebbox.bottom, precision) == pageh:
|
||||
elementsOutside.append([element, "touching"])
|
||||
elif \
|
||||
round(ebbox.right, precision) < 0 or \
|
||||
round(ebbox.left, precision) > pagew or \
|
||||
round(ebbox.top, precision) < 0 or \
|
||||
round(ebbox.bottom, precision) > pageh:
|
||||
elementsOutside.append([element, "fully outside"])
|
||||
else: #fully inside or partially inside/outside. we check if one or more corners is outside the canvas
|
||||
rightOutside = False
|
||||
leftOutside = False
|
||||
topOutside = False
|
||||
bottomOutside = False
|
||||
if round(ebbox.right, precision) < 0 or round(ebbox.right, precision) > pagew:
|
||||
rightOutside = True
|
||||
if round(ebbox.left, precision) < 0 or round(ebbox.left, precision) > pagew:
|
||||
leftOutside = True
|
||||
if round(ebbox.top, precision) < 0 or round(ebbox.top, precision) > pageh:
|
||||
topOutside = True
|
||||
if round(ebbox.bottom, precision) < 0 or round(ebbox.bottom, precision) > pageh:
|
||||
bottomOutside = True
|
||||
if rightOutside is True or leftOutside is True or topOutside is True or bottomOutside is True:
|
||||
elementsOutside.append([element, "partially outside"])
|
||||
if self.options.show_issues_only is False:
|
||||
inkex.utils.debug("{} Elements outside canvas or touching the border in total".format(len(elementsOutside)))
|
||||
for elementOutside in elementsOutside:
|
||||
inkex.utils.debug("id={}, status={}".format(
|
||||
elementOutside[0].get('id'),
|
||||
elementOutside[1]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
'''
|
||||
Shapes like rectangles, ellipses, arcs, spirals should be converted to svg:path to have more
|
||||
|
Reference in New Issue
Block a user