kopia lustrzana https://github.com/inkstitch/inkstitch
107 wiersze
4.8 KiB
Python
107 wiersze
4.8 KiB
Python
# Authors: see git history
|
|
#
|
|
# Copyright (c) 2025 Authors
|
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
|
|
|
from inkex import Boolean, Path, PathElement
|
|
from shapely import union_all
|
|
from shapely.geometry import LineString, Polygon
|
|
|
|
from ..stitches.ripple_stitch import ripple_stitch
|
|
from ..svg import PIXELS_PER_MM, get_correction_transform
|
|
from ..utils.geometry import ensure_multi_polygon
|
|
from .base import InkstitchExtension
|
|
|
|
|
|
class KnockdownFill(InkstitchExtension):
|
|
'''
|
|
This extension generates a shape around all selected shapes and inserts it into the document
|
|
'''
|
|
def __init__(self, *args, **kwargs):
|
|
InkstitchExtension.__init__(self, *args, **kwargs)
|
|
self.arg_parser.add_argument("--notebook")
|
|
self.arg_parser.add_argument("-k", "--keep-holes", type=Boolean, default=True, dest="keep_holes")
|
|
self.arg_parser.add_argument("-o", "--offset", type=float, default=0, dest="offset")
|
|
self.arg_parser.add_argument("-j", "--join-style", type=str, default="1", dest="join_style")
|
|
self.arg_parser.add_argument("-m", "--mitre-limit", type=float, default=5.0, dest="mitre_limit")
|
|
# TODO: Layer options: underlay, row spacing, angle
|
|
|
|
def effect(self):
|
|
if not self.get_elements():
|
|
return
|
|
|
|
polygons = []
|
|
for element in self.elements:
|
|
if element.name == "FillStitch":
|
|
# take expand value into account
|
|
shape = element.shrink_or_grow_shape(element.shape, element.expand)
|
|
# MultiPolygon
|
|
for polygon in shape.geoms:
|
|
polygons.append(polygon)
|
|
elif element.name == "SatinColumn":
|
|
# plot points on rails, so we get the actual satin size (including pull compensation)
|
|
rail_pairs = zip(*element.plot_points_on_rails(
|
|
0.3,
|
|
element.pull_compensation_px,
|
|
element.pull_compensation_percent / 100)
|
|
)
|
|
rails = []
|
|
for rail in rail_pairs:
|
|
rails.append(LineString(rail))
|
|
polygon = Polygon(list(rails[0].coords) + list(rails[1].reverse().coords)).buffer(0)
|
|
polygons.append(polygon)
|
|
elif element.name == "Stroke":
|
|
if element.stroke_method == 'ripple_stitch':
|
|
# for ripples this is going to be a bit complicated, so let's follow the stitch plan
|
|
stitches = ripple_stitch(element)
|
|
linestring = LineString(stitches)
|
|
polygons.append(linestring.buffer(0.15 * PIXELS_PER_MM, cap_style='flat'))
|
|
elif element.stroke_method == 'zigzag_stitch':
|
|
# zigzag stitch depends on the width of the stroke and pull compensation settings
|
|
polygons.append(element.as_multi_line_string().buffer((element.stroke_width + element.pull_compensation) / 2, cap_style='flat'))
|
|
else:
|
|
polygons.append(element.as_multi_line_string().buffer(0.15 * PIXELS_PER_MM, cap_style='flat'))
|
|
combined_shape = union_all(polygons)
|
|
combined_shape = combined_shape.buffer(
|
|
self.options.offset * PIXELS_PER_MM,
|
|
cap_style=int(self.options.join_style),
|
|
join_style=int(self.options.join_style),
|
|
mitre_limit=float(max(self.options.mitre_limit, 0.1))
|
|
)
|
|
combined_shape = combined_shape.simplify(0.3)
|
|
combined_shape = ensure_multi_polygon(combined_shape)
|
|
|
|
self.insert_knockdown_elements(combined_shape)
|
|
|
|
def insert_knockdown_elements(self, combined_shape):
|
|
first = self.svg.selection.rendering_order()[0]
|
|
try:
|
|
parent = first.getparent()
|
|
index = parent.index(first)
|
|
except AttributeError:
|
|
parent = self.svg
|
|
index = 0
|
|
transform = get_correction_transform(first)
|
|
|
|
for polygon in combined_shape.geoms:
|
|
d = str(Path(polygon.exterior.coords))
|
|
if self.options.keep_holes:
|
|
for interior in polygon.interiors:
|
|
d += str(Path(interior.coords))
|
|
|
|
path = PathElement()
|
|
path.set('d', d)
|
|
path.label = self.svg.get_unique_id('Knockdown ')
|
|
path.set('transform', transform)
|
|
|
|
path.set('inkstitch:row_spacing_mm', '2.6')
|
|
path.set('inkstitch:fill_underlay_angle', '60 -60')
|
|
path.set('inkstitch:fill_underlay_max_stitch_length_mm', '3')
|
|
path.set('inkstitch:fill_underlay_row_spacing_mm', '2.6')
|
|
path.set('inkstitch:underlay_underpath', 'False')
|
|
path.set('inkstitch:underpath', 'False')
|
|
path.set('inkstitch:staggers', '2')
|
|
path.set('style', 'fill:black;')
|
|
|
|
parent.insert(index, path)
|