meander: pick ending point far from starting point (#2095)

pull/2120/head
Lex Neva 2023-03-07 12:13:57 -05:00 zatwierdzone przez GitHub
rodzic 9552291de5
commit 74157dd1cb
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
4 zmienionych plików z 23 dodań i 20 usunięć

Wyświetl plik

@ -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',

Wyświetl plik

@ -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)

Wyświetl plik

@ -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)

Wyświetl plik

@ -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):