kopia lustrzana https://github.com/evil-mad/EggBot
Hatch Fill 2.4.0
- Revise GUI - Add option to set hatch spacing and inset distances with selectable units, px, mm, or inch. - Ignore non-fillable SVG elements (except text) - Fill only visible layerspull/175/head
rodzic
6e528683e4
commit
948d7f2157
|
@ -8,58 +8,71 @@
|
|||
<param name="tab" type="notebook">
|
||||
<page name="splash" _gui-text="Hatch Fill">
|
||||
<_param name="Header" type="description" xml:space="preserve">
|
||||
This extension fills each closed figure in your drawing
|
||||
with a path consisting of back and forth drawn "hatch" lines.
|
||||
If any objects are selected, then only those selected objects
|
||||
will be filled.
|
||||
|
||||
Hatched figures will be grouped with their fills.
|
||||
Hatch Fill: An extension to fill all or selected closed figures in your
|
||||
drawing with paths consisting of back-and-forth hatch line.
|
||||
</_param>
|
||||
<param name="hatchSpacing" type="float" min="0.1" max="1000" _gui-text=" Hatch spacing (px)">3.0</param>
|
||||
<param name="hatchAngle" type="float" min="-360" max="360" _gui-text=" Hatch angle (degrees)">45</param>
|
||||
<param name="crossHatch" type="boolean" _gui-text=" Crosshatch?">false</param>
|
||||
|
||||
<param name="reducePenLifts" type="boolean" _gui-text=" Connect nearby ends?">true</param>
|
||||
<param name="hatchScope" type="float" min="1.1" max="5.0" _gui-text=" Range of end connections (default: 3)">3.0</param>
|
||||
<param name="holdBackHatchFromEdges" type="boolean" _gui-text=" Inset fill from edges?">true</param>
|
||||
<param name="holdBackSteps" type="float" min="0.1" max="10.0" _gui-text=" Inset distance (px) (default: 1)">1.0</param>
|
||||
<param name="tolerance" type="float" min="0.1" max="100" _gui-text=" Tolerance (default: 3.0)">3.0</param>
|
||||
<param name="hatchSpacing" type="float" min="0.001" max="1000" indent="2"
|
||||
precision="3" _gui-text="Hatch Spacing">3.0</param>
|
||||
|
||||
<param name="footer" type="description" xml:space="preserve">
|
||||
(v2.3.0, June 11, 2019)</param>
|
||||
<param name="units" type="optiongroup" appearance="minimal"
|
||||
indent="4" _gui-text="Spacing Units :">
|
||||
<_option value="2">px</_option>
|
||||
<_option value="3">mm</_option>
|
||||
<_option value="4">inch</_option>
|
||||
</param>
|
||||
|
||||
<param name="hatchAngle" type="float" min="-360" max="360" indent="4" _gui-text="Hatch Angle (degrees)">45</param>
|
||||
<param name="crossHatch" type="boolean" indent="4" _gui-text="Crosshatch">false</param>
|
||||
|
||||
<separator />
|
||||
|
||||
<param name="connect_bool" type="boolean" indent="2" _gui-text="Connect Nearby Ends">true</param>
|
||||
<param name="hatchScope" type="float" min="1.1" max="5.0" indent="2" _gui-text="Range of end connections (default: 3)">3.0</param>
|
||||
|
||||
<separator />
|
||||
<param name="inset_bool" type="boolean" indent="2" _gui-text="Inset Fill from Edges">true</param>
|
||||
<param name="inset_dist" type="float" min="0.001" max="1000" precision="3" indent="2"
|
||||
_gui-text="Inset Distance, in selected units">0.5</param>
|
||||
|
||||
<separator />
|
||||
<param name="tolerance" type="float" min="0.1" max="100" indent="2"
|
||||
_gui-text="Tolerance (default: 2.0)">2.0</param>
|
||||
|
||||
</page>
|
||||
<page name="info" _gui-text="More info...">
|
||||
<_param name="aboutpage" type="description" xml:space="preserve">
|
||||
Hatch spacing is the distance between hatch lines,
|
||||
measured in units of screen pixels (px). Angles are in
|
||||
degrees from horizontal; for example 90 is vertical.
|
||||
<param name="aboutpage" type="description" xml:space="preserve">
|
||||
Hatch spacing is the distance between hatch lines, measured in selected
|
||||
units. Hatch angle is in degrees from horizontal; e.g., 90 for vertical.
|
||||
|
||||
The Crosshatch option will apply a second set of
|
||||
hatches, perpendicular to the first.
|
||||
The Crosshatch option will add a second set of hatches, perpendicular
|
||||
to the first.
|
||||
|
||||
The "Connect nearby ends" option will attempt to connect
|
||||
nearby line ends with a smoothly flowing curve, to improve
|
||||
the smoothness of plotting.
|
||||
The Connect Nearby Ends option will join nearby line ends with a
|
||||
smooth curve, giving a differnt appearance and reducing the number of
|
||||
pen lifts when using robotic tools like pen plotters. The Range
|
||||
parameter sets the distance (in hatch spacing) over which end
|
||||
connections may be made. Large values may result in hatches where you
|
||||
don't want them.
|
||||
|
||||
The Range parameter sets the distance (in hatch widths)
|
||||
over which that option searches for segments to join.
|
||||
Large values may result in hatches where you don't want
|
||||
them. Consider using a value in the range of 2-4.
|
||||
The Inset Fill from Edges option allows you to hold back the hatches
|
||||
away from the edge of your original object. This can allow you to more
|
||||
reliably "color inside the lines".
|
||||
|
||||
The Inset option allows you to hold back the edges of the
|
||||
fill somewhat from the edge of your original object.
|
||||
This can improve performance, as it allows you to more
|
||||
reliably "color inside the lines" when using pens.
|
||||
The Tolerance parameter affects how precisely the hatches try
|
||||
to fill the input paths.
|
||||
|
||||
The hatches will be the same color and width
|
||||
as the original object.
|
||||
|
||||
The Tolerance parameter affects how precisely
|
||||
the hatches try to fill the input paths.</_param>
|
||||
Hatches will have the same stroke color and width as the original
|
||||
object. When filling more than one object, the hatches will be grouped
|
||||
with their original (filled) objects.
|
||||
|
||||
|
||||
v2.4.0, August 8, 2021</_param>
|
||||
|
||||
</page>
|
||||
</param>
|
||||
|
||||
<effect needs-live-preview="true">
|
||||
<object-type>all</object-type>
|
||||
<effects-menu>
|
||||
|
|
|
@ -84,8 +84,12 @@
|
|||
# This prevents extremely complex plots from generating glitches
|
||||
# Modifications are limited to recursivelyTraverseSvg and effect methods
|
||||
|
||||
# Updated by Windell H. Oskay, 2021
|
||||
# Add option for selecting units.
|
||||
# Make inset settable in selected units as well.
|
||||
|
||||
# Current software version:
|
||||
# (v2.3.2, September 29, 2019)
|
||||
# (v2.4.0, August 8, 2021)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
|
@ -104,7 +108,7 @@
|
|||
import math
|
||||
from lxml import etree
|
||||
|
||||
from plot_utils_import import from_dependency_import # plotink
|
||||
from axidrawinternal.plot_utils_import import from_dependency_import # plotink
|
||||
inkex = from_dependency_import('ink_extensions.inkex')
|
||||
simplepath = from_dependency_import('ink_extensions.simplepath')
|
||||
simpletransform = from_dependency_import('ink_extensions.simpletransform')
|
||||
|
@ -471,7 +475,7 @@ def interstices(self, p1, p2, paths, hatches, b_hold_back_hatches, f_hold_back_s
|
|||
# remove it from consideration by marking it as already drawn - a
|
||||
# fiction, but is much quicker than actually removing the hatch from the list.
|
||||
|
||||
f_min_allowed_hatch_length = self.options.hatchSpacing * MIN_HATCH_FRACTION
|
||||
f_min_allowed_hatch_length = self.hatch_spacing_px * MIN_HATCH_FRACTION
|
||||
f_initial_hatch_length = math.hypot(x2 - x1, y2 - y1)
|
||||
# We did as much as possible of the inset operation back when we were finding intersections.
|
||||
# We did it back then because at that point we knew more about the geometry than we know now.
|
||||
|
@ -610,19 +614,19 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
self.docTransform = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
|
||||
|
||||
self.OptionParser.add_option(
|
||||
"--holdBackSteps", action="store", type="float",
|
||||
dest="holdBackSteps", default=3.0,
|
||||
help="How far hatch strokes stay from boundary (steps)")
|
||||
"--inset_dist", action="store", type="float",
|
||||
dest="inset_dist", default=3.0,
|
||||
help="How far hatch strokes stay from boundary")
|
||||
self.OptionParser.add_option(
|
||||
"--hatchScope", action="store", type="float",
|
||||
dest="hatchScope", default=3.0,
|
||||
help="Radius searched for segments to join (units of hatch width)")
|
||||
self.OptionParser.add_option(
|
||||
"--holdBackHatchFromEdges", action="store", dest="holdBackHatchFromEdges",
|
||||
"--inset_bool", action="store", dest="inset_bool",
|
||||
type="inkbool", default=True,
|
||||
help="Stay away from edges, so no need for inset")
|
||||
self.OptionParser.add_option(
|
||||
"--reducePenLifts", action="store", dest="reducePenLifts",
|
||||
"--connect_bool", action="store", dest="connect_bool",
|
||||
type="inkbool", default=True,
|
||||
help="Reduce plotting time by joining some hatches")
|
||||
self.OptionParser.add_option(
|
||||
|
@ -639,12 +643,19 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
help="Spacing between hatch lines")
|
||||
self.OptionParser.add_option(
|
||||
"--tolerance", action="store", type="float",
|
||||
dest="tolerance", default=20.0,
|
||||
dest="tolerance", default=3.0,
|
||||
help="Allowed deviation from original paths")
|
||||
self.OptionParser.add_option(
|
||||
"--units",
|
||||
action="store", type="int",
|
||||
dest="units", default=1,
|
||||
help="Units to use for hatches. 1: line width. 2: px. 3: mm. 4: inch")
|
||||
|
||||
self.OptionParser.add_option("--tab", # NOTE: value is not used.
|
||||
action="store", type="string", dest="tab", default="splash",
|
||||
action="store", type="string", dest="_tab", default="splash",
|
||||
help="The active tab when Apply was pressed")
|
||||
|
||||
|
||||
def getDocProps(self):
|
||||
|
||||
"""
|
||||
|
@ -753,11 +764,11 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
for vertex in subpath:
|
||||
if vertex[0] < self.xmin:
|
||||
self.xmin = vertex[0]
|
||||
elif vertex[0] > self.xmax:
|
||||
if vertex[0] > self.xmax:
|
||||
self.xmax = vertex[0]
|
||||
if vertex[1] < self.ymin:
|
||||
self.ymin = vertex[1]
|
||||
elif vertex[1] > self.ymax:
|
||||
if vertex[1] > self.ymax:
|
||||
self.ymax = vertex[1]
|
||||
|
||||
def recursivelyTraverseSvg(self, a_node_list, mat_current=None, parent_visibility='visible'):
|
||||
|
@ -803,7 +814,17 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
if v == 'inherit':
|
||||
v = parent_visibility
|
||||
if v == 'hidden' or v == 'collapse':
|
||||
pass
|
||||
continue
|
||||
|
||||
style = simplestyle.parseStyle(node.get('style'))
|
||||
|
||||
# Check for "display:none" in the node's style attribute:
|
||||
if 'display' in style.keys() and style['display'] == 'none':
|
||||
continue # Do not hatch this object or its children
|
||||
|
||||
# The node may have a display="none" attribute as well:
|
||||
if node.get('display') == 'none':
|
||||
continue # Do not hatch this object or its children
|
||||
|
||||
# first apply the current matrix transform to this node's transform
|
||||
mat_new = simpletransform.composeTransform(mat_current, simpletransform.parseTransform(node.get("transform")))
|
||||
|
@ -849,13 +870,13 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
self.addPathVertices(path_data, node, mat_new)
|
||||
# We now have a path we want to apply a (cross)hatch to
|
||||
# Apply appropriate functions
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.options.hatchSpacing), True)
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.hatch_spacing_px), True)
|
||||
if b_have_grid:
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.options.hatchSpacing), False)
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.hatch_spacing_px), False)
|
||||
# Now loop over our hatch lines looking for intersections
|
||||
for h in self.grid:
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.holdBackHatchFromEdges, self.options.holdBackSteps)
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.inset_bool, self.inset_dist_px)
|
||||
|
||||
elif node.tag in [inkex.addNS('rect', 'svg'), 'rect']:
|
||||
|
||||
|
@ -885,13 +906,13 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
self.addPathVertices(simplepath.formatPath(a), node, mat_new)
|
||||
# We now have a path we want to apply a (cross)hatch to
|
||||
# Apply appropriate functions
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.options.hatchSpacing), True)
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.hatch_spacing_px), True)
|
||||
if b_have_grid:
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.options.hatchSpacing), False)
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.hatch_spacing_px), False)
|
||||
# Now loop over our hatch lines looking for intersections
|
||||
for h in self.grid:
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.holdBackHatchFromEdges, self.options.holdBackSteps)
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.inset_bool, self.inset_dist_px)
|
||||
|
||||
elif node.tag in [inkex.addNS('line', 'svg'), 'line']:
|
||||
|
||||
|
@ -914,13 +935,13 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
self.addPathVertices(simplepath.formatPath(a), node, mat_new)
|
||||
# We now have a path we want to apply a (cross)hatch to
|
||||
# Apply appropriate functions
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.options.hatchSpacing), True)
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.hatch_spacing_px), True)
|
||||
if b_have_grid:
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.options.hatchSpacing), False)
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.hatch_spacing_px), False)
|
||||
# Now loop over our hatch lines looking for intersections
|
||||
for h in self.grid:
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.holdBackHatchFromEdges, self.options.holdBackSteps)
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.inset_bool, self.inset_dist_px)
|
||||
|
||||
elif node.tag in [inkex.addNS('polyline', 'svg'), 'polyline']:
|
||||
|
||||
|
@ -955,13 +976,13 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
|
||||
# We now have a path we want to apply a (cross)hatch to
|
||||
# Apply appropriate functions
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.options.hatchSpacing), True)
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.hatch_spacing_px), True)
|
||||
if b_have_grid:
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.options.hatchSpacing), False)
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.hatch_spacing_px), False)
|
||||
# Now loop over our hatch lines looking for intersections
|
||||
for h in self.grid:
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.holdBackHatchFromEdges, self.options.holdBackSteps)
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.inset_bool, self.inset_dist_px)
|
||||
|
||||
elif node.tag in [inkex.addNS('polygon', 'svg'), 'polygon']:
|
||||
# Convert
|
||||
|
@ -982,13 +1003,13 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
self.addPathVertices(d, node, mat_new)
|
||||
# We now have a path we want to apply a (cross)hatch to
|
||||
# Apply appropriate functions
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.options.hatchSpacing), True)
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.hatch_spacing_px), True)
|
||||
if b_have_grid:
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.options.hatchSpacing), False)
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.hatch_spacing_px), False)
|
||||
# Now loop over our hatch lines looking for intersections
|
||||
for h in self.grid:
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.holdBackHatchFromEdges, self.options.holdBackSteps)
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.inset_bool, self.inset_dist_px)
|
||||
|
||||
elif node.tag in [inkex.addNS('ellipse', 'svg'), 'ellipse',
|
||||
inkex.addNS('circle', 'svg'), 'circle']:
|
||||
|
@ -1033,34 +1054,33 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
self.addPathVertices(d, node, mat_new)
|
||||
# We now have a path we want to apply a (cross)hatch to
|
||||
# Apply appropriate functions
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.options.hatchSpacing), True)
|
||||
b_have_grid = self.makeHatchGrid(float(self.options.hatchAngle), float(self.hatch_spacing_px), True)
|
||||
if b_have_grid:
|
||||
if self.options.crossHatch:
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.options.hatchSpacing), False)
|
||||
self.makeHatchGrid(float(self.options.hatchAngle + 90.0), float(self.hatch_spacing_px), False)
|
||||
# Now loop over our hatch lines looking for intersections
|
||||
for h in self.grid:
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.holdBackHatchFromEdges, self.options.holdBackSteps)
|
||||
interstices(self, (h[0], h[1]), (h[2], h[3]), self.paths, self.hatches, self.options.inset_bool, self.inset_dist_px)
|
||||
|
||||
elif node.tag in [inkex.addNS('pattern', 'svg'), 'pattern']:
|
||||
pass
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('metadata', 'svg'), 'metadata']:
|
||||
pass
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('defs', 'svg'), 'defs']:
|
||||
pass
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('namedview', 'sodipodi'), 'namedview']:
|
||||
pass
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('eggbot', 'svg'), 'eggbot']:
|
||||
pass
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('WCB', 'svg'), 'WCB']:
|
||||
pass
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('image', 'svg'), 'image']:
|
||||
continue
|
||||
elif node.tag in [inkex.addNS('text', 'svg'), 'text']:
|
||||
inkex.errormsg('Warning: unable to draw text, please convert it to a path first.')
|
||||
pass
|
||||
elif not isinstance(node.tag, basestring):
|
||||
pass
|
||||
inkex.errormsg('Warning: unable to hatch text, please convert it to a path first.')
|
||||
continue
|
||||
else:
|
||||
inkex.errormsg('Warning: unable to hatch object <{0}>, please convert it to a path first.'.format(node.tag))
|
||||
pass
|
||||
continue # produce no error on other SVG elements.
|
||||
|
||||
def joinFillsWithNode(self, node, stroke_width, path):
|
||||
|
||||
|
@ -1193,8 +1213,19 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
# Viewbox handling
|
||||
self.handleViewBox()
|
||||
|
||||
if self.options.hatchSpacing == 0:
|
||||
self.options.hatchSpacing = 0.1 # Hardcode minimum value
|
||||
# Default spacing values for hatches and inset; handle px units case:
|
||||
self.hatch_spacing_px = self.options.hatchSpacing
|
||||
self.inset_dist_px = self.options.inset_dist
|
||||
|
||||
if self.options.units == 3: # Units in mm
|
||||
self.hatch_spacing_px = (96.0 / 25.4) * self.options.hatchSpacing
|
||||
self.inset_dist_px = (96.0 / 25.4) * self.options.inset_dist
|
||||
if self.options.units == 4: # Units in inches
|
||||
self.hatch_spacing_px = 96.0 * self.options.hatchSpacing
|
||||
self.inset_dist_px = 96.0 * self.options.inset_dist
|
||||
|
||||
if self.hatch_spacing_px < 0.1:
|
||||
self.hatch_spacing_px = 0.1 # Hardcode minimum value
|
||||
|
||||
ref_count = 0
|
||||
pt_last_position_abs = [0, 0]
|
||||
|
@ -1256,14 +1287,14 @@ class Eggbot_Hatch(inkex.Effect):
|
|||
stroke_width = 1.0
|
||||
|
||||
# The transform also applies to the hatch spacing we use when searching for end connections
|
||||
transformed_hatch_spacing = stroke_width * self.options.hatchSpacing
|
||||
transformed_hatch_spacing = stroke_width * self.hatch_spacing_px
|
||||
|
||||
path = '' # regardless of whether or not we're reducing pen lifts
|
||||
pt_last_position_abs = [0, 0]
|
||||
pt_last_position_abs[0] = 0
|
||||
pt_last_position_abs[1] = 0
|
||||
f_distance_moved_with_pen_up = 0
|
||||
if not self.options.reducePenLifts:
|
||||
if not self.options.connect_bool:
|
||||
for segment in self.hatches[key]:
|
||||
if len(segment) < 2:
|
||||
continue
|
||||
|
|
Ładowanie…
Reference in New Issue