added more options to contour scanner, fixed bugs
This commit is contained in:
parent
8eac0bcfb3
commit
7c2de7d7e3
@ -8,17 +8,30 @@
|
||||
<param name="show_debug" type="bool" gui-text="Show debug infos">false</param>
|
||||
<param name="break_apart" type="bool" gui-text="Break apart input" gui-description="Break apart input paths into sub paths. Modifies original paths">false</param>
|
||||
<param name="handle_groups" type="bool" gui-text="Handle groups" gui-description="Also looks for paths in groups which are in the current selection. Note: The generated results have a different structure (less granularity due to grouping) than directly selected paths. The colorization for non-intersected paths will be different too.">false</param>
|
||||
<param name="path_types" type="optiongroup" appearance="combo" gui-text="Scanning selection" gui-description="Process open paths by other open paths, closed paths by other closed paths, or all paths by all other paths">
|
||||
<option value="both">all:all paths</option>
|
||||
<option value="open_paths">open:open paths</option>
|
||||
<option value="closed_paths">closed:closed paths</option>
|
||||
</param>
|
||||
<param name="flattenbezier" type="bool" gui-text="Quantization (flatten bezier curves to polylines)" gui-description="Convert bezier curves to polylines.">true</param>
|
||||
<param name="flatness" type="float" min="0.001" max="99999.000" precision="3" gui-text="Flatness (tolerance)" gui-description="Minimum flatness = 0.001. The smaller the value the more fine segments you will get (quantization). Large values might destroy the line continuity.">0.100</param>
|
||||
<param name="decimals" type="int" min="0" max="16" gui-text="Decimals" gui-description="Accuracy for sub split lines / lines trimmed by shapely (default: 3)">3</param>
|
||||
<param name="snap_tolerance" type="float" min="0.01" max="10.0" gui-text="Snap tolerance" gui-description="Snap tolerance for intersection points on paths (default: 0.1)">0.1</param>
|
||||
<param name="draw_subsplit" type="bool" gui-text="Draw sub split lines (for debugging purposes)" gui-description="Draws polylines">false</param>
|
||||
<param name="draw_subsplit" type="bool" gui-text="Draw sub split lines (for debugging purposes)" gui-description="Draws polylines. Will be automatically enabled if any highlighting below is activated.">false</param>
|
||||
</page>
|
||||
<page name="tab_scanning" gui-text="Scanning and Trimming">
|
||||
<hbox>
|
||||
<vbox>
|
||||
<label appearance="header">Scanning</label>
|
||||
<label appearance="header">Removing</label>
|
||||
<param name="remove_polylines" type="bool" gui-text="Remove original polylines paths">false</param>
|
||||
<param name="remove_beziers" type="bool" gui-text="Remove original beziers paths">false</param>
|
||||
<param name="remove_opened" type="bool" gui-text="Remove original opened paths">false</param>
|
||||
<param name="remove_closed" type="bool" gui-text="Remove original closed paths">false</param>
|
||||
<param name="remove_self_intersecting" type="bool" gui-text="Remove original self-intersecting paths">false</param>
|
||||
<separator/>
|
||||
<label appearance="header">Highlighting</label>
|
||||
<param name="highlight_polylines" type="bool" gui-text="Highlight polyline paths">false</param>
|
||||
<param name="highlight_beziers" type="bool" gui-text="Highlight bezier paths">false</param>
|
||||
<param name="highlight_opened" type="bool" gui-text="Highlight opened paths">false</param>
|
||||
<param name="highlight_closed" type="bool" gui-text="Highlight closed paths">false</param>
|
||||
<param name="highlight_self_intersecting" type="bool" gui-text="Highlight self-intersecting paths" gui-description="Requires to draw sub split lines. Will override highlighting colors for open and closed paths (if those options are enabled)">false</param>
|
||||
@ -28,11 +41,6 @@
|
||||
<separator/>
|
||||
<vbox>
|
||||
<label appearance="header">Trimming</label>
|
||||
<param name="path_types" type="optiongroup" appearance="combo" gui-text="Trimming selection" gui-description="Trim open paths by other open paths, closed paths by other closed paths, or all paths by all other paths">
|
||||
<option value="both">all:all paths</option>
|
||||
<option value="open_paths">open:open paths</option>
|
||||
<option value="closed_paths">closed:closed paths</option>
|
||||
</param>
|
||||
<param name="draw_trimmed" type="bool" gui-text="Draw trimmed lines">false</param>
|
||||
<param name="combine_nonintersects" type="bool" gui-text="Chain + combine non-intersected lines">true</param>
|
||||
<param name="remove_duplicates" type="bool" gui-text="Remove duplicate trim lines">true</param>
|
||||
@ -51,8 +59,10 @@
|
||||
<param name="removefillsetstroke" type="bool" gui-text="Remove fill and define stroke" gui-description="Modifies original path style">false</param>
|
||||
<param name="apply_original_style" type="bool" gui-text="Original style for trimmed lines" gui-description="Apply original path style to trimmed lines.">true</param>
|
||||
<label appearance="header">Scanning Colors</label>
|
||||
<param name="color_opened" type="color" appearance="colorbutton" gui-text="Color for opened contours">4012452351</param>
|
||||
<param name="color_closed" type="color" appearance="colorbutton" gui-text="Color for closed contours">2330080511</param>
|
||||
<param name="color_polyline" type="color" appearance="colorbutton" gui-text="Color for polyline paths">4289703935</param>
|
||||
<param name="color_bezier" type="color" appearance="colorbutton" gui-text="Color for bezier paths">258744063</param>
|
||||
<param name="color_opened" type="color" appearance="colorbutton" gui-text="Color for opened paths">4012452351</param>
|
||||
<param name="color_closed" type="color" appearance="colorbutton" gui-text="Color for closed paths">2330080511</param>
|
||||
<param name="color_self_intersecting_paths" type="color" appearance="colorbutton" gui-text="Color for self-intersecting contours">2593756927</param>
|
||||
<param name="color_subsplit" type="color" appearance="colorbutton" gui-text="Color for sub split lines">1630897151</param>
|
||||
<param name="color_self_intersections" type="color" appearance="colorbutton" gui-text="Color for self-intersecting line points">6320383</param>
|
||||
@ -76,6 +86,7 @@
|
||||
- Does not find overlapping colinear lines (sweep line algorithm does not intersect them)
|
||||
|
||||
Tips:
|
||||
- If nothings is selected, the whole document will be processed, regardless of groups. In contrast, if you made a custom selection, check to handle or not to handle groups.
|
||||
- Convert your strokes and objects to paths before
|
||||
- Does not work for clones. You will need to unlink them before
|
||||
- Use extensions to filter short/unrequired lines
|
||||
|
@ -41,6 +41,22 @@ Mail: mario.voigt@stadtfabrikanten.org
|
||||
Date: 09.08.2020 (extension originally called "Contour Scanner")
|
||||
Last patch: 01.06.2021
|
||||
License: GNU GPL v3
|
||||
|
||||
|
||||
efficiently find overlapping lines
|
||||
- loope durch alle straihgt lines und berechne deren steigung -< einsortieren der linien nach steigung
|
||||
- wenn die steigung noch nicht erfasst wurde, dann adde die line in eine collection aller in frage kommenden linien
|
||||
- loope durch die vorfilterung und check für shapely
|
||||
|
||||
intersects() is equivalent to the OR-ing of contains(), crosses(), equals(), touches(), and within().
|
||||
So there might be some cases where two lines intersect eachother without crossing,
|
||||
in particular when one line contains another or when two lines are equals.
|
||||
More specifically:
|
||||
crosses() returns True [...] if the dimension of the intersection is less than the dimension of the one or the other.
|
||||
So if two lines overlap, they won't be considered as "crossing".
|
||||
intersection() will return a geometric object.
|
||||
|
||||
|
||||
'''
|
||||
|
||||
import sys
|
||||
@ -122,7 +138,6 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
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')
|
||||
return
|
||||
return pathElements
|
||||
|
||||
if self.options.break_apart is True:
|
||||
breakApartElements = None
|
||||
@ -133,6 +148,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
if self.options.show_debug is True:
|
||||
self.msg("total processing paths count: {}".format(len(pathElements)))
|
||||
|
||||
return pathElements
|
||||
|
||||
def findGroup(self, groupId):
|
||||
''' check if a group with a given id exists or not. Returns None if not found, else returns the group element '''
|
||||
@ -279,8 +295,12 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
if element.path not in totalTrimPaths:
|
||||
totalTrimPaths.append(element.path)
|
||||
else:
|
||||
if self.options.show_debug is True:
|
||||
self.msg("Deleting {}".format(element.get('id')))
|
||||
element.delete()
|
||||
if len(trimGroup) == 0:
|
||||
if self.options.show_debug is True:
|
||||
self.msg("Deleting {}".format(trimGroup.get('id')))
|
||||
trimGroup.delete()
|
||||
|
||||
|
||||
@ -384,20 +404,24 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
|
||||
#Settings - General
|
||||
pars.add_argument("--show_debug", type=inkex.Boolean, default=False, help="Show debug infos")
|
||||
pars.add_argument("--path_types", default="closed_paths", help="Apply for closed paths, open paths or both")
|
||||
pars.add_argument("--break_apart", type=inkex.Boolean, default=False, help="Break apart input paths into sub paths")
|
||||
pars.add_argument("--handle_groups", type=inkex.Boolean, default=False, help="Also looks for paths in groups which are in the current selection")
|
||||
pars.add_argument("--path_types", default="closed_paths", help="Process open paths by other open paths, closed paths by other closed paths, or all paths by all other paths")
|
||||
pars.add_argument("--flattenbezier", type=inkex.Boolean, default=True, help="Flatten bezier curves to polylines")
|
||||
pars.add_argument("--flatness", type=float, default=0.1, help="Minimum flatness = 0.001. The smaller the value the more fine segments you will get (quantization). Large values might destroy the line continuity.")
|
||||
pars.add_argument("--decimals", type=int, default=3, help="Accuracy for sub split lines / lines trimmed by shapely")
|
||||
pars.add_argument("--snap_tolerance", type=float, default=0.1, help="Snap tolerance for intersection points")
|
||||
|
||||
#Settings - Scanning
|
||||
pars.add_argument("--remove_polylines", type=inkex.Boolean, default=False, help="Remove original polyline paths")
|
||||
pars.add_argument("--remove_beziers", type=inkex.Boolean, default=False, help="Remove original bezier paths")
|
||||
pars.add_argument("--remove_opened", type=inkex.Boolean, default=False, help="Remove original opened paths")
|
||||
pars.add_argument("--remove_closed", type=inkex.Boolean, default=False, help="Remove original closed paths")
|
||||
pars.add_argument("--remove_self_intersecting", type=inkex.Boolean, default=False, help="Remove original self-intersecting paths")
|
||||
pars.add_argument("--highlight_opened", type=inkex.Boolean, default=False, help="Highlight opened contours")
|
||||
pars.add_argument("--highlight_closed", type=inkex.Boolean, default=False, help="Highlight closed contours")
|
||||
pars.add_argument("--highlight_polylines", type=inkex.Boolean, default=False, help="Highlight polyline paths")
|
||||
pars.add_argument("--highlight_beziers", type=inkex.Boolean, default=False, help="Highlight bezier paths")
|
||||
pars.add_argument("--highlight_opened", type=inkex.Boolean, default=False, help="Highlight opened paths")
|
||||
pars.add_argument("--highlight_closed", type=inkex.Boolean, default=False, help="Highlight closed paths")
|
||||
pars.add_argument("--highlight_self_intersecting", type=inkex.Boolean, default=False, help="Highlight self-intersecting contours")
|
||||
pars.add_argument("--draw_subsplit", type=inkex.Boolean, default=False, help="Draw sub split lines (polylines)")
|
||||
pars.add_argument("--visualize_self_intersections", type=inkex.Boolean, default=False, help="Visualize self-intersecting path points")
|
||||
@ -418,8 +442,10 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
pars.add_argument("--apply_original_style", type=inkex.Boolean, default=True, help="Apply original path style to trimmed lines")
|
||||
|
||||
#Style - Scanning Colors
|
||||
pars.add_argument("--color_opened", type=Color, default='4012452351', help="Color for opened contours")
|
||||
pars.add_argument("--color_closed", type=Color, default='2330080511', help="Color for closed contours")
|
||||
pars.add_argument("--color_polyline", type=Color, default='4289703935', help="Color for polyline paths")
|
||||
pars.add_argument("--color_bezier", type=Color, default='258744063', help="Color for bezier paths")
|
||||
pars.add_argument("--color_opened", type=Color, default='4012452351', help="Color for opened paths")
|
||||
pars.add_argument("--color_closed", type=Color, default='2330080511', help="Color for closed paths")
|
||||
pars.add_argument("--color_self_intersecting_paths", type=Color, default='2593756927', help="Color for self-intersecting contours")
|
||||
pars.add_argument("--color_subsplit", type=Color, default='1630897151', help="Color for sub split lines")
|
||||
pars.add_argument("--color_self_intersections", type=Color, default='6320383', help="Color for self-intersecting line points")
|
||||
@ -434,35 +460,29 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
def effect(self):
|
||||
|
||||
so = self.options
|
||||
|
||||
#warn if there is nothing to visualize
|
||||
if \
|
||||
so.keep_original_after_trim is False and \
|
||||
so.remove_opened is True and \
|
||||
so.remove_closed is True and \
|
||||
so.visualize_self_intersections is False and \
|
||||
so.visualize_global_intersections is False and \
|
||||
so.draw_subsplit is False and \
|
||||
so.draw_trimmed is False:
|
||||
self.msg("Nothing to draw. Select at least one visualization option.")
|
||||
return
|
||||
|
||||
#some dependent configuration for drawing modes
|
||||
if \
|
||||
so.highlight_beziers is True or \
|
||||
so.highlight_polylines is True or \
|
||||
so.highlight_opened is True or \
|
||||
so.highlight_closed is True or \
|
||||
so.highlight_self_intersecting is True:
|
||||
so.draw_subsplit = True
|
||||
if so.draw_subsplit is False:
|
||||
so.highlight_beziers = False
|
||||
so.highlight_polylines = False
|
||||
so.highlight_open = False
|
||||
so.highlight_closed = False
|
||||
so.highlight_self_intersecting = False
|
||||
|
||||
#some constant stuff / styles
|
||||
keepOpenPathStyle = {'stroke': str(so.color_opened), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
keepClosedPathStyle = {'stroke': str(so.color_closed), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
keepSelfIntersectingPathStyle = {'stroke': str(so.color_self_intersecting_paths), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
subSplitLineStyle = {'stroke': str(so.color_subsplit), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
polylinePathStyle = {'stroke': str(so.color_polyline), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
bezierPathStyle = {'stroke': str(so.color_bezier), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
openPathStyle = {'stroke': str(so.color_opened), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
closedPathStyle = {'stroke': str(so.color_closed), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
selfIntersectingPathStyle = {'stroke': str(so.color_self_intersecting_paths), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
basicSubSplitLineStyle = {'stroke': str(so.color_subsplit), 'fill': 'none', 'stroke-width': so.strokewidth}
|
||||
|
||||
''' 1 //
|
||||
get all paths which are within selection or in document and generate sub split lines
|
||||
@ -496,25 +516,25 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
Note: highlighting open/closed/self-intersecting contours does work best if you break apart
|
||||
combined paths before.
|
||||
'''
|
||||
pathIsClosed = False
|
||||
isClosed = False
|
||||
path_arrays = path.to_arrays()
|
||||
if path_arrays[-1][0] == 'Z' or \
|
||||
(path_arrays[-1][0] == 'L' and path_arrays[0][1] == path_arrays[-1][1]) or \
|
||||
(path_arrays[-1][0] == 'C' and path_arrays[0][1] == [path_arrays[-1][1][-2], path_arrays[-1][1][-1]]) \
|
||||
: #if first is last point the path is also closed. The "Z" command is not required
|
||||
pathIsClosed = True
|
||||
isClosed = True
|
||||
|
||||
#Check if we should delete the path or not
|
||||
if so.remove_opened is True and pathIsClosed is False:
|
||||
if so.remove_opened is True and isClosed is False:
|
||||
pathElement.delete()
|
||||
continue #skip this loop iteration
|
||||
if so.remove_closed is True and pathIsClosed is True:
|
||||
if so.remove_closed is True and isClosed is True:
|
||||
pathElement.delete()
|
||||
continue #skip this loop iteration
|
||||
|
||||
#Check if we should skip or process the path anyway
|
||||
if so.path_types == 'open_paths' and pathIsClosed is True: continue #skip this loop iteration
|
||||
elif so.path_types == 'closed_paths' and pathIsClosed is False: continue #skip this loop iteration
|
||||
if so.path_types == 'open_paths' and isClosed is True: continue #skip this loop iteration
|
||||
elif so.path_types == 'closed_paths' and isClosed is False: continue #skip this loop iteration
|
||||
elif so.path_types == 'both': pass
|
||||
|
||||
#adjust the style of original paths if desired. Has influence to the finally trimmed lines style results too!
|
||||
@ -544,6 +564,12 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
if so.show_debug is True:
|
||||
self.msg("sub path in {} is bezier: {}".format(originalPathId, isBezier))
|
||||
|
||||
deleteFlag = False
|
||||
if so.remove_beziers is True and isBezier is True:
|
||||
deleteFlag = True
|
||||
if so.remove_polylines is True and isBezier is False:
|
||||
deleteFlag = True
|
||||
|
||||
#self.msg("sub path in {} = {}".format(element.get('id'), subPath))
|
||||
#flatten the subpath if wanted
|
||||
subPathData = CubicSuperPath(subPath)
|
||||
@ -582,7 +608,9 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
line.path = [['M', [x1, y1]], ['L', [x2, y2]]]
|
||||
if pathElement.getparent() != self.svg.root:
|
||||
line.path = line.path.transform(-pathElement.getparent().composed_transform())
|
||||
line.style = subSplitLineStyle
|
||||
line.style = basicSubSplitLineStyle
|
||||
line.attrib['isBezier'] = str(isBezier)
|
||||
line.attrib['isClosed'] = str(isClosed)
|
||||
subSplitTrimLineGroup.add(line)
|
||||
|
||||
subSplitLines.append([(x1, y1), (x2, y2)])
|
||||
@ -591,19 +619,32 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
subSplitIsBezier.append(isBezier) #some dirty flag we need
|
||||
subSplitOriginalPathIds.append(originalPathId) #some dirty flag we need
|
||||
|
||||
if deleteFlag is True:
|
||||
pathElement.delete()
|
||||
continue #skip the subPath loop
|
||||
|
||||
if so.draw_subsplit is True:
|
||||
#check for open/closed again (at first we checked for the <maybe> combined path. Now we can do for each sub path too!
|
||||
subPathIsClosed = False
|
||||
if subSplitLines[0][0] == subSplitLines[-1][1]:
|
||||
subPathIsClosed = True
|
||||
#subPathIsClosed = False
|
||||
#if subSplitLines[0][0] == subSplitLines[-1][1]:
|
||||
# subPathIsClosed = True
|
||||
|
||||
for subSplitLine in subSplitTrimLineGroup:
|
||||
if subPathIsClosed is True:
|
||||
if subSplitLine.attrib['isBezier'] == 'True':
|
||||
if so.highlight_beziers is True:
|
||||
subSplitLine.style = bezierPathStyle
|
||||
else:
|
||||
if so.highlight_polylines is True:
|
||||
subSplitLine.style = polylinePathStyle
|
||||
|
||||
if subSplitLine.attrib['isClosed'] == 'True':
|
||||
#if subPathIsClosed is True:
|
||||
if so.highlight_closed is True:
|
||||
subSplitLine.style = keepClosedPathStyle
|
||||
subSplitLine.style = closedPathStyle
|
||||
else:
|
||||
if so.highlight_opened is True:
|
||||
subSplitLine.style = keepOpenPathStyle
|
||||
|
||||
subSplitLine.style = openPathStyle
|
||||
|
||||
#check for self intersections
|
||||
selfIntersectionPoints = isect_segments(subSplitLines, validate=True)
|
||||
if len(selfIntersectionPoints) > 0:
|
||||
@ -612,7 +653,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
||||
if so.draw_subsplit is True:
|
||||
if so.highlight_self_intersecting is True:
|
||||
for subSplitLine in subSplitTrimLineGroup:
|
||||
subSplitLine.style = keepSelfIntersectingPathStyle #adjusts line color
|
||||
subSplitLine.style = selfIntersectingPathStyle #adjusts line color
|
||||
#delete cosmetic sub split lines if desired
|
||||
if so.remove_self_intersecting:
|
||||
subSplitTrimLineGroup.delete()
|
||||
|
Reference in New Issue
Block a user