some refactorings in contour scanner
This commit is contained in:
parent
f1c189919b
commit
1184c9fbdf
@ -78,7 +78,7 @@ intersectedVerb = "-intersected-"
|
|||||||
|
|
||||||
class ContourScannerAndTrimmer(inkex.EffectExtension):
|
class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||||
|
|
||||||
def breakContours(self, element, breakelements = None):
|
def break_contours(self, element, breakelements = None):
|
||||||
'''
|
'''
|
||||||
this does the same as "CTRL + SHIFT + K"
|
this does the same as "CTRL + SHIFT + K"
|
||||||
This functions honors the fact of absolute or relative paths!
|
This functions honors the fact of absolute or relative paths!
|
||||||
@ -113,22 +113,22 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
breakelements.append(replacedelement)
|
breakelements.append(replacedelement)
|
||||||
element.delete()
|
element.delete()
|
||||||
for child in element.getchildren():
|
for child in element.getchildren():
|
||||||
self.breakContours(child, breakelements)
|
self.break_contours(child, breakelements)
|
||||||
return breakelements
|
return breakelements
|
||||||
|
|
||||||
|
|
||||||
def getChildPaths(self, element, elements = None):
|
def get_child_paths(self, element, elements = None):
|
||||||
''' a function to get child paths from elements (used by "handling groups" option) '''
|
''' a function to get child paths from elements (used by "handling groups" option) '''
|
||||||
if elements == None:
|
if elements == None:
|
||||||
elements = []
|
elements = []
|
||||||
if element.tag == inkex.addNS('path','svg'):
|
if element.tag == inkex.addNS('path','svg'):
|
||||||
elements.append(element)
|
elements.append(element)
|
||||||
for child in element.getchildren():
|
for child in element.getchildren():
|
||||||
self.getChildPaths(child, elements)
|
self.get_child_paths(child, elements)
|
||||||
return elements
|
return elements
|
||||||
|
|
||||||
|
|
||||||
def getPathElements(self):
|
def get_path_elements(self):
|
||||||
''' get all path elements, either from selection or from whole document. Uses options '''
|
''' get all path elements, either from selection or from whole document. Uses options '''
|
||||||
pathElements = []
|
pathElements = []
|
||||||
if len(self.svg.selected) == 0: #if nothing selected we search for the complete document
|
if len(self.svg.selected) == 0: #if nothing selected we search for the complete document
|
||||||
@ -138,7 +138,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
pathElements = list(self.svg.selection.filter(PathElement).values())
|
pathElements = list(self.svg.selection.filter(PathElement).values())
|
||||||
else:
|
else:
|
||||||
for element in self.svg.selection.values():
|
for element in self.svg.selection.values():
|
||||||
pathElements = self.getChildPaths(element, pathElements)
|
pathElements = self.get_child_paths(element, pathElements)
|
||||||
|
|
||||||
if len(pathElements) == 0:
|
if len(pathElements) == 0:
|
||||||
self.msg('Selection appears to be empty or does not contain any valid svg:path nodes. Try to cast your objects to paths using CTRL + SHIFT + C or strokes to paths using CTRL + ALT + C')
|
self.msg('Selection appears to be empty or does not contain any valid svg:path nodes. Try to cast your objects to paths using CTRL + SHIFT + C or strokes to paths using CTRL + ALT + C')
|
||||||
@ -147,7 +147,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
if self.options.break_apart is True:
|
if self.options.break_apart is True:
|
||||||
breakApartElements = None
|
breakApartElements = None
|
||||||
for pathElement in pathElements:
|
for pathElement in pathElements:
|
||||||
breakApartElements = self.breakContours(pathElement, breakApartElements)
|
breakApartElements = self.break_contours(pathElement, breakApartElements)
|
||||||
pathElements = breakApartElements
|
pathElements = breakApartElements
|
||||||
|
|
||||||
if self.options.show_debug is True:
|
if self.options.show_debug is True:
|
||||||
@ -156,7 +156,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
return pathElements
|
return pathElements
|
||||||
|
|
||||||
|
|
||||||
def findGroup(self, groupId):
|
def find_group(self, groupId):
|
||||||
''' check if a group with a given id exists or not. Returns None if not found, else returns the group element '''
|
''' check if a group with a given id exists or not. Returns None if not found, else returns the group element '''
|
||||||
groups = self.document.xpath('//svg:g', namespaces=inkex.NSS)
|
groups = self.document.xpath('//svg:g', namespaces=inkex.NSS)
|
||||||
for group in groups:
|
for group in groups:
|
||||||
@ -166,7 +166,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def adjustStyle(self, element):
|
def adjust_style(self, element):
|
||||||
''' Replace some style attributes of the given element '''
|
''' Replace some style attributes of the given element '''
|
||||||
if element.attrib.has_key('style'):
|
if element.attrib.has_key('style'):
|
||||||
style = element.get('style')
|
style = element.get('style')
|
||||||
@ -186,7 +186,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
element.set('style', 'stroke:#000000;stroke-opacity:1.0')
|
element.set('style', 'stroke:#000000;stroke-opacity:1.0')
|
||||||
|
|
||||||
|
|
||||||
def lineFromSegments(self, segs, i, decimals):
|
def line_from_segments(self, segs, i, decimals):
|
||||||
'''builds a straight line for the segment i and the next segment i+2. Returns both point XY coordinates'''
|
'''builds a straight line for the segment i and the next segment i+2. Returns both point XY coordinates'''
|
||||||
pseudoPath = Path(segs[i:i+2]).to_arrays()
|
pseudoPath = Path(segs[i:i+2]).to_arrays()
|
||||||
x1 = round(pseudoPath[0][1][-2], decimals)
|
x1 = round(pseudoPath[0][1][-2], decimals)
|
||||||
@ -237,8 +237,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
globalIntersectionGroup.add(globalIntersectionPointCircle)
|
globalIntersectionGroup.add(globalIntersectionPointCircle)
|
||||||
|
|
||||||
|
|
||||||
def buildTrimLineGroups(self, subSplitLineArray, subSplitIndex, globalIntersectionPoints,
|
def build_trim_line_group(self, subSplitLineArray, subSplitIndex, globalIntersectionPoints):
|
||||||
snap_tolerance, apply_style_to_trimmed):
|
|
||||||
''' make a group containing trimmed lines'''
|
''' make a group containing trimmed lines'''
|
||||||
|
|
||||||
#Check if we should skip or process the path anyway
|
#Check if we should skip or process the path anyway
|
||||||
@ -252,12 +251,12 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
|
|
||||||
trimLineStyle = {'stroke': str(self.options.color_trimmed), 'fill': 'none', 'stroke-width': self.options.strokewidth}
|
trimLineStyle = {'stroke': str(self.options.color_trimmed), 'fill': 'none', 'stroke-width': self.options.strokewidth}
|
||||||
|
|
||||||
linesWithSnappedIntersectionPoints = snap(ls, globalIntersectionPoints, snap_tolerance)
|
linesWithSnappedIntersectionPoints = snap(ls, globalIntersectionPoints, self.options.snap_tolerance)
|
||||||
trimGroupId = 'shapely-' + subSplitLineArray[subSplitIndex].attrib['id'].split("_")[0] #split at "_" (_ from subSplitId)
|
trimGroupId = 'shapely-' + subSplitLineArray[subSplitIndex].attrib['id'].split("_")[0] #split at "_" (_ from subSplitId)
|
||||||
trimGroupParentId = subSplitLineArray[subSplitIndex].attrib['id'].split(idPrefix+"-")[1].split("_")[0]
|
trimGroupParentId = subSplitLineArray[subSplitIndex].attrib['id'].split(idPrefix+"-")[1].split("_")[0]
|
||||||
trimGroupParent = self.svg.getElementById(trimGroupParentId)
|
trimGroupParent = self.svg.getElementById(trimGroupParentId)
|
||||||
trimGroupParentTransform = trimGroupParent.composed_transform()
|
trimGroupParentTransform = trimGroupParent.composed_transform()
|
||||||
trimGroup = self.findGroup(trimGroupId)
|
trimGroup = self.find_group(trimGroupId)
|
||||||
if trimGroup is None:
|
if trimGroup is None:
|
||||||
trimGroup = trimGroupParent.getparent().add(inkex.Group(id=trimGroupId))
|
trimGroup = trimGroupParent.getparent().add(inkex.Group(id=trimGroupId))
|
||||||
|
|
||||||
@ -271,7 +270,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
splitAt = [] #if the sub split line was split by an intersecting line we receive two trim lines with same assigned original path id!
|
splitAt = [] #if the sub split line was split by an intersecting line we receive two trim lines with same assigned original path id!
|
||||||
prevLine = None
|
prevLine = None
|
||||||
for j in range(len(trimLines)):
|
for j in range(len(trimLines)):
|
||||||
trimLineId = trimGroupId + "-" + str(subSplitIndex)
|
trimLineId = "{}-{}".format(trimGroupId, subSplitIndex)
|
||||||
splitAt.append(trimGroupId)
|
splitAt.append(trimGroupId)
|
||||||
if splitAt.count(trimGroupId) > 1: #we detected a lines with intersection on
|
if splitAt.count(trimGroupId) > 1: #we detected a lines with intersection on
|
||||||
trimLineId = trimLineId + self.svg.get_unique_id(intersectedVerb)
|
trimLineId = trimLineId + self.svg.get_unique_id(intersectedVerb)
|
||||||
@ -287,7 +286,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
trimLine.path = [['M', [x[0],y[0]]], ['L', [x[1],y[1]]]]
|
trimLine.path = [['M', [x[0],y[0]]], ['L', [x[1],y[1]]]]
|
||||||
if trimGroupParentTransform is not None:
|
if trimGroupParentTransform is not None:
|
||||||
trimLine.path = trimLine.path.transform(-trimGroupParentTransform)
|
trimLine.path = trimLine.path.transform(-trimGroupParentTransform)
|
||||||
if apply_style_to_trimmed is False:
|
if self.options.apply_style_to_trimmed is False:
|
||||||
trimLine.style = trimLineStyle
|
trimLine.style = trimLineStyle
|
||||||
else:
|
else:
|
||||||
trimLine.style = subSplitLineArray[subSplitIndex].attrib['originalPathStyle']
|
trimLine.style = subSplitLineArray[subSplitIndex].attrib['originalPathStyle']
|
||||||
@ -295,10 +294,10 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
return trimGroup
|
return trimGroup
|
||||||
|
|
||||||
|
|
||||||
def remove_duplicates(self, allTrimGroups, reverse_removal_order):
|
def remove_duplicates(self, allTrimGroups):
|
||||||
''' find duplicate lines in a given array [] of groups '''
|
''' find duplicate lines in a given array [] of groups '''
|
||||||
totalTrimPaths = []
|
totalTrimPaths = []
|
||||||
if reverse_removal_order is True:
|
if self.options.reverse_removal_order is True:
|
||||||
allTrimGroups = allTrimGroups[::-1]
|
allTrimGroups = allTrimGroups[::-1]
|
||||||
for trimGroup in allTrimGroups:
|
for trimGroup in allTrimGroups:
|
||||||
for element in trimGroup:
|
for element in trimGroup:
|
||||||
@ -314,7 +313,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
trimGroup.delete()
|
trimGroup.delete()
|
||||||
|
|
||||||
|
|
||||||
def combine_nonintersects(self, allTrimGroups, apply_style_to_trimmed):
|
def combine_nonintersects(self, allTrimGroups):
|
||||||
'''
|
'''
|
||||||
combine and chain all non intersected sub split lines which were trimmed at intersection points before.
|
combine and chain all non intersected sub split lines which were trimmed at intersection points before.
|
||||||
- At first we sort out all lines by their id:
|
- At first we sort out all lines by their id:
|
||||||
@ -357,7 +356,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
self.msg("trim group {} has {} combinable segments:".format(trimGroup.get('id'), len(newPathData)))
|
self.msg("trim group {} has {} combinable segments:".format(trimGroup.get('id'), len(newPathData)))
|
||||||
self.msg("{}".format(newPathData))
|
self.msg("{}".format(newPathData))
|
||||||
combinedPath.path = Path(newPathData)
|
combinedPath.path = Path(newPathData)
|
||||||
if apply_style_to_trimmed is False:
|
if self.options.apply_style_to_trimmed is False:
|
||||||
combinedPath.style = trimNonIntersectedStyle
|
combinedPath.style = trimNonIntersectedStyle
|
||||||
if totalIntersectionsAtPath == 0:
|
if totalIntersectionsAtPath == 0:
|
||||||
combinedPath.style = nonTrimLineStyle
|
combinedPath.style = nonTrimLineStyle
|
||||||
@ -372,7 +371,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
This function does not work yet.
|
This function does not work yet.
|
||||||
'''
|
'''
|
||||||
for trimGroup in allTrimGroups:
|
for trimGroup in allTrimGroups:
|
||||||
if trimGroup.attrib.has_key('isBezier') and trimGroup.attrib['isBezier'] == "True":
|
if trimGroup.attrib.has_key('originalPathIsBezier') and trimGroup.attrib['originalPathIsBezier'] == "True":
|
||||||
globalTParameters = []
|
globalTParameters = []
|
||||||
if self.options.show_debug is True:
|
if self.options.show_debug is True:
|
||||||
self.msg("{}: count of trim lines = {}".format(trimGroup.get('id'), len(trimGroup)))
|
self.msg("{}: count of trim lines = {}".format(trimGroup.get('id'), len(trimGroup)))
|
||||||
@ -497,7 +496,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
basicSubSplitLineStyle = {'stroke': str(so.color_subsplit), 'fill': 'none', 'stroke-width': so.strokewidth}
|
basicSubSplitLineStyle = {'stroke': str(so.color_subsplit), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||||
|
|
||||||
#get all paths which are within selection or in document and generate sub split lines
|
#get all paths which are within selection or in document and generate sub split lines
|
||||||
pathElements = self.getPathElements()
|
pathElements = self.get_path_elements()
|
||||||
|
|
||||||
subSplitLineArray = []
|
subSplitLineArray = []
|
||||||
|
|
||||||
@ -565,7 +564,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
continue #skip this loop iteration
|
continue #skip this loop iteration
|
||||||
|
|
||||||
if so.draw_subsplit is True:
|
if so.draw_subsplit is True:
|
||||||
subSplitLineGroup = pathElement.getparent().add(inkex.Group(id="{}-{}".format(idPrefix, pathElement.attrib["id"])))
|
subSplitLineGroup = pathElement.getparent().add(inkex.Group(id="{}-{}".format(idPrefix, originalPathId)))
|
||||||
|
|
||||||
#get all sub paths for the path of the element
|
#get all sub paths for the path of the element
|
||||||
subPaths, prev = [], 0
|
subPaths, prev = [], 0
|
||||||
@ -600,7 +599,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
#build polylines from segment data
|
#build polylines from segment data
|
||||||
subSplitLines = []
|
subSplitLines = []
|
||||||
for i in range(len(segs) - 1): #we could do the same routine to build up polylines using "for x, y in node.path.end_points". See "number nodes" extension
|
for i in range(len(segs) - 1): #we could do the same routine to build up polylines using "for x, y in node.path.end_points". See "number nodes" extension
|
||||||
x1, y1, x2, y2 = self.lineFromSegments(segs, i, so.decimals)
|
x1, y1, x2, y2 = self.line_from_segments(segs, i, so.decimals)
|
||||||
#self.msg("(y1 = {},y2 = {},x1 = {},x2 = {})".format(x1, y1, x2, y2))
|
#self.msg("(y1 = {},y2 = {},x1 = {},x2 = {})".format(x1, y1, x2, y2))
|
||||||
subSplitId = "{}-{}_{}".format(idPrefix, originalPathId, i)
|
subSplitId = "{}-{}_{}".format(idPrefix, originalPathId, i)
|
||||||
line = inkex.PathElement(id=subSplitId)
|
line = inkex.PathElement(id=subSplitId)
|
||||||
@ -674,7 +673,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
|
|
||||||
#adjust the style of original paths if desired. Has influence to the finally trimmed lines style results too!
|
#adjust the style of original paths if desired. Has influence to the finally trimmed lines style results too!
|
||||||
if so.removefillsetstroke is True:
|
if so.removefillsetstroke is True:
|
||||||
self.adjustStyle(pathElement)
|
self.adjust_style(pathElement)
|
||||||
|
|
||||||
#apply styles to original paths
|
#apply styles to original paths
|
||||||
if isRelative is True:
|
if isRelative is True:
|
||||||
@ -738,8 +737,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
'''
|
'''
|
||||||
allTrimGroups = [] #container to collect all trim groups for later on processing
|
allTrimGroups = [] #container to collect all trim groups for later on processing
|
||||||
for subSplitIndex in range(len(subSplitLineArray)):
|
for subSplitIndex in range(len(subSplitLineArray)):
|
||||||
trimGroup = self.buildTrimLineGroups(subSplitLineArray, subSplitIndex,
|
trimGroup = self.build_trim_line_group(subSplitLineArray, subSplitIndex, globalIntersectionPoints)
|
||||||
globalIntersectionPoints, so.snap_tolerance, so.apply_style_to_trimmed)
|
|
||||||
if trimGroup is not None:
|
if trimGroup is not None:
|
||||||
if trimGroup not in allTrimGroups:
|
if trimGroup not in allTrimGroups:
|
||||||
allTrimGroups.append(trimGroup)
|
allTrimGroups.append(trimGroup)
|
||||||
@ -752,10 +750,10 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
if so.bezier_trimming is True: self.trim_bezier(allTrimGroups)
|
if so.bezier_trimming is True: self.trim_bezier(allTrimGroups)
|
||||||
|
|
||||||
#check for duplicate trim lines and delete them if desired
|
#check for duplicate trim lines and delete them if desired
|
||||||
if so.remove_duplicates is True: self.remove_duplicates(allTrimGroups, so.reverse_removal_order)
|
if so.remove_duplicates is True: self.remove_duplicates(allTrimGroups)
|
||||||
|
|
||||||
#glue together all non-intersected sub split lines to larger path structures again (cleaning up).
|
#glue together all non-intersected sub split lines to larger path structures again (cleaning up).
|
||||||
if so.combine_nonintersects is True: self. combine_nonintersects(allTrimGroups, so.apply_style_to_trimmed)
|
if so.combine_nonintersects is True: self. combine_nonintersects(allTrimGroups)
|
||||||
|
|
||||||
#clean original paths if selected. This option is explicitely independent from remove_open, remove_closed
|
#clean original paths if selected. This option is explicitely independent from remove_open, remove_closed
|
||||||
if so.keep_original_after_trim is False:
|
if so.keep_original_after_trim is False:
|
||||||
|
Reference in New Issue
Block a user