fixed overlapping line scanning
This commit is contained in:
parent
3ca9c257f2
commit
adf720fa11
@ -13,7 +13,7 @@
|
|||||||
<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="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="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. Will be automatically enabled if any highlighting is activated.">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 is activated.">false</param>
|
||||||
<param name="remove_subsplit_collinear" type="bool" gui-text="Remove collinear overlapping lines (experimental)" gui-description="Removes any duplicates by merging (multiple) overlapping line segments into longer lines.">true</param>
|
<param name="remove_subsplit_collinear" type="bool" gui-text="Remove collinear overlapping lines (experimental)" gui-description="Removes any duplicates by merging (multiple) overlapping line segments into longer lines. Not possible to apply for original paths because this routine does not support bezier type paths.">true</param>
|
||||||
</page>
|
</page>
|
||||||
<page name="tab_scanning" gui-text="Scanning and Trimming">
|
<page name="tab_scanning" gui-text="Scanning and Trimming">
|
||||||
<hbox>
|
<hbox>
|
||||||
|
@ -5,9 +5,8 @@ Extension for InkScape 1.0+
|
|||||||
- WARNING: HORRIBLY SLOW CODE. PLEASE HELP TO MAKE IT USEFUL FOR LARGE AMOUNT OF PATHS
|
- WARNING: HORRIBLY SLOW CODE. PLEASE HELP TO MAKE IT USEFUL FOR LARGE AMOUNT OF PATHS
|
||||||
- add options:
|
- add options:
|
||||||
- replace trimmed paths by bezier paths (calculating lengths and required t parameter)
|
- replace trimmed paths by bezier paths (calculating lengths and required t parameter)
|
||||||
- detection of collinear segments: does not work sometimes because it generates pointy paths or kicks out paths which still should be inside the data set
|
|
||||||
- filter/remove overlapping/duplicates in
|
- filter/remove overlapping/duplicates in
|
||||||
- in original selection
|
- in original selection (not working bezier but for straight line segments!) We can use another extension for it
|
||||||
- split bezier
|
- split bezier
|
||||||
- ...
|
- ...
|
||||||
- maybe option: convert abs path to rel path
|
- maybe option: convert abs path to rel path
|
||||||
@ -339,6 +338,10 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
s0x1 = working_set[i]['p1'][0]
|
s0x1 = working_set[i]['p1'][0]
|
||||||
s1x0 = working_set[j]['p0'][0]
|
s1x0 = working_set[j]['p0'][0]
|
||||||
s1x1 = working_set[j]['p1'][0]
|
s1x1 = working_set[j]['p1'][0]
|
||||||
|
|
||||||
|
if s0x0 == s1x0 and s0x1 == s1x1:
|
||||||
|
continue #skip if pointy path is going to be created
|
||||||
|
|
||||||
if not (s0x0 < s0x1 and s0x1 < s1x0 and s1x0 < s1x1):
|
if not (s0x0 < s0x1 and s0x1 < s1x0 and s1x0 < s1x1):
|
||||||
# make a duplicate set, omitting segments i and j
|
# make a duplicate set, omitting segments i and j
|
||||||
new_set = [x for (k, x) in enumerate(working_set) if k not in (i, j)]
|
new_set = [x for (k, x) in enumerate(working_set) if k not in (i, j)]
|
||||||
@ -346,16 +349,9 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
# add a segment representing i and j's furthest points
|
# add a segment representing i and j's furthest points
|
||||||
pts = [ working_set[i]['p0'], working_set[i]['p1'], working_set[j]['p0'], working_set[j]['p1'] ]
|
pts = [ working_set[i]['p0'], working_set[i]['p1'], working_set[j]['p0'], working_set[j]['p1'] ]
|
||||||
pts.sort(key=lambda x: x[0])
|
pts.sort(key=lambda x: x[0])
|
||||||
#if pts[0] == pts[-1]:
|
if pts[0] == pts[-1]:
|
||||||
# replace_path = Path(working_set[i]['d']).to_arrays()
|
continue #skip if pointy path is going to be created
|
||||||
# if self.options.show_debug is True:
|
|
||||||
# self.msg("Error: creating pointy path while looking for overlapping lines. Result will be wrong: p0{} = p1{}. Replacing by p0{} = p1{}".format(pts[0], pts[-1], replace_path[0][1], replace_path[1][1]))
|
|
||||||
# pts[0] = replace_path[0][1]
|
|
||||||
# pts[-1] = replace_path[1][1]
|
|
||||||
# working_set[i]['p0'] = replace_path[0][1]
|
|
||||||
# working_set[i]['p1'] = replace_path[1][1]
|
|
||||||
# working_set[j]['p0'] = replace_path[0][1]
|
|
||||||
# working_set[j]['p1'] = replace_path[1][1]
|
|
||||||
new_set.append({
|
new_set.append({
|
||||||
'p0': pts[0],
|
'p0': pts[0],
|
||||||
'p1': pts[-1],
|
'p1': pts[-1],
|
||||||
@ -373,10 +369,14 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
Loop through a set of lines and find + fiter all overlapping segments / duplicate segments
|
Loop through a set of lines and find + fiter all overlapping segments / duplicate segments
|
||||||
finally returns a set of merged-like lines and a set of original items which should be dropped
|
finally returns a set of merged-like lines and a set of original items which should be dropped
|
||||||
'''
|
'''
|
||||||
segments = []
|
input_set = []
|
||||||
|
input_ids = []
|
||||||
|
|
||||||
# collect segments, calculate their slopes, order their points left-to-right
|
# collect segments, calculate their slopes, order their points left-to-right
|
||||||
for line in lineArray:
|
for line in lineArray:
|
||||||
csp = line.path.to_arrays()
|
csp = line.path.to_arrays()
|
||||||
|
#csp = Path(line.path.transform(line.composed_transform()).to_superpath()).to_arrays()
|
||||||
|
|
||||||
x1, y1, x2, y2 = csp[0][1][0], csp[0][1][1], csp[1][1][0], csp[1][1][1]
|
x1, y1, x2, y2 = csp[0][1][0], csp[0][1][1], csp[1][1][0], csp[1][1][1]
|
||||||
# ensure p0 is left of p1
|
# ensure p0 is left of p1
|
||||||
if x1 < x2:
|
if x1 < x2:
|
||||||
@ -393,19 +393,19 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
s['id'] = line.attrib['id']
|
s['id'] = line.attrib['id']
|
||||||
s['originalPathId'] = line.attrib['originalPathId']
|
s['originalPathId'] = line.attrib['originalPathId']
|
||||||
#s['d'] = line.attrib['d']
|
#s['d'] = line.attrib['d']
|
||||||
segments.append(s)
|
input_set.append(s)
|
||||||
|
|
||||||
working_set = []
|
working_set = []
|
||||||
output_set = []
|
output_set = []
|
||||||
segments.sort(key=lambda x: x['slope'])
|
input_set.sort(key=lambda x: x['slope'])
|
||||||
segments.append(False) # used to clear out lingering contents of working_set on last iteration
|
input_set.append(False) # used to clear out lingering contents of working_set on last iteration
|
||||||
current_slope = segments[0]['slope']
|
current_slope = input_set[0]['slope']
|
||||||
for seg in segments:
|
for input in input_set:
|
||||||
|
# bin sets of input_set by slope (within a tolerance)
|
||||||
# bin sets of segments by slope (within a tolerance)
|
dm = input and abs(input['slope'] - current_slope) or 0
|
||||||
dm = seg and abs(seg['slope'] - current_slope) or 0
|
if input and dm < EPS_M:
|
||||||
if seg and dm < EPS_M:
|
working_set.append(input) #we put all lines to working set which have similar slopes
|
||||||
working_set.append(seg)
|
if input['id'] != '': input_ids.append(input['id'])
|
||||||
|
|
||||||
else: # slope discontinuity, process accumulated set
|
else: # slope discontinuity, process accumulated set
|
||||||
while True:
|
while True:
|
||||||
@ -414,28 +414,46 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
output_set.extend(working_set)
|
output_set.extend(working_set)
|
||||||
break
|
break
|
||||||
|
|
||||||
if seg: # begin new working set
|
if input: # begin new working set
|
||||||
working_set = [seg]
|
working_set = [input]
|
||||||
current_slope = seg['slope']
|
current_slope = input['slope']
|
||||||
|
if input['id'] != '': input_ids.append(input['id'])
|
||||||
|
|
||||||
seg_ids = []
|
output_ids = []
|
||||||
for seg in segments:
|
|
||||||
if seg is not False and seg['id'] != '':
|
|
||||||
seg_ids.append(seg['id'])
|
|
||||||
out_ids = []
|
|
||||||
for output in output_set:
|
for output in output_set:
|
||||||
out_ids.append(output['id'])
|
output_ids.append(output['id'])
|
||||||
|
|
||||||
dropped_ids = set(seg_ids) - set(out_ids)
|
working_ids = []
|
||||||
|
for working in working_set:
|
||||||
|
working_ids.append(working['id'])
|
||||||
|
|
||||||
#self.msg("segments:{}".format(segments))
|
#we finally build a list which contains all overlapping elements we want to drop
|
||||||
#self.msg("_____________")
|
dropped_ids = []
|
||||||
|
for working_id in working_ids: #if the working id is not in the output id we are going to drop it
|
||||||
|
if working_id not in output_ids:
|
||||||
|
dropped_ids.append(working_id)
|
||||||
|
|
||||||
|
if self.options.show_debug is True:
|
||||||
|
#self.msg("input_set:{}".format(input_set))
|
||||||
|
self.msg("input_ids:")
|
||||||
|
for input_id in input_ids:
|
||||||
|
self.msg(input_id)
|
||||||
|
self.msg("*"*24)
|
||||||
#self.msg("working_set:{}".format(working_set))
|
#self.msg("working_set:{}".format(working_set))
|
||||||
#self.msg("_____________")
|
self.msg("working_ids:")
|
||||||
|
for working_id in working_ids:
|
||||||
|
self.msg(working_id)
|
||||||
|
self.msg("*"*24)
|
||||||
#self.msg("output_set:{}".format(output_set))
|
#self.msg("output_set:{}".format(output_set))
|
||||||
#self.msg("_____________")
|
self.msg("output_ids:")
|
||||||
#self.msg("dropped_set:{}".format(dropped_ids))
|
for output_id in output_ids:
|
||||||
#self.msg("_____________")
|
self.msg(output_id)
|
||||||
|
self.msg("*"*24)
|
||||||
|
self.msg("dropped_ids:")
|
||||||
|
for dropped_id in dropped_ids:
|
||||||
|
self.msg(dropped_id)
|
||||||
|
self.msg("*"*24)
|
||||||
|
|
||||||
return output_set, dropped_ids
|
return output_set, dropped_ids
|
||||||
|
|
||||||
|
|
||||||
@ -566,7 +584,7 @@ class ContourScannerAndTrimmer(inkex.EffectExtension):
|
|||||||
pars.add_argument("--decimals", type=int, default=3, help="Accuracy for sub split lines / lines trimmed by shapely")
|
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")
|
pars.add_argument("--snap_tolerance", type=float, default=0.1, help="Snap tolerance for intersection points")
|
||||||
pars.add_argument("--draw_subsplit", type=inkex.Boolean, default=False, help="Draw sub split lines (polylines)")
|
pars.add_argument("--draw_subsplit", type=inkex.Boolean, default=False, help="Draw sub split lines (polylines)")
|
||||||
pars.add_argument("--remove_subsplit_collinear", type=inkex.Boolean, default=True, help="Removes any duplicates by merging (multiple) overlapping line segments into longer lines.")
|
pars.add_argument("--remove_subsplit_collinear", type=inkex.Boolean, default=True, help="Removes any duplicates by merging (multiple) overlapping line segments into longer lines. Not possible to apply for original paths because this routine does not support bezier type paths.")
|
||||||
|
|
||||||
#Scanning - Removing
|
#Scanning - Removing
|
||||||
pars.add_argument("--remove_relative", type=inkex.Boolean, default=False, help="relative cmd")
|
pars.add_argument("--remove_relative", type=inkex.Boolean, default=False, help="relative cmd")
|
||||||
|
Reference in New Issue
Block a user