kopia lustrzana https://github.com/inkstitch/inkstitch
add random parameters to satin columns
rodzic
4285a6fb7f
commit
72b001e7c2
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 697 B |
|
@ -2,16 +2,15 @@
|
|||
#
|
||||
# Copyright (c) 2010 Authors
|
||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
import random
|
||||
from copy import deepcopy
|
||||
from itertools import chain
|
||||
|
||||
from inkex import paths
|
||||
from shapely import affinity as shaffinity
|
||||
from shapely import geometry as shgeo
|
||||
from shapely.ops import nearest_points
|
||||
|
||||
from inkex import paths
|
||||
|
||||
from ..i18n import _
|
||||
from ..stitch_plan import StitchGroup
|
||||
from ..svg import line_strings_to_csp, point_lists_to_csp
|
||||
|
@ -99,6 +98,46 @@ class SatinColumn(EmbroideryElement):
|
|||
def max_stitch_length(self):
|
||||
return self.get_float_param("max_stitch_length_mm") or None
|
||||
|
||||
@property
|
||||
@param('random_split_factor',
|
||||
_('Random Split Factor'),
|
||||
tooltip=_('randomize position for split stitches.'),
|
||||
type='int', unit="%", sort_index=70)
|
||||
def random_split_factor(self):
|
||||
return min(max(self.get_int_param("random_split_factor", 0), 0), 100)
|
||||
|
||||
@property
|
||||
@param('random_first_rail_factor_in',
|
||||
_('First Rail Random Factor inside'),
|
||||
tooltip=_('shorten stitch around first rail at most this percent.'),
|
||||
type='int', unit="%", sort_index=60)
|
||||
def random_first_rail_factor_in(self):
|
||||
return min(max(self.get_int_param("random_first_rail_factor_in", 0), 0), 100)
|
||||
|
||||
@property
|
||||
@param('random_first_rail_factor_out',
|
||||
_('First Rail Random Factor outside'),
|
||||
tooltip=_('lengthen stitch around first rail at most this percent.'),
|
||||
type='int', unit="%", sort_index=61)
|
||||
def random_first_rail_factor_out(self):
|
||||
return max(self.get_int_param("random_first_rail_factor_out", 0), 0)
|
||||
|
||||
@property
|
||||
@param('random_second_rail_factor_in',
|
||||
_('Second Rail Random Factor inside'),
|
||||
tooltip=_('shorten stitch around second rail at most this percent.'),
|
||||
type='int', unit="%", sort_index=62)
|
||||
def random_second_rail_factor_in(self):
|
||||
return min(max(self.get_int_param("random_second_rail_factor_in", 0), 0), 100)
|
||||
|
||||
@property
|
||||
@param('random_second_rail_factor_out',
|
||||
_('Second Rail Random Factor outside'),
|
||||
tooltip=_('lengthen stitch around second rail at most this percent.'),
|
||||
type='int', unit="%", sort_index=63)
|
||||
def random_second_rail_factor_out(self):
|
||||
return max(self.get_int_param("random_second_rail_factor_out", 0), 0)
|
||||
|
||||
@property
|
||||
@param('short_stitch_inset',
|
||||
_('Short stitch inset'),
|
||||
|
@ -132,6 +171,15 @@ class SatinColumn(EmbroideryElement):
|
|||
# peak-to-peak distance between zigzags
|
||||
return max(self.get_float_param("zigzag_spacing_mm", 0.4), 0.01)
|
||||
|
||||
@property
|
||||
@param('random_zigzag_spacing',
|
||||
_('Zig-zag spacing randomness(peak-to-peak)'),
|
||||
tooltip=_('percentage of randomness of Peak-to-peak distance between zig-zags.'),
|
||||
type='int', unit="%", sort_index=64)
|
||||
def random_zigzag_spacing(self):
|
||||
# peak-to-peak distance between zigzags
|
||||
return max(self.get_int_param("random_zigzag_spacing", 0), 0)
|
||||
|
||||
@property
|
||||
@param(
|
||||
'pull_compensation_percent',
|
||||
|
@ -257,6 +305,10 @@ class SatinColumn(EmbroideryElement):
|
|||
def zigzag_underlay_max_stitch_length(self):
|
||||
return self.get_float_param("zigzag_underlay_max_stitch_length_mm") or None
|
||||
|
||||
@property
|
||||
def use_seed(self):
|
||||
return self.get_int_param("use_seed", 0)
|
||||
|
||||
@property
|
||||
@cache
|
||||
def shape(self):
|
||||
|
@ -500,6 +552,22 @@ class SatinColumn(EmbroideryElement):
|
|||
for rung in self.rungs:
|
||||
point_lists.append(self.flatten_subpath(rung))
|
||||
|
||||
# If originally there were only two subpaths (no rungs) with same number of rails, we may the rails may now
|
||||
# have two rails with different number of points, and still no rungs, let's add one.
|
||||
|
||||
if not self.rungs:
|
||||
rails = [shgeo.LineString(reversed(self.flatten_subpath(rail))) for rail in self.rails]
|
||||
rails.reverse()
|
||||
path_list = rails
|
||||
|
||||
rung_start = path_list[0].interpolate(0.1)
|
||||
rung_end = path_list[1].interpolate(0.1)
|
||||
rung = shgeo.LineString((rung_start, rung_end))
|
||||
# make it a bit bigger so that it definitely intersects
|
||||
rung = shaffinity.scale(rung, 1.1, 1.1)
|
||||
path_list.append(rung)
|
||||
return (self._path_list_to_satins(path_list))
|
||||
|
||||
return self._csp_to_satin(point_lists_to_csp(point_lists))
|
||||
|
||||
def apply_transform(self):
|
||||
|
@ -789,8 +857,13 @@ class SatinColumn(EmbroideryElement):
|
|||
old_center = new_center
|
||||
|
||||
if to_travel <= 0:
|
||||
add_pair(pos0, pos1)
|
||||
to_travel = spacing
|
||||
|
||||
decalage0 = random.uniform(-self.random_first_rail_factor_in, self.random_first_rail_factor_out) / 100
|
||||
decalage1 = random.uniform(-self.random_second_rail_factor_in, self.random_second_rail_factor_out) / 100
|
||||
|
||||
add_pair(pos0 + (pos0 - pos1) * decalage0, pos1 + (pos1 - pos0) * decalage1)
|
||||
|
||||
to_travel = spacing * (random.uniform(1, 1 + self.random_zigzag_spacing/100))
|
||||
|
||||
if to_travel > 0:
|
||||
add_pair(pos0, pos1)
|
||||
|
@ -842,8 +915,7 @@ class SatinColumn(EmbroideryElement):
|
|||
|
||||
patch = StitchGroup(color=self.color)
|
||||
|
||||
sides = self.plot_points_on_rails(self.zigzag_underlay_spacing / 2.0,
|
||||
-self.zigzag_underlay_inset)
|
||||
sides = self.plot_points_on_rails(self.zigzag_underlay_spacing / 2.0, -self.zigzag_underlay_inset)
|
||||
|
||||
if self._center_walk_is_odd():
|
||||
sides = [list(reversed(sides[0])), list(reversed(sides[1]))]
|
||||
|
@ -953,7 +1025,12 @@ class SatinColumn(EmbroideryElement):
|
|||
split_count = count or int(-(-distance // max_stitch_length))
|
||||
for i in range(split_count):
|
||||
line = shgeo.LineString((left, right))
|
||||
split_point = line.interpolate((i+1)/split_count, normalized=True)
|
||||
|
||||
random_move = 0
|
||||
if self.random_split_factor and i != split_count-1:
|
||||
random_move = random.uniform(-self.random_split_factor / 100, self.random_split_factor / 100)
|
||||
|
||||
split_point = line.interpolate((i + 1 + random_move) / split_count, normalized=True)
|
||||
points.append(Point(split_point.x, split_point.y))
|
||||
return [points, split_count]
|
||||
|
||||
|
@ -978,6 +1055,16 @@ class SatinColumn(EmbroideryElement):
|
|||
# beziers. The boundary points between beziers serve as "checkpoints",
|
||||
# allowing the user to control how the zigzags flow around corners.
|
||||
|
||||
# If no seed is defined, compute one randomly using time to seed, otherwise, use stored seed
|
||||
|
||||
if self.use_seed == 0:
|
||||
random.seed()
|
||||
x = random.randint(1, 10000)
|
||||
random.seed(x)
|
||||
self.set_param("use_seed", x)
|
||||
else:
|
||||
random.seed(self.use_seed)
|
||||
|
||||
patch = StitchGroup(color=self.color)
|
||||
|
||||
if self.center_walk_underlay:
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# -*- coding: UTF-8 -*-
|
||||
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from copy import copy
|
||||
|
@ -78,6 +79,9 @@ class ParamsTab(ScrolledPanel):
|
|||
self.pencil_icon = wx.Image(os.path.join(get_resource_dir(
|
||||
"icons"), "pencil_20x20.png")).ConvertToBitmap()
|
||||
|
||||
self.randomize_icon = wx.Image(os.path.join(get_resource_dir(
|
||||
"icons"), "randomize_20x20.png")).ConvertToBitmap()
|
||||
|
||||
self.__set_properties()
|
||||
self.__do_layout()
|
||||
|
||||
|
@ -187,6 +191,16 @@ class ParamsTab(ScrolledPanel):
|
|||
|
||||
return values
|
||||
|
||||
def on_change_seed(self, event):
|
||||
|
||||
for node in self.nodes:
|
||||
random.seed()
|
||||
new_seed = random.randint(1, 10000)
|
||||
node.set_param("use_seed", new_seed)
|
||||
if self.on_change_hook:
|
||||
self.on_change_hook(self)
|
||||
event.Skip()
|
||||
|
||||
def apply(self):
|
||||
values = self.get_values()
|
||||
for node in self.nodes:
|
||||
|
@ -379,6 +393,17 @@ class ParamsTab(ScrolledPanel):
|
|||
self.inputs_to_params = {v: k for k, v in self.param_inputs.items()}
|
||||
|
||||
box.Add(self.settings_grid, proportion=1, flag=wx.ALL, border=10)
|
||||
|
||||
add_seed_button = False
|
||||
for param in self.params:
|
||||
if param.name[:6] == "random":
|
||||
add_seed_button = True
|
||||
if add_seed_button:
|
||||
self.change_seed_button = wx.Button(self, wx.ID_ANY, _("Change Seed"))
|
||||
self.change_seed_button.Bind(wx.EVT_BUTTON, self.on_change_seed)
|
||||
self.change_seed_button.SetBitmap(self.randomize_icon)
|
||||
box.Add(self.change_seed_button, proportion=0, flag=wx.ALIGN_CENTER_HORIZONTAL, border=10)
|
||||
|
||||
self.SetSizer(box)
|
||||
self.update_choice_widgets()
|
||||
|
||||
|
|
|
@ -119,6 +119,13 @@ inkstitch_attribs = [
|
|||
'pull_compensation_percent',
|
||||
'pull_compensation_rails',
|
||||
'stroke_first',
|
||||
'random_split_factor',
|
||||
'random_first_rail_factor_in',
|
||||
'random_first_rail_factor_out',
|
||||
'random_second_rail_factor_in',
|
||||
'random_second_rail_factor_out',
|
||||
'random_zigzag_spacing',
|
||||
'use_seed',
|
||||
# stitch_plan
|
||||
'invisible_layers',
|
||||
# Legacy
|
||||
|
|
Ładowanie…
Reference in New Issue