#!/usr/bin/env python3 ''' Extension for InkScape 1.0 Features - Filter paths which are smaller/bigger than a given length or area Author: Mario Voigt / FabLab Chemnitz Mail: mario.voigt@stadtfabrikanten.org Date: 03.08.2020 Last patch: 21.10.2021 License: GNU GPL v3 ''' import inkex from inkex.bezier import csplength, csparea class FilterByLengthArea(inkex.EffectExtension): def add_arguments(self, pars): 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('--measure', default="length") def effect(self): if len(self.svg.selected) == 0: inkex.utils.debug("Your selection is empty.") return if self.options.min_filter_enable is False and self.options.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: inkex.utils.debug("One or both tresholds are zero. Please adjust.") return for element in self.document.xpath("//svg:path", namespaces=inkex.NSS): 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)): element.delete() if self.options.max_filter_enable is True and area >= (self.options.max_threshold * (unit_factor * unit_factor)): element.delete() elif self.options.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): element.delete() if self.options.max_filter_enable is True and stotal >= (self.options.max_threshold * unit_factor): element.delete() except Exception as e: pass if __name__ == '__main__': FilterByLengthArea().run()