kopia lustrzana https://github.com/inkstitch/inkstitch
annotations (#3569)
* begin to add annotations to some extensions * break_apart: use path operations * do not follow pyembroidery importspull/3578/head
rodzic
e3ac18d643
commit
760c17b815
|
@ -9,6 +9,6 @@ from .base import InkstitchExtension
|
|||
|
||||
class About(InkstitchExtension):
|
||||
|
||||
def effect(self):
|
||||
def effect(self) -> None:
|
||||
app = AboutInkstitchApp()
|
||||
app.MainLoop()
|
||||
|
|
|
@ -16,7 +16,7 @@ class ApplyPalette(InkstitchExtension):
|
|||
Applies colors of a color palette to elements
|
||||
'''
|
||||
|
||||
def effect(self):
|
||||
def effect(self) -> None:
|
||||
# Remove selection, we want all the elements in the document
|
||||
self.svg.selection.clear()
|
||||
|
||||
|
@ -32,7 +32,7 @@ class ApplyPalette(InkstitchExtension):
|
|||
if palette_choice.palette:
|
||||
self.apply_palette(palette_choice.palette)
|
||||
|
||||
def apply_palette(self, palette_name):
|
||||
def apply_palette(self, palette_name: str) -> None:
|
||||
palette = ThreadCatalog().get_palette_by_name(palette_name)
|
||||
|
||||
# Iterate through the color blocks to apply colors
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
|
||||
import inkex
|
||||
|
||||
|
@ -31,7 +32,7 @@ class ApplyThreadlist(InkstitchExtension):
|
|||
self.arg_parser.add_argument("-m", "--method", type=int, default=1, dest="method")
|
||||
self.arg_parser.add_argument("-t", "--palette", type=str, default=None, dest="palette")
|
||||
|
||||
def effect(self):
|
||||
def effect(self) -> None:
|
||||
# Remove selection, we want all the elements in the document
|
||||
self.svg.selection.clear()
|
||||
|
||||
|
@ -72,7 +73,7 @@ class ApplyThreadlist(InkstitchExtension):
|
|||
if colors[i][1] is not None:
|
||||
element.node.set(INKSTITCH_ATTRIBS['cutwork_needle'], colors[i][1])
|
||||
|
||||
def verify_path(self, path):
|
||||
def verify_path(self, path: str) -> None:
|
||||
if not os.path.exists(path):
|
||||
inkex.errormsg(_("File not found."))
|
||||
sys.exit(1)
|
||||
|
@ -80,7 +81,7 @@ class ApplyThreadlist(InkstitchExtension):
|
|||
inkex.errormsg(_("The filepath specified is not a file but a dictionary.\nPlease choose a threadlist file to import."))
|
||||
sys.exit(1)
|
||||
|
||||
def verify_colors(self, colors, method):
|
||||
def verify_colors(self, colors: List[List[Optional[str]]], method: int) -> None:
|
||||
if all(c is None for c in colors):
|
||||
inkex.errormsg(_("Couldn't find any matching colors in the file."))
|
||||
if method == 1:
|
||||
|
@ -89,7 +90,7 @@ class ApplyThreadlist(InkstitchExtension):
|
|||
inkex.errormsg(_("Please chose an other color palette for your design."))
|
||||
sys.exit(1)
|
||||
|
||||
def parse_inkstitch_threadlist(self, path):
|
||||
def parse_inkstitch_threadlist(self, path: str) -> List[List[Optional[str]]]:
|
||||
colors = []
|
||||
with open(path) as threadlist:
|
||||
for line in threadlist:
|
||||
|
@ -102,7 +103,7 @@ class ApplyThreadlist(InkstitchExtension):
|
|||
colors.append([None, None])
|
||||
return colors
|
||||
|
||||
def parse_color_format(self, path):
|
||||
def parse_color_format(self, path: str) -> List[List[Optional[str]]]:
|
||||
colors = []
|
||||
threads = pyembroidery.read(path).threadlist
|
||||
for color in threads:
|
||||
|
@ -113,7 +114,7 @@ class ApplyThreadlist(InkstitchExtension):
|
|||
colors.append([color.hex_color(), None])
|
||||
return colors
|
||||
|
||||
def parse_threadlist_by_catalog_number(self, path):
|
||||
def parse_threadlist_by_catalog_number(self, path: str) -> List[List[Optional[str]]]:
|
||||
palette_name = self.options.palette
|
||||
palette = ThreadCatalog().get_palette_by_name(palette_name)
|
||||
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
# Copyright (c) 2010 Authors
|
||||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
import inkex
|
||||
from typing import Any, List, Optional, Union
|
||||
|
||||
from inkex import Boolean, Vector2d, errormsg
|
||||
|
||||
from ..elements import Stroke
|
||||
from ..i18n import _
|
||||
|
@ -17,12 +19,12 @@ class AutoRun(CommandsExtension):
|
|||
def __init__(self, *args, **kwargs):
|
||||
CommandsExtension.__init__(self, *args, **kwargs)
|
||||
|
||||
self.arg_parser.add_argument("-b", "--break_up", dest="break_up", type=inkex.Boolean, default=True)
|
||||
self.arg_parser.add_argument("-p", "--preserve_order", dest="preserve_order", type=inkex.Boolean, default=False)
|
||||
self.arg_parser.add_argument("-b", "--break_up", dest="break_up", type=Boolean, default=True)
|
||||
self.arg_parser.add_argument("-p", "--preserve_order", dest="preserve_order", type=Boolean, default=False)
|
||||
self.arg_parser.add_argument("-o", "--options", dest="options", type=str, default="")
|
||||
self.arg_parser.add_argument("-i", "--info", dest="help", type=str, default="")
|
||||
|
||||
def effect(self):
|
||||
def effect(self) -> None:
|
||||
elements = self.check_selection()
|
||||
if not elements:
|
||||
return
|
||||
|
@ -34,32 +36,29 @@ class AutoRun(CommandsExtension):
|
|||
|
||||
autorun(elements, self.options.preserve_order, break_up, starting_point, ending_point, self.options.trim)
|
||||
|
||||
def get_starting_point(self):
|
||||
def get_starting_point(self) -> Optional[Vector2d]:
|
||||
return self.get_command_point("autoroute_start")
|
||||
|
||||
def get_ending_point(self):
|
||||
def get_ending_point(self) -> Optional[Vector2d]:
|
||||
return self.get_command_point("autoroute_end")
|
||||
|
||||
def get_command_point(self, command_type):
|
||||
def get_command_point(self, command_type: str) -> Optional[Vector2d]:
|
||||
command = None
|
||||
for stroke in self.elements:
|
||||
command = stroke.get_command(command_type)
|
||||
# return the first occurence directly
|
||||
if command:
|
||||
return command.target_point
|
||||
return None
|
||||
|
||||
def check_selection(self):
|
||||
if not self.get_elements():
|
||||
return
|
||||
|
||||
def check_selection(self) -> List[Union[Stroke, Any]]:
|
||||
if not self.svg.selection:
|
||||
# L10N auto-route running stitch columns extension
|
||||
inkex.errormsg(_("Please select one or more stroke elements."))
|
||||
return False
|
||||
errormsg(_("Please select one or more stroke elements."))
|
||||
|
||||
self.get_elements()
|
||||
elements = [element for element in self.elements if isinstance(element, Stroke)]
|
||||
if len(elements) == 0:
|
||||
inkex.errormsg(_("Please select at least one stroke element."))
|
||||
return False
|
||||
errormsg(_("Please select at least one stroke element."))
|
||||
|
||||
return elements
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
||||
|
||||
from copy import copy
|
||||
from typing import List, Tuple, Union
|
||||
|
||||
import inkex
|
||||
from inkex import Path, errormsg
|
||||
from shapely.geometry import LinearRing, MultiPolygon, Polygon
|
||||
from shapely.ops import polygonize, unary_union
|
||||
|
||||
|
@ -26,9 +27,9 @@ class BreakApart(InkstitchExtension):
|
|||
self.arg_parser.add_argument("-m", "--method", type=int, default=1, dest="method")
|
||||
self.minimum_size = 5
|
||||
|
||||
def effect(self): # noqa: C901
|
||||
def effect(self) -> None: # noqa: C901
|
||||
if not self.svg.selection:
|
||||
inkex.errormsg(_("Please select one or more fill areas to break apart."))
|
||||
errormsg(_("Please select one or more fill areas to break apart."))
|
||||
return
|
||||
|
||||
elements = []
|
||||
|
@ -58,29 +59,29 @@ class BreakApart(InkstitchExtension):
|
|||
if polygons:
|
||||
self.polygons_to_nodes(polygons, element)
|
||||
|
||||
def break_apart_paths(self, paths):
|
||||
def break_apart_paths(self, paths: List[List[Union[List[float], Tuple[float, float]]]]) -> List[Polygon]:
|
||||
polygons = []
|
||||
for path in paths:
|
||||
if len(path) < 3:
|
||||
continue
|
||||
linearring = LinearRing(path)
|
||||
if not linearring.is_simple:
|
||||
linearring = unary_union(linearring)
|
||||
for polygon in polygonize(linearring):
|
||||
union = unary_union(linearring)
|
||||
for polygon in polygonize(union):
|
||||
polygons.append(polygon)
|
||||
else:
|
||||
polygon = Polygon(path).buffer(0)
|
||||
polygons.append(polygon)
|
||||
return polygons
|
||||
|
||||
def combine_overlapping_polygons(self, polygons):
|
||||
def combine_overlapping_polygons(self, polygons: List[Polygon]) -> List[Polygon]:
|
||||
for polygon in polygons:
|
||||
for other in polygons:
|
||||
if polygon == other:
|
||||
continue
|
||||
if polygon.overlaps(other):
|
||||
diff = polygon.symmetric_difference(other)
|
||||
if diff.geom_type == 'MultiPolygon':
|
||||
if isinstance(diff, MultiPolygon):
|
||||
polygons.remove(other)
|
||||
polygons.remove(polygon)
|
||||
for p in diff.geoms:
|
||||
|
@ -91,17 +92,17 @@ class BreakApart(InkstitchExtension):
|
|||
return polygons
|
||||
return polygons
|
||||
|
||||
def geom_is_valid(self, geom):
|
||||
def geom_is_valid(self, geom: MultiPolygon) -> bool:
|
||||
valid = geom.is_valid
|
||||
return valid
|
||||
|
||||
def ensure_minimum_size(self, polygons, size):
|
||||
def ensure_minimum_size(self, polygons: List[Polygon], size: int) -> List[Polygon]:
|
||||
for polygon in polygons:
|
||||
if polygon.area < size:
|
||||
polygons.remove(polygon)
|
||||
return polygons
|
||||
|
||||
def recombine_polygons(self, polygons):
|
||||
def recombine_polygons(self, polygons: List[Polygon]) -> List[List[Polygon]]:
|
||||
polygons.sort(key=lambda polygon: polygon.area, reverse=True)
|
||||
multipolygons = []
|
||||
holes = []
|
||||
|
@ -126,10 +127,12 @@ class BreakApart(InkstitchExtension):
|
|||
multipolygons.append(polygon_list)
|
||||
return multipolygons
|
||||
|
||||
def polygons_to_nodes(self, polygon_list, element):
|
||||
def polygons_to_nodes(self, polygon_list: List[List[Polygon]], element: EmbroideryElement) -> None:
|
||||
# reverse the list of polygons, we don't want to cover smaller shapes
|
||||
polygon_list = polygon_list[::-1]
|
||||
index = element.node.getparent().index(element.node)
|
||||
parent = element.node.getparent()
|
||||
assert parent is not None, "The element should be part of a group."
|
||||
index = parent.index(element.node)
|
||||
for polygons in polygon_list:
|
||||
if polygons[0].area < 5:
|
||||
continue
|
||||
|
@ -148,14 +151,12 @@ class BreakApart(InkstitchExtension):
|
|||
el.set('id', node_id)
|
||||
|
||||
# Set path
|
||||
d = ""
|
||||
d = Path()
|
||||
for polygon in polygons:
|
||||
d += "M"
|
||||
for x, y in polygon.exterior.coords:
|
||||
d += "%s,%s " % (x, y)
|
||||
d += " "
|
||||
d += "Z"
|
||||
el.set('d', d)
|
||||
path = Path(polygon.exterior.coords)
|
||||
path.close()
|
||||
d += path
|
||||
el.set('d', str(d))
|
||||
el.set('transform', get_correction_transform(element.node))
|
||||
element.node.getparent().insert(index, el)
|
||||
element.node.getparent().remove(element.node)
|
||||
parent.insert(index, el)
|
||||
parent.remove(element.node)
|
||||
|
|
1
mypy.ini
1
mypy.ini
|
@ -38,3 +38,4 @@ ignore_missing_imports = True
|
|||
# ... And this one is ours but is missing type information for now anyway...
|
||||
[mypy-pyembroidery.*]
|
||||
ignore_missing_imports = True
|
||||
follow_imports = skip
|
||||
|
|
Ładowanie…
Reference in New Issue