kopia lustrzana https://github.com/inkstitch/inkstitch
meander: pick ending point far from starting point (#2095)
rodzic
9552291de5
commit
74157dd1cb
|
@ -9,6 +9,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
from inkex import Transform
|
from inkex import Transform
|
||||||
from shapely import geometry as shgeo
|
from shapely import geometry as shgeo
|
||||||
from shapely.errors import TopologicalError
|
from shapely.errors import TopologicalError
|
||||||
|
@ -182,7 +183,7 @@ class FillStitch(EmbroideryElement):
|
||||||
@param('meander_pattern', _('Meander Pattern'), type='combo', default=0,
|
@param('meander_pattern', _('Meander Pattern'), type='combo', default=0,
|
||||||
options=sorted(tiles.all_tiles()), select_items=[('fill_method', 'meander_fill')], sort_index=3)
|
options=sorted(tiles.all_tiles()), select_items=[('fill_method', 'meander_fill')], sort_index=3)
|
||||||
def meander_pattern(self):
|
def meander_pattern(self):
|
||||||
return self.get_param('meander_pattern', None)
|
return self.get_param('meander_pattern', min(tiles.all_tiles()).id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@param('meander_scale_percent',
|
@param('meander_scale_percent',
|
||||||
|
@ -192,7 +193,7 @@ class FillStitch(EmbroideryElement):
|
||||||
select_items=[('fill_method', 'meander_fill')],
|
select_items=[('fill_method', 'meander_fill')],
|
||||||
sort_index=4)
|
sort_index=4)
|
||||||
def meander_scale(self):
|
def meander_scale(self):
|
||||||
return self.get_split_float_param('meander_scale_percent', (100, 100)) / 100
|
return np.maximum(self.get_split_float_param('meander_scale_percent', (100, 100)), (1, 1)) / 100
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@param('angle',
|
@param('angle',
|
||||||
|
|
|
@ -149,11 +149,11 @@ class ParamsTab(ScrolledPanel):
|
||||||
def update_combo_state(self, event=None):
|
def update_combo_state(self, event=None):
|
||||||
self.update_choice_state(event, True)
|
self.update_choice_state(event, True)
|
||||||
|
|
||||||
def get_combo_value_index(self, param, options):
|
def get_combo_value_index(self, param, options, default):
|
||||||
for option in options:
|
for option in options:
|
||||||
if option.id == param:
|
if option.id == param:
|
||||||
return options.index(option)
|
return options.index(option)
|
||||||
return 0
|
return default
|
||||||
|
|
||||||
def pair_changed(self, value):
|
def pair_changed(self, value):
|
||||||
new_value = not value
|
new_value = not value
|
||||||
|
@ -407,8 +407,7 @@ class ParamsTab(ScrolledPanel):
|
||||||
input.Append(option.name, image, option)
|
input.Append(option.name, image, option)
|
||||||
if not param.options:
|
if not param.options:
|
||||||
input.Append(_('No options available'), ParamOption('not_available'))
|
input.Append(_('No options available'), ParamOption('not_available'))
|
||||||
|
value = self.get_combo_value_index(param.values[0], param.options, param.default or 0)
|
||||||
value = self.get_combo_value_index(param.values[0], param.options)
|
|
||||||
input.SetSelection(value)
|
input.SetSelection(value)
|
||||||
input.Bind(wx.EVT_COMBOBOX, self.changed)
|
input.Bind(wx.EVT_COMBOBOX, self.changed)
|
||||||
input.Bind(wx.EVT_COMBOBOX, self.update_combo_state)
|
input.Bind(wx.EVT_COMBOBOX, self.update_combo_state)
|
||||||
|
|
|
@ -66,7 +66,9 @@ def find_starting_and_ending_nodes(graph, shape, starting_point, ending_point):
|
||||||
starting_point = Point(starting_point)
|
starting_point = Point(starting_point)
|
||||||
|
|
||||||
if ending_point is None:
|
if ending_point is None:
|
||||||
ending_point = starting_point
|
# pick a spot on the opposite side of the shape
|
||||||
|
projection = (shape.exterior.project(starting_point, normalized=True) + 0.5) % 1.0
|
||||||
|
ending_point = shape.exterior.interpolate(projection, normalized=True)
|
||||||
else:
|
else:
|
||||||
ending_point = Point(ending_point)
|
ending_point = Point(ending_point)
|
||||||
|
|
||||||
|
|
27
lib/tiles.py
27
lib/tiles.py
|
@ -100,10 +100,10 @@ class Tile:
|
||||||
|
|
||||||
return center, width, height
|
return center, width, height
|
||||||
|
|
||||||
def _translate_tile(self, shift):
|
def _translate_tile(self, tile, shift):
|
||||||
translated_tile = []
|
translated_tile = []
|
||||||
|
|
||||||
for start, end in self.tile:
|
for start, end in tile:
|
||||||
start += shift
|
start += shift
|
||||||
end += shift
|
end += shift
|
||||||
translated_tile.append((start.as_int().as_tuple(), end.as_int().as_tuple()))
|
translated_tile.append((start.as_int().as_tuple(), end.as_int().as_tuple()))
|
||||||
|
@ -111,15 +111,16 @@ class Tile:
|
||||||
return translated_tile
|
return translated_tile
|
||||||
|
|
||||||
def _scale(self, x_scale, y_scale):
|
def _scale(self, x_scale, y_scale):
|
||||||
self.shift0 = self.shift0.scale(x_scale, y_scale)
|
scaled_shift0 = self.shift0.scale(x_scale, y_scale)
|
||||||
self.shift1 = self.shift1.scale(x_scale, y_scale)
|
scaled_shift1 = self.shift1.scale(x_scale, y_scale)
|
||||||
|
|
||||||
scaled_tile = []
|
scaled_tile = []
|
||||||
for start, end in self.tile:
|
for start, end in self.tile:
|
||||||
start = start.scale(x_scale, y_scale)
|
start = start.scale(x_scale, y_scale)
|
||||||
end = end.scale(x_scale, y_scale)
|
end = end.scale(x_scale, y_scale)
|
||||||
scaled_tile.append((start, end))
|
scaled_tile.append((start, end))
|
||||||
self.tile = scaled_tile
|
|
||||||
|
return scaled_shift0, scaled_shift1, scaled_tile
|
||||||
|
|
||||||
@debug.time
|
@debug.time
|
||||||
def to_graph(self, shape, scale):
|
def to_graph(self, shape, scale):
|
||||||
|
@ -132,25 +133,25 @@ class Tile:
|
||||||
"""
|
"""
|
||||||
self._load()
|
self._load()
|
||||||
x_scale, y_scale = scale
|
x_scale, y_scale = scale
|
||||||
self._scale(x_scale, y_scale)
|
shift0, shift1, tile = self._scale(x_scale, y_scale)
|
||||||
|
|
||||||
shape_center, shape_width, shape_height = self._get_center_and_dimensions(shape)
|
shape_center, shape_width, shape_height = self._get_center_and_dimensions(shape)
|
||||||
shape_diagonal = Point(shape_width, shape_height).length()
|
shape_diagonal = Point(shape_width, shape_height).length()
|
||||||
prepared_shape = prep(shape)
|
prepared_shape = prep(shape)
|
||||||
|
|
||||||
return self._generate_graph(prepared_shape, shape_center, shape_diagonal)
|
return self._generate_graph(prepared_shape, shape_center, shape_diagonal, shift0, shift1, tile)
|
||||||
|
|
||||||
def _generate_graph(self, shape, shape_center, shape_diagonal):
|
def _generate_graph(self, shape, shape_center, shape_diagonal, shift0, shift1, tile):
|
||||||
graph = nx.Graph()
|
graph = nx.Graph()
|
||||||
tiles0 = ceil(shape_diagonal / self.shift0.length()) + 2
|
tiles0 = ceil(shape_diagonal / shift0.length()) + 2
|
||||||
tiles1 = ceil(shape_diagonal / self.shift1.length()) + 2
|
tiles1 = ceil(shape_diagonal / shift1.length()) + 2
|
||||||
for repeat0 in range(floor(-tiles0 / 2), ceil(tiles0 / 2)):
|
for repeat0 in range(floor(-tiles0 / 2), ceil(tiles0 / 2)):
|
||||||
for repeat1 in range(floor(-tiles1 / 2), ceil(tiles1 / 2)):
|
for repeat1 in range(floor(-tiles1 / 2), ceil(tiles1 / 2)):
|
||||||
check_stop_flag()
|
check_stop_flag()
|
||||||
|
|
||||||
shift0 = repeat0 * self.shift0
|
offset0 = repeat0 * shift0
|
||||||
shift1 = repeat1 * self.shift1
|
offset1 = repeat1 * shift1
|
||||||
this_tile = self._translate_tile(shift0 + shift1 + shape_center)
|
this_tile = self._translate_tile(tile, offset0 + offset1 + shape_center)
|
||||||
for line in this_tile:
|
for line in this_tile:
|
||||||
line_string = LineString(line)
|
line_string = LineString(line)
|
||||||
if shape.contains(line_string):
|
if shape.contains(line_string):
|
||||||
|
|
Ładowanie…
Reference in New Issue