knit-graphs 0.0.10__py3-none-any.whl → 0.0.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docs/source/conf.py +71 -71
- docs/source/index.rst +0 -4
- knit_graphs/Course.py +64 -41
- knit_graphs/Knit_Graph.py +70 -162
- knit_graphs/Knit_Graph_Visualizer.py +386 -185
- knit_graphs/Loop.py +124 -117
- knit_graphs/Pull_Direction.py +5 -2
- knit_graphs/Yarn.py +257 -219
- knit_graphs/artin_wale_braids/Crossing_Direction.py +2 -0
- knit_graphs/artin_wale_braids/Loop_Braid_Graph.py +47 -56
- knit_graphs/artin_wale_braids/Wale.py +67 -79
- knit_graphs/artin_wale_braids/Wale_Braid.py +8 -2
- knit_graphs/artin_wale_braids/Wale_Braid_Word.py +45 -31
- knit_graphs/artin_wale_braids/Wale_Group.py +53 -43
- knit_graphs/basic_knit_graph_generators.py +96 -140
- knit_graphs/directed_loop_graph.py +454 -0
- knit_graphs/knit_graph_builder.py +187 -0
- knit_graphs/knit_graph_errors/__init__.py +0 -0
- knit_graphs/knit_graph_errors/knit_graph_error.py +30 -0
- knit_graphs/py.typed +0 -0
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.12.dist-info}/METADATA +3 -2
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.12.dist-info}/RECORD +24 -19
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.12.dist-info}/LICENSE +0 -0
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.12.dist-info}/WHEEL +0 -0
|
@@ -2,20 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
This module provides the Wale_Group class which represents a collection of interconnected wales that are joined through decrease operations, forming a tree-like structure of vertical stitch columns.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from __future__ import annotations
|
|
6
7
|
|
|
7
|
-
from typing import TYPE_CHECKING,
|
|
8
|
+
from typing import TYPE_CHECKING, TypeVar
|
|
8
9
|
|
|
9
10
|
from networkx import DiGraph, dfs_preorder_nodes
|
|
10
11
|
|
|
11
12
|
from knit_graphs.artin_wale_braids.Wale import Wale
|
|
13
|
+
from knit_graphs.directed_loop_graph import Directed_Loop_Graph
|
|
12
14
|
from knit_graphs.Loop import Loop
|
|
15
|
+
from knit_graphs.Pull_Direction import Pull_Direction
|
|
13
16
|
|
|
14
17
|
if TYPE_CHECKING:
|
|
15
18
|
from knit_graphs.Knit_Graph import Knit_Graph
|
|
16
19
|
|
|
20
|
+
LoopT = TypeVar("LoopT", bound=Loop)
|
|
21
|
+
|
|
17
22
|
|
|
18
|
-
class Wale_Group:
|
|
23
|
+
class Wale_Group(Directed_Loop_Graph[LoopT, Pull_Direction]):
|
|
19
24
|
"""A graph structure maintaining relationships between connected wales through decrease operations.
|
|
20
25
|
|
|
21
26
|
This class represents a collection of wales that are connected through decrease stitches, where multiple wales merge into fewer wales as the knitting progresses upward.
|
|
@@ -23,48 +28,71 @@ class Wale_Group:
|
|
|
23
28
|
|
|
24
29
|
Attributes:
|
|
25
30
|
wale_graph (DiGraph): A directed graph representing the relationships between wales in this group.
|
|
26
|
-
stitch_graph (DiGraph): A directed graph of all individual stitch connections within this wale group.
|
|
27
31
|
top_loops (dict[Loop, Wale]): Mapping from the last (top) loop of each wale to the wale itself.
|
|
28
32
|
bottom_loops (dict[Loop, Wale]): Mapping from the first (bottom) loop of each wale to the wale itself.
|
|
29
33
|
"""
|
|
30
34
|
|
|
31
|
-
def __init__(self, terminal_loop:
|
|
35
|
+
def __init__(self, terminal_loop: LoopT, knit_graph: Knit_Graph[LoopT]):
|
|
32
36
|
"""Initialize a wale group starting from a terminal wale and building downward.
|
|
33
37
|
|
|
34
38
|
Args:
|
|
35
39
|
terminal_loop (Loop): The terminal loop of this wale-group. All the wales in the group connect up to this loop.
|
|
36
40
|
knit_graph (Knit_Graph): The parent knit graph that contains this wale group.
|
|
37
41
|
"""
|
|
42
|
+
super().__init__()
|
|
38
43
|
self.wale_graph: DiGraph = DiGraph()
|
|
39
|
-
self.
|
|
40
|
-
self.
|
|
41
|
-
self.
|
|
42
|
-
self.
|
|
43
|
-
self.bottom_loops: dict[Loop, Wale] = {}
|
|
44
|
+
self._knit_graph: Knit_Graph[LoopT] = knit_graph
|
|
45
|
+
self._terminal_loop: LoopT = terminal_loop
|
|
46
|
+
self.top_loops: dict[LoopT, Wale] = {}
|
|
47
|
+
self.bottom_loops: dict[LoopT, Wale] = {}
|
|
44
48
|
self._build_wale_group()
|
|
45
49
|
|
|
46
50
|
@property
|
|
47
|
-
def terminal_loop(self) ->
|
|
51
|
+
def terminal_loop(self) -> LoopT:
|
|
48
52
|
"""
|
|
49
53
|
Returns:
|
|
50
|
-
|
|
54
|
+
LoopT: The loop that terminates all wales in this group.
|
|
51
55
|
"""
|
|
52
56
|
return self._terminal_loop
|
|
53
57
|
|
|
58
|
+
def get_loops_over_courses(self) -> list[list[LoopT]]:
|
|
59
|
+
"""Get loops organized by their course (horizontal row) within this wale group.
|
|
60
|
+
|
|
61
|
+
This method traces through the stitch connections starting from the terminal wale's top loop and groups loops by their vertical position (course) in the knitted structure.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
list[list[LoopT]]: A list where each inner list contains all loops that belong to the same course, ordered from top to bottom courses. Returns empty list if there is no terminal wale.
|
|
65
|
+
"""
|
|
66
|
+
courses: list[list[LoopT]] = []
|
|
67
|
+
cur_course: list[LoopT] = [self._terminal_loop]
|
|
68
|
+
while len(cur_course) > 0:
|
|
69
|
+
courses.append(cur_course)
|
|
70
|
+
next_course: list[LoopT] = []
|
|
71
|
+
for loop in cur_course:
|
|
72
|
+
next_course.extend(self.predecessors(loop))
|
|
73
|
+
cur_course = next_course
|
|
74
|
+
return courses
|
|
75
|
+
|
|
54
76
|
def _build_wale_group(self) -> None:
|
|
55
77
|
full_wales = self._knit_graph.get_wales_ending_with_loop(self._terminal_loop)
|
|
56
78
|
# Build up the stitch graph.
|
|
57
79
|
for wale in full_wales:
|
|
58
|
-
u_loops
|
|
59
|
-
v_loops
|
|
60
|
-
for u, v in zip(u_loops, v_loops):
|
|
61
|
-
|
|
80
|
+
u_loops = wale[:-1]
|
|
81
|
+
v_loops = wale[1:]
|
|
82
|
+
for u, v in zip(u_loops, v_loops, strict=False):
|
|
83
|
+
if u not in self:
|
|
84
|
+
self.add_loop(u)
|
|
85
|
+
if v not in self:
|
|
86
|
+
self.add_loop(v)
|
|
87
|
+
self.add_edge(u, v, self._knit_graph.get_pull_direction(u, v))
|
|
62
88
|
wales_to_split = full_wales
|
|
63
89
|
while len(wales_to_split) > 0:
|
|
64
90
|
wale_to_split = wales_to_split.pop()
|
|
65
91
|
split = False
|
|
66
|
-
upper_loops =
|
|
67
|
-
for
|
|
92
|
+
upper_loops = wale_to_split[1:]
|
|
93
|
+
for (
|
|
94
|
+
loop
|
|
95
|
+
) in upper_loops: # skip first loop in each wale as it may be already connected to a discovered decrease.
|
|
68
96
|
if len(loop.parent_loops) > 1: # Focal of a decrease.
|
|
69
97
|
clean_wale, remaining_wale = wale_to_split.split_wale(loop)
|
|
70
98
|
if not self.wale_graph.has_node(clean_wale):
|
|
@@ -75,7 +103,7 @@ class Wale_Group:
|
|
|
75
103
|
break
|
|
76
104
|
if not split:
|
|
77
105
|
self._add_wale(wale_to_split)
|
|
78
|
-
for
|
|
106
|
+
for _bot_loop, lower_wale in self.bottom_loops.items():
|
|
79
107
|
if lower_wale.last_loop in self.bottom_loops:
|
|
80
108
|
self.wale_graph.add_edge(lower_wale, self.bottom_loops[lower_wale.last_loop])
|
|
81
109
|
|
|
@@ -84,24 +112,6 @@ class Wale_Group:
|
|
|
84
112
|
self.top_loops[wale.last_loop] = wale
|
|
85
113
|
self.bottom_loops[wale.first_loop] = wale
|
|
86
114
|
|
|
87
|
-
def get_loops_over_courses(self) -> list[list[Loop]]:
|
|
88
|
-
"""Get loops organized by their course (horizontal row) within this wale group.
|
|
89
|
-
|
|
90
|
-
This method traces through the stitch connections starting from the terminal wale's top loop and groups loops by their vertical position (course) in the knitted structure.
|
|
91
|
-
|
|
92
|
-
Returns:
|
|
93
|
-
list[list[Loop]]: A list where each inner list contains all loops that belong to the same course, ordered from top to bottom courses. Returns empty list if there is no terminal wale.
|
|
94
|
-
"""
|
|
95
|
-
courses: list[list[Loop]] = []
|
|
96
|
-
cur_course: list[Loop] = [self._terminal_loop]
|
|
97
|
-
while len(cur_course) > 0:
|
|
98
|
-
courses.append(cur_course)
|
|
99
|
-
next_course = []
|
|
100
|
-
for loop in cur_course:
|
|
101
|
-
next_course.extend(self.stitch_graph.predecessors(loop))
|
|
102
|
-
cur_course = next_course
|
|
103
|
-
return courses
|
|
104
|
-
|
|
105
115
|
def __len__(self) -> int:
|
|
106
116
|
"""Get the height of the wale group measured as the maximum number of loops from base to terminal.
|
|
107
117
|
|
|
@@ -111,7 +121,7 @@ class Wale_Group:
|
|
|
111
121
|
int: The height of the wale group from the base loops to the tallest terminal, measured in total number of loops.
|
|
112
122
|
"""
|
|
113
123
|
max_len = 0
|
|
114
|
-
for
|
|
124
|
+
for _bot_loop, wale in self.bottom_loops.items():
|
|
115
125
|
path_len = sum(len(successor) for successor in dfs_preorder_nodes(self.wale_graph, wale))
|
|
116
126
|
max_len = max(max_len, path_len)
|
|
117
127
|
return max_len
|
|
@@ -123,18 +133,18 @@ class Wale_Group:
|
|
|
123
133
|
"""
|
|
124
134
|
return hash(self._terminal_loop)
|
|
125
135
|
|
|
126
|
-
def __contains__(self, item:
|
|
136
|
+
def __contains__(self, item: LoopT | int | tuple[LoopT | int, LoopT | int] | Wale) -> bool:
|
|
127
137
|
"""
|
|
128
138
|
Args:
|
|
129
|
-
item (
|
|
139
|
+
item (LoopT | int | tuple[LoopT | int, LoopT | int] | Wale): The item to check for in the wale group.
|
|
130
140
|
|
|
131
141
|
Returns:
|
|
132
|
-
bool: True if the given loop, loop_id (int), or wale is in this group.
|
|
142
|
+
bool: True if the given loop, loop_id (int), pair of loops, or wale is in this group.
|
|
133
143
|
"""
|
|
134
|
-
if isinstance(item,
|
|
135
|
-
return item in self.stitch_graph.nodes
|
|
136
|
-
else: # isinstance(item, Wale):
|
|
144
|
+
if isinstance(item, Wale):
|
|
137
145
|
return item in self.wale_graph
|
|
146
|
+
else:
|
|
147
|
+
return super().__contains__(item)
|
|
138
148
|
|
|
139
149
|
def __str__(self) -> str:
|
|
140
150
|
"""
|
|
@@ -3,30 +3,35 @@
|
|
|
3
3
|
This module provides utility functions for creating common knitting patterns and structures as knit graphs.
|
|
4
4
|
These functions serve as building blocks for testing and demonstration purposes.
|
|
5
5
|
"""
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
|
|
7
11
|
from knit_graphs.Knit_Graph import Knit_Graph
|
|
12
|
+
from knit_graphs.knit_graph_builder import Knit_Graph_Builder
|
|
8
13
|
from knit_graphs.Loop import Loop
|
|
9
14
|
from knit_graphs.Pull_Direction import Pull_Direction
|
|
10
15
|
from knit_graphs.Yarn import Yarn
|
|
11
16
|
|
|
12
17
|
|
|
13
|
-
def co_loops(width: int) -> tuple[Knit_Graph, Yarn]:
|
|
18
|
+
def co_loops(width: int) -> tuple[Knit_Graph_Builder[Loop], Knit_Graph[Loop], Yarn[Loop]]:
|
|
14
19
|
"""Create a cast-on row of loops forming the foundation for knitting patterns.
|
|
15
20
|
|
|
16
21
|
Args:
|
|
17
22
|
width (int): The number of loops to create in the cast-on row.
|
|
18
23
|
|
|
19
24
|
Returns:
|
|
20
|
-
tuple[Knit_Graph, Yarn]: A tuple containing the knit graph with one course of the specified width and the yarn used to create it.
|
|
25
|
+
tuple[Knit_Graph_Builder[Loop], Knit_Graph[Loop], Yarn[Loop]: A tuple containing the knit graph builder and its knitgraph with one course of the specified width and the yarn used to create it.
|
|
21
26
|
"""
|
|
22
|
-
|
|
23
|
-
yarn =
|
|
27
|
+
builder = Knit_Graph_Builder[Loop]()
|
|
28
|
+
yarn = builder.add_yarn()
|
|
24
29
|
for _ in range(0, width):
|
|
25
|
-
_loop =
|
|
26
|
-
return knit_graph, yarn
|
|
30
|
+
_loop = builder.tuck(yarn)
|
|
31
|
+
return builder, builder.knit_graph, yarn
|
|
27
32
|
|
|
28
33
|
|
|
29
|
-
def jersey_swatch(width: int, height: int) -> Knit_Graph:
|
|
34
|
+
def jersey_swatch(width: int, height: int) -> Knit_Graph[Loop]:
|
|
30
35
|
"""Generate a rectangular knit swatch with all knit stitches in a flat sheet structure.
|
|
31
36
|
|
|
32
37
|
This creates a basic stockinette/jersey pattern where all stitches are worked as knit stitches from back to front.
|
|
@@ -38,19 +43,14 @@ def jersey_swatch(width: int, height: int) -> Knit_Graph:
|
|
|
38
43
|
Returns:
|
|
39
44
|
Knit_Graph: A knit graph representing a flat rectangular swatch with all knit stitches.
|
|
40
45
|
"""
|
|
41
|
-
knit_graph, yarn = co_loops(width)
|
|
42
|
-
last_course =
|
|
46
|
+
builder, knit_graph, yarn = co_loops(width)
|
|
47
|
+
last_course: Sequence[Loop] = knit_graph.get_courses()[0]
|
|
43
48
|
for _ in range(0, height):
|
|
44
|
-
|
|
45
|
-
for parent_loop in reversed(last_course):
|
|
46
|
-
child_loop = yarn.make_loop_on_end()
|
|
47
|
-
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=Pull_Direction.BtF)
|
|
48
|
-
next_course.append(child_loop)
|
|
49
|
-
last_course = next_course
|
|
49
|
+
last_course = [builder.knit(yarn, [parent_loop]) for parent_loop in reversed(last_course)]
|
|
50
50
|
return knit_graph
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
def jersey_tube(tube_width: int, height: int) -> Knit_Graph:
|
|
53
|
+
def jersey_tube(tube_width: int, height: int) -> Knit_Graph[Loop]:
|
|
54
54
|
"""Generate a tubular knit structure with all knit stitches worked in the round.
|
|
55
55
|
|
|
56
56
|
This creates a seamless tube by knitting in the round, where the front and back sections are connected by floats to maintain the circular structure.
|
|
@@ -62,29 +62,22 @@ def jersey_tube(tube_width: int, height: int) -> Knit_Graph:
|
|
|
62
62
|
Returns:
|
|
63
63
|
Knit_Graph: A knit graph representing a seamless tube with all knit stitches.
|
|
64
64
|
"""
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"""Internal helper function to set up float connections between front and back of tube."""
|
|
70
|
-
front_loops = last_course[0:tube_width]
|
|
71
|
-
back_loops = last_course[tube_width:]
|
|
72
|
-
for first_front, second_front, back in zip(front_loops[0:-1], front_loops[1:], reversed(back_loops)):
|
|
73
|
-
yarn.add_loop_behind_float(back, first_front, second_front)
|
|
74
|
-
for (first_back, second_back, front) in zip(back_loops[0:-1], back_loops[1:], reversed(front_loops)):
|
|
75
|
-
yarn.add_loop_in_front_of_float(front, first_back, second_back)
|
|
76
|
-
|
|
77
|
-
_set_tube_floats()
|
|
65
|
+
builder = Knit_Graph_Builder[Loop]()
|
|
66
|
+
yarn = builder.add_yarn()
|
|
67
|
+
front_of_tube = [builder.tuck(yarn) for _ in range(0, tube_width)]
|
|
68
|
+
back_of_tube = [builder.tuck(yarn) for _ in reversed(front_of_tube)]
|
|
78
69
|
for _ in range(0, height):
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
70
|
+
for fl, bl in zip(front_of_tube[:-1], reversed(back_of_tube[1:]), strict=False):
|
|
71
|
+
builder.position_float(fl, loops_behind_float=[bl])
|
|
72
|
+
for fl, bl in zip(reversed(front_of_tube[1:]), back_of_tube[:-1], strict=False):
|
|
73
|
+
builder.position_float(bl, loops_in_front_of_float=[fl])
|
|
74
|
+
front_of_tube = [builder.knit(yarn, [fl], Pull_Direction.BtF) for fl in front_of_tube]
|
|
75
|
+
back_of_tube = [builder.knit(yarn, [bl], Pull_Direction.FtB) for bl in back_of_tube]
|
|
76
|
+
|
|
77
|
+
return builder.knit_graph
|
|
85
78
|
|
|
86
79
|
|
|
87
|
-
def kp_rib_swatch(width: int, height: int) -> Knit_Graph:
|
|
80
|
+
def kp_rib_swatch(width: int, height: int) -> Knit_Graph[Loop]:
|
|
88
81
|
"""Generate a knit-purl ribbing swatch with alternating wales of knit and purl stitches.
|
|
89
82
|
|
|
90
83
|
This creates a 1x1 ribbing pattern where knit and purl wales alternate, maintaining their stitch type throughout the height of the swatch for a stretchy, textured fabric.
|
|
@@ -96,30 +89,19 @@ def kp_rib_swatch(width: int, height: int) -> Knit_Graph:
|
|
|
96
89
|
Returns:
|
|
97
90
|
Knit_Graph: A knit graph representing a ribbed swatch with alternating knit and purl wales.
|
|
98
91
|
"""
|
|
99
|
-
knit_graph, yarn = co_loops(width)
|
|
100
|
-
last_course = knit_graph.get_courses()[0]
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
last_course = next_course
|
|
109
|
-
for _ in range(1, height):
|
|
110
|
-
next_course = []
|
|
111
|
-
for parent_loop in reversed(last_course):
|
|
112
|
-
grand_parent = parent_loop.parent_loops[0]
|
|
113
|
-
parent_pull = knit_graph.get_pull_direction(grand_parent, parent_loop)
|
|
114
|
-
assert isinstance(parent_pull, Pull_Direction)
|
|
115
|
-
child_loop = yarn.make_loop_on_end()
|
|
116
|
-
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=parent_pull)
|
|
117
|
-
next_course.append(child_loop)
|
|
118
|
-
last_course = next_course
|
|
92
|
+
builder, knit_graph, yarn = co_loops(width)
|
|
93
|
+
last_course: Sequence[Loop] = knit_graph.get_courses()[0]
|
|
94
|
+
for _ in range(0, height):
|
|
95
|
+
assert yarn.last_loop is not None
|
|
96
|
+
pull_direction = yarn.last_loop.pull_directions[0] if yarn.last_loop.has_parent_loops else Pull_Direction.BtF
|
|
97
|
+
last_course = [
|
|
98
|
+
builder.knit(yarn, [parent_loop], pull_direction=pull_direction if i % 2 == 0 else pull_direction.opposite)
|
|
99
|
+
for i, parent_loop in enumerate(reversed(last_course))
|
|
100
|
+
]
|
|
119
101
|
return knit_graph
|
|
120
102
|
|
|
121
103
|
|
|
122
|
-
def seed_swatch(width: int, height: int) -> Knit_Graph:
|
|
104
|
+
def seed_swatch(width: int, height: int) -> Knit_Graph[Loop]:
|
|
123
105
|
"""Generate a seed stitch swatch with a checkerboard pattern of knit and purl stitches.
|
|
124
106
|
|
|
125
107
|
This creates a textured fabric where each stitch alternates between knit and purl both horizontally and vertically, creating a bumpy, non-curling fabric texture.
|
|
@@ -131,30 +113,19 @@ def seed_swatch(width: int, height: int) -> Knit_Graph:
|
|
|
131
113
|
Returns:
|
|
132
114
|
Knit_Graph: A knit graph representing a seed stitch swatch with checkerboard knit-purl pattern.
|
|
133
115
|
"""
|
|
134
|
-
knit_graph, yarn = co_loops(width)
|
|
135
|
-
last_course = knit_graph.get_courses()[0]
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
last_course = next_course
|
|
144
|
-
for _ in range(1, height):
|
|
145
|
-
next_course = []
|
|
146
|
-
for parent_loop in reversed(last_course):
|
|
147
|
-
grand_parent = parent_loop.parent_loops[0]
|
|
148
|
-
parent_pull = knit_graph.get_pull_direction(grand_parent, parent_loop)
|
|
149
|
-
assert isinstance(parent_pull, Pull_Direction)
|
|
150
|
-
child_loop = yarn.make_loop_on_end()
|
|
151
|
-
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=parent_pull.opposite())
|
|
152
|
-
next_course.append(child_loop)
|
|
153
|
-
last_course = next_course
|
|
116
|
+
builder, knit_graph, yarn = co_loops(width)
|
|
117
|
+
last_course: Sequence[Loop] = knit_graph.get_courses()[0]
|
|
118
|
+
for _ in range(0, height):
|
|
119
|
+
assert yarn.last_loop is not None
|
|
120
|
+
pull_direction = yarn.last_loop.pull_directions[0] if yarn.last_loop.has_parent_loops else Pull_Direction.BtF
|
|
121
|
+
last_course = [
|
|
122
|
+
builder.knit(yarn, [parent_loop], pull_direction=pull_direction.opposite if i % 2 == 0 else pull_direction)
|
|
123
|
+
for i, parent_loop in enumerate(reversed(last_course))
|
|
124
|
+
]
|
|
154
125
|
return knit_graph
|
|
155
126
|
|
|
156
127
|
|
|
157
|
-
def lace_mesh(width: int, height: int) -> Knit_Graph:
|
|
128
|
+
def lace_mesh(width: int, height: int) -> Knit_Graph[Loop]:
|
|
158
129
|
"""Generate a mesh pattern with alternating left and right leaning decrease paired to yarn-overs.
|
|
159
130
|
These pairings create a basic lace pattern with eyelets formed around the increases.
|
|
160
131
|
|
|
@@ -165,48 +136,31 @@ def lace_mesh(width: int, height: int) -> Knit_Graph:
|
|
|
165
136
|
Returns:
|
|
166
137
|
Knit_Graph: A knit graph representing a mesh swatch.
|
|
167
138
|
"""
|
|
168
|
-
knit_graph, yarn = co_loops(width)
|
|
169
|
-
last_course = knit_graph.get_courses()[0]
|
|
170
|
-
next_course = []
|
|
171
|
-
for parent_loop in reversed(last_course):
|
|
172
|
-
child_loop = yarn.make_loop_on_end()
|
|
173
|
-
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=Pull_Direction.BtF)
|
|
174
|
-
next_course.append(child_loop)
|
|
175
|
-
last_course = next_course
|
|
139
|
+
builder, knit_graph, yarn = co_loops(width)
|
|
140
|
+
last_course = [builder.knit(yarn, [p]) for p in reversed(knit_graph.get_courses()[0])]
|
|
176
141
|
for _ in range(1, height):
|
|
177
|
-
|
|
142
|
+
dec1 = last_course[1::3]
|
|
143
|
+
dec2 = last_course[2::3]
|
|
144
|
+
decs = [
|
|
145
|
+
dec_parents if i % 2 == 0 else (dec_parents[1], dec_parents[0])
|
|
146
|
+
for i, dec_parents in enumerate(zip(reversed(dec1), reversed(dec2), strict=False))
|
|
147
|
+
]
|
|
148
|
+
knits = last_course[0::3]
|
|
178
149
|
next_course = []
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
assert isinstance(yo_parent, Loop)
|
|
190
|
-
knit_graph.connect_loops(yo_parent, child_loop, pull_direction=Pull_Direction.BtF, stack_position=1)
|
|
191
|
-
elif i % 6 == 4: # Fifth of every six stitches is bottom of decrease with next yarn-over's parent
|
|
192
|
-
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=Pull_Direction.BtF, stack_position=0)
|
|
193
|
-
prior_child = child_loop
|
|
194
|
-
elif i % 6 == 5: # The last of six stitches is the top of the prior decrease and new yarn-over
|
|
195
|
-
assert isinstance(prior_child, Loop)
|
|
196
|
-
knit_graph.connect_loops(parent_loop, prior_child, pull_direction=Pull_Direction.BtF, stack_position=1)
|
|
197
|
-
next_course.append(child_loop)
|
|
198
|
-
last_course = next_course
|
|
199
|
-
# Make a basic jersey course
|
|
200
|
-
next_course = []
|
|
201
|
-
for parent_loop in reversed(last_course):
|
|
202
|
-
child_loop = yarn.make_loop_on_end()
|
|
203
|
-
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=Pull_Direction.BtF)
|
|
204
|
-
next_course.append(child_loop)
|
|
205
|
-
last_course = next_course
|
|
150
|
+
for i, parent_loop in enumerate(reversed(knits)):
|
|
151
|
+
next_course.append(builder.knit(yarn, [parent_loop]))
|
|
152
|
+
if len(decs) > 0:
|
|
153
|
+
if i % 2 == 0:
|
|
154
|
+
next_course.append(builder.tuck(yarn))
|
|
155
|
+
next_course.append(builder.knit(yarn, decs.pop(0)))
|
|
156
|
+
else:
|
|
157
|
+
next_course.append(builder.knit(yarn, decs.pop(0)))
|
|
158
|
+
next_course.append(builder.tuck(yarn))
|
|
159
|
+
last_course = [builder.knit(yarn, [p]) for p in reversed(next_course)]
|
|
206
160
|
return knit_graph
|
|
207
161
|
|
|
208
162
|
|
|
209
|
-
def twist_cable(width: int, height: int) -> Knit_Graph:
|
|
163
|
+
def twist_cable(width: int, height: int) -> Knit_Graph[Loop]:
|
|
210
164
|
"""Generate a twisted cable pattern with alternating crossing directions and purl separators.
|
|
211
165
|
|
|
212
166
|
This creates a cable pattern with 1x1 twists that alternate direction every two rows, separated by purl wales to make the cable structure more prominent.
|
|
@@ -223,29 +177,31 @@ def twist_cable(width: int, height: int) -> Knit_Graph:
|
|
|
223
177
|
# p k/k p ->: 1-2
|
|
224
178
|
# p k k p <-: 0-1
|
|
225
179
|
# 0 1 2 3
|
|
226
|
-
knit_graph, yarn = co_loops(width)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
for r in range(1, height):
|
|
237
|
-
|
|
238
|
-
for i, parent_loop in enumerate(
|
|
239
|
-
if
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
180
|
+
builder, knit_graph, yarn = co_loops(width)
|
|
181
|
+
pull_directions = [
|
|
182
|
+
Pull_Direction.FtB,
|
|
183
|
+
Pull_Direction.BtF,
|
|
184
|
+
Pull_Direction.BtF,
|
|
185
|
+
Pull_Direction.FtB,
|
|
186
|
+
]
|
|
187
|
+
last_course = [
|
|
188
|
+
builder.knit(yarn, [p], pull_directions[i % 4]) for i, p in enumerate(reversed(knit_graph.get_courses()[0]))
|
|
189
|
+
]
|
|
190
|
+
for r in range(1, height, 2):
|
|
191
|
+
crossed_course: list[Loop] = []
|
|
192
|
+
for i, parent_loop in enumerate(last_course):
|
|
193
|
+
if i % 4 == 2:
|
|
194
|
+
crossed_course.insert(-1, parent_loop)
|
|
195
|
+
else:
|
|
196
|
+
crossed_course.append(parent_loop)
|
|
197
|
+
last_course = [builder.knit(yarn, [p]) for p in reversed(crossed_course)]
|
|
198
|
+
left_cable_loops = last_course[-2:0:-4]
|
|
199
|
+
right_cable_loops = last_course[-3:0:-4]
|
|
200
|
+
for left_loop, right_loop in zip(left_cable_loops, right_cable_loops, strict=False):
|
|
201
|
+
if r % 4 == 1:
|
|
202
|
+
builder.xfer(left_loop, over_loops_to_right=[right_loop])
|
|
243
203
|
else:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
for left_loop, right_loop in zip(next_course[1::4], next_course[2::4]):
|
|
248
|
-
knit_graph.add_crossing(left_loop, right_loop, crossing)
|
|
249
|
-
crossing = ~crossing
|
|
250
|
-
last_course = next_course
|
|
204
|
+
builder.xfer(left_loop, under_loops_to_right=[right_loop])
|
|
205
|
+
last_course = [builder.knit(yarn, [p]) for p in reversed(last_course)]
|
|
206
|
+
|
|
251
207
|
return knit_graph
|