knit-graphs 0.0.10__py3-none-any.whl → 0.0.11__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 +3 -1
- knit_graphs/Knit_Graph.py +17 -11
- knit_graphs/Knit_Graph_Visualizer.py +362 -149
- knit_graphs/Loop.py +3 -2
- knit_graphs/Pull_Direction.py +2 -0
- knit_graphs/Yarn.py +35 -10
- knit_graphs/artin_wale_braids/Crossing_Direction.py +2 -0
- knit_graphs/artin_wale_braids/Loop_Braid_Graph.py +16 -5
- knit_graphs/artin_wale_braids/Wale.py +16 -7
- knit_graphs/artin_wale_braids/Wale_Braid.py +1 -0
- knit_graphs/artin_wale_braids/Wale_Braid_Word.py +9 -8
- knit_graphs/artin_wale_braids/Wale_Group.py +8 -5
- knit_graphs/basic_knit_graph_generators.py +45 -10
- knit_graphs/py.typed +0 -0
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.11.dist-info}/METADATA +3 -2
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.11.dist-info}/RECORD +20 -19
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.11.dist-info}/LICENSE +0 -0
- {knit_graphs-0.0.10.dist-info → knit_graphs-0.0.11.dist-info}/WHEEL +0 -0
knit_graphs/Loop.py
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
This module defines the Loop class which represents individual loops in a knitting pattern.
|
|
4
4
|
Loops are the fundamental building blocks of knitted structures and maintain relationships with parent loops, yarn connections, and float positions.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
from __future__ import annotations
|
|
7
8
|
|
|
8
9
|
from typing import TYPE_CHECKING
|
|
@@ -225,7 +226,7 @@ class Loop:
|
|
|
225
226
|
"""
|
|
226
227
|
return self.loop_id
|
|
227
228
|
|
|
228
|
-
def __eq__(self, other:
|
|
229
|
+
def __eq__(self, other: object) -> bool:
|
|
229
230
|
"""Check equality with another base loop based on loop_id and type.
|
|
230
231
|
|
|
231
232
|
Args:
|
|
@@ -234,7 +235,7 @@ class Loop:
|
|
|
234
235
|
Returns:
|
|
235
236
|
bool: True if both loops have the same class and loop_id, False otherwise.
|
|
236
237
|
"""
|
|
237
|
-
return isinstance(other, other.__class__) and self.loop_id == other.loop_id
|
|
238
|
+
return isinstance(other, Loop) and isinstance(other, other.__class__) and self.loop_id == other.loop_id
|
|
238
239
|
|
|
239
240
|
def __lt__(self, other: Loop | int) -> bool:
|
|
240
241
|
"""Compare loop_id with another loop or integer for ordering.
|
knit_graphs/Pull_Direction.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This module defines the Pull_Direction enumeration which represents the two ways a loop can be pulled through other loops in knitting: from back to front (knit) or from front to back (purl).
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from __future__ import annotations
|
|
6
7
|
|
|
7
8
|
from enum import Enum
|
|
@@ -13,6 +14,7 @@ class Pull_Direction(Enum):
|
|
|
13
14
|
This enumeration represents the two directions that yarn can be pulled through loops to create different stitch types.
|
|
14
15
|
BtF (Back to Front) creates knit stitches, while FtB (Front to Back) creates purl stitches.
|
|
15
16
|
"""
|
|
17
|
+
|
|
16
18
|
BtF = "Knit"
|
|
17
19
|
FtB = "Purl"
|
|
18
20
|
|
knit_graphs/Yarn.py
CHANGED
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
This module contains the Yarn class and Yarn_Properties dataclass which together represent the physical yarn used in knitting patterns.
|
|
4
4
|
The Yarn class manages the sequence of loops along a yarn and their floating relationships.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
from __future__ import annotations
|
|
7
8
|
|
|
9
|
+
from collections.abc import Iterator
|
|
8
10
|
from dataclasses import dataclass
|
|
9
|
-
from typing import TYPE_CHECKING,
|
|
11
|
+
from typing import TYPE_CHECKING, cast
|
|
10
12
|
|
|
11
13
|
from networkx import DiGraph, dfs_edges, dfs_preorder_nodes
|
|
12
14
|
|
|
@@ -22,6 +24,7 @@ class Yarn_Properties:
|
|
|
22
24
|
|
|
23
25
|
This frozen dataclass contains all the physical and visual properties that characterize a yarn, including its structure, weight, and appearance.
|
|
24
26
|
"""
|
|
27
|
+
|
|
25
28
|
name: str = "yarn" # name (str): The name or identifier for this yarn type.
|
|
26
29
|
plies: int = 2 # plies (int): The number of individual strands twisted together to form the yarn.
|
|
27
30
|
weight: float = 28 # weight (float): The weight category or thickness of the yarn.
|
|
@@ -52,7 +55,7 @@ class Yarn_Properties:
|
|
|
52
55
|
"""
|
|
53
56
|
return Yarn_Properties()
|
|
54
57
|
|
|
55
|
-
def __eq__(self, other:
|
|
58
|
+
def __eq__(self, other: object) -> bool:
|
|
56
59
|
"""Check equality with another Yarn_Properties instance.
|
|
57
60
|
|
|
58
61
|
Args:
|
|
@@ -61,7 +64,13 @@ class Yarn_Properties:
|
|
|
61
64
|
Returns:
|
|
62
65
|
bool: True if all properties (name, plies, weight, color) are equal, False otherwise.
|
|
63
66
|
"""
|
|
64
|
-
return
|
|
67
|
+
return (
|
|
68
|
+
isinstance(other, Yarn_Properties)
|
|
69
|
+
and self.name == other.name
|
|
70
|
+
and self.plies == other.plies
|
|
71
|
+
and self.weight == other.weight
|
|
72
|
+
and self.color == other.color
|
|
73
|
+
)
|
|
65
74
|
|
|
66
75
|
def __hash__(self) -> int:
|
|
67
76
|
"""Get hash value for use in sets and dictionaries.
|
|
@@ -82,10 +91,15 @@ class Yarn:
|
|
|
82
91
|
loop_graph (DiGraph): The directed graph loops connected by yarn-wise float edges.
|
|
83
92
|
properties (Yarn_Properties): The physical and visual properties of this yarn.
|
|
84
93
|
"""
|
|
94
|
+
|
|
85
95
|
FRONT_LOOPS: str = "Front_Loops"
|
|
86
96
|
_BACK_LOOPS: str = "Back_Loops"
|
|
87
97
|
|
|
88
|
-
def __init__(
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
yarn_properties: None | Yarn_Properties = None,
|
|
101
|
+
knit_graph: None | Knit_Graph = None,
|
|
102
|
+
):
|
|
89
103
|
"""Initialize a yarn with the specified properties and optional knit graph association.
|
|
90
104
|
|
|
91
105
|
Args:
|
|
@@ -304,7 +318,7 @@ class Yarn:
|
|
|
304
318
|
KeyError: The given loop does not exist in the yarn.
|
|
305
319
|
"""
|
|
306
320
|
if loop not in self:
|
|
307
|
-
raise KeyError(f
|
|
321
|
+
raise KeyError(f"Loop {loop} does not exist on yarn {self}.")
|
|
308
322
|
prior_loop = self.prior_loop(loop)
|
|
309
323
|
next_loop = self.next_loop(loop)
|
|
310
324
|
if isinstance(prior_loop, Loop) and isinstance(next_loop, Loop): # Loop is between two floats to be merged.
|
|
@@ -313,7 +327,12 @@ class Yarn:
|
|
|
313
327
|
back_of_float_loops = self.get_loops_behind_float(prior_loop, loop)
|
|
314
328
|
back_of_float_loops.update(self.get_loops_behind_float(loop, next_loop))
|
|
315
329
|
self.loop_graph.remove_node(loop)
|
|
316
|
-
self.loop_graph.add_edge(
|
|
330
|
+
self.loop_graph.add_edge(
|
|
331
|
+
prior_loop,
|
|
332
|
+
next_loop,
|
|
333
|
+
Front_Loops=front_of_float_loops,
|
|
334
|
+
Back_Loops=back_of_float_loops,
|
|
335
|
+
)
|
|
317
336
|
for front_loop in front_of_float_loops:
|
|
318
337
|
front_loop.add_loop_in_front_of_float(prior_loop, next_loop)
|
|
319
338
|
for back_loop in back_of_float_loops:
|
|
@@ -433,8 +452,11 @@ class Yarn:
|
|
|
433
452
|
list[tuple[Loop, Loop, set[Loop]]]: List of tuples containing the two loops defining each float and the set of loops positioned in front of that float.
|
|
434
453
|
Only includes floats that have loops in front of them.
|
|
435
454
|
"""
|
|
436
|
-
return [
|
|
437
|
-
|
|
455
|
+
return [
|
|
456
|
+
(u, v, self.get_loops_in_front_of_float(u, v))
|
|
457
|
+
for u, v in self.edge_iter()
|
|
458
|
+
if len(self.get_loops_in_front_of_float(u, v)) > 0
|
|
459
|
+
]
|
|
438
460
|
|
|
439
461
|
def loops_behind_floats(self) -> list[tuple[Loop, Loop, set[Loop]]]:
|
|
440
462
|
"""Get all float segments with loops positioned behind them.
|
|
@@ -443,8 +465,11 @@ class Yarn:
|
|
|
443
465
|
list[tuple[Loop, Loop, set[Loop]]]: List of tuples containing the two loops defining each float and the set of loops positioned behind that float.
|
|
444
466
|
Only includes floats that have loops behind them.
|
|
445
467
|
"""
|
|
446
|
-
return [
|
|
447
|
-
|
|
468
|
+
return [
|
|
469
|
+
(u, v, self.get_loops_behind_float(u, v))
|
|
470
|
+
for u, v in self.edge_iter()
|
|
471
|
+
if len(self.get_loops_behind_float(u, v)) > 0
|
|
472
|
+
]
|
|
448
473
|
|
|
449
474
|
def __getitem__(self, item: int) -> Loop:
|
|
450
475
|
"""Get a loop by its ID from this yarn.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This module defines the Crossing_Direction enumeration which represents the different ways loops can cross over or under each other in cable knitting patterns.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from __future__ import annotations
|
|
6
7
|
|
|
7
8
|
from enum import Enum
|
|
@@ -13,6 +14,7 @@ class Crossing_Direction(Enum):
|
|
|
13
14
|
This enumeration represents the three possible crossing relationships between loops: crossing over to the right, crossing under to the right, or no crossing at all.
|
|
14
15
|
These directions are fundamental to representing cable structures in knitted fabrics.
|
|
15
16
|
"""
|
|
17
|
+
|
|
16
18
|
Over_Right = "+"
|
|
17
19
|
Under_Right = "-"
|
|
18
20
|
No_Cross = "|"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This module provides the Loop_Braid_Graph class which tracks crossing relationships between loops in cable knitting patterns using a directed graph structure.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from typing import cast
|
|
6
7
|
|
|
7
8
|
from networkx import DiGraph
|
|
@@ -19,6 +20,7 @@ class Loop_Braid_Graph:
|
|
|
19
20
|
Attributes:
|
|
20
21
|
loop_crossing_graph (DiGraph): A NetworkX directed graph storing loop crossing relationships with crossing direction attributes.
|
|
21
22
|
"""
|
|
23
|
+
|
|
22
24
|
_CROSSING = "crossing"
|
|
23
25
|
|
|
24
26
|
def __init__(self) -> None:
|
|
@@ -70,8 +72,11 @@ class Loop_Braid_Graph:
|
|
|
70
72
|
if left_loop not in self:
|
|
71
73
|
return []
|
|
72
74
|
else:
|
|
73
|
-
return [
|
|
74
|
-
|
|
75
|
+
return [
|
|
76
|
+
rl
|
|
77
|
+
for rl in self.loop_crossing_graph.successors(left_loop)
|
|
78
|
+
if self.get_crossing(left_loop, rl) is not Crossing_Direction.No_Cross
|
|
79
|
+
]
|
|
75
80
|
|
|
76
81
|
def right_crossing_loops(self, right_loop: Loop) -> list[Loop]:
|
|
77
82
|
"""Get all loops that cross with the given loop when it is on the right side.
|
|
@@ -85,8 +90,11 @@ class Loop_Braid_Graph:
|
|
|
85
90
|
if right_loop not in self:
|
|
86
91
|
return []
|
|
87
92
|
else:
|
|
88
|
-
return [
|
|
89
|
-
|
|
93
|
+
return [
|
|
94
|
+
l
|
|
95
|
+
for l in self.loop_crossing_graph.predecessors(right_loop)
|
|
96
|
+
if self.get_crossing(l, right_loop) is not Crossing_Direction.No_Cross
|
|
97
|
+
]
|
|
90
98
|
|
|
91
99
|
def get_crossing(self, left_loop: Loop, right_loop: Loop) -> Crossing_Direction:
|
|
92
100
|
"""Get the crossing direction between two loops, creating a no-cross edge if none exists.
|
|
@@ -102,4 +110,7 @@ class Loop_Braid_Graph:
|
|
|
102
110
|
"""
|
|
103
111
|
if not self.loop_crossing_graph.has_edge(left_loop, right_loop):
|
|
104
112
|
self.add_crossing(left_loop, right_loop, Crossing_Direction.No_Cross)
|
|
105
|
-
return cast(
|
|
113
|
+
return cast(
|
|
114
|
+
Crossing_Direction,
|
|
115
|
+
self.loop_crossing_graph[left_loop][right_loop][self._CROSSING],
|
|
116
|
+
)
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
This module defines the Wale class which represents a vertical column of stitches in a knitted structure, maintaining the sequence and relationships between loops in that column.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from __future__ import annotations
|
|
6
7
|
|
|
7
|
-
from
|
|
8
|
+
from collections.abc import Iterator
|
|
9
|
+
from typing import TYPE_CHECKING, cast
|
|
8
10
|
|
|
9
11
|
from networkx import DiGraph, dfs_preorder_nodes
|
|
10
12
|
|
|
@@ -26,6 +28,7 @@ class Wale:
|
|
|
26
28
|
last_loop (Loop | None): The last (top) loop in the wale sequence.
|
|
27
29
|
stitches (DiGraph): Stores the directed graph of stitch connections within this wale.
|
|
28
30
|
"""
|
|
31
|
+
|
|
29
32
|
_PULL_DIRECTION: str = "pull_direction"
|
|
30
33
|
|
|
31
34
|
def __init__(self, first_loop: Loop, knit_graph: Knit_Graph, end_loop: Loop | None = None) -> None:
|
|
@@ -60,7 +63,11 @@ class Wale:
|
|
|
60
63
|
Args:
|
|
61
64
|
loop (Loop): The loop to add to the end of the wale.
|
|
62
65
|
"""
|
|
63
|
-
self.stitches.add_edge(
|
|
66
|
+
self.stitches.add_edge(
|
|
67
|
+
self.last_loop,
|
|
68
|
+
loop,
|
|
69
|
+
pull_direction=self._knit_graph.get_pull_direction(self.last_loop, loop),
|
|
70
|
+
)
|
|
64
71
|
self.last_loop = loop
|
|
65
72
|
|
|
66
73
|
def get_stitch_pull_direction(self, u: Loop, v: Loop) -> Pull_Direction:
|
|
@@ -91,12 +98,14 @@ class Wale:
|
|
|
91
98
|
* The second wale (from split_loop to end). This will be None if the split_loop is not found.
|
|
92
99
|
"""
|
|
93
100
|
if split_loop in self:
|
|
94
|
-
return (
|
|
95
|
-
|
|
101
|
+
return (
|
|
102
|
+
Wale(self.first_loop, self._knit_graph, end_loop=split_loop),
|
|
103
|
+
Wale(split_loop, self._knit_graph, end_loop=self.last_loop),
|
|
104
|
+
)
|
|
96
105
|
else:
|
|
97
106
|
return self, None
|
|
98
107
|
|
|
99
|
-
def __eq__(self, other:
|
|
108
|
+
def __eq__(self, other: object) -> bool:
|
|
100
109
|
"""
|
|
101
110
|
Args:
|
|
102
111
|
other (Wale): The wale to compare.
|
|
@@ -104,9 +113,9 @@ class Wale:
|
|
|
104
113
|
Returns:
|
|
105
114
|
bool: True if all the loops in both wales are present and in the same order. False, otherwise.
|
|
106
115
|
"""
|
|
107
|
-
if len(self) != len(other):
|
|
116
|
+
if not isinstance(other, Wale) or len(self) != len(other):
|
|
108
117
|
return False
|
|
109
|
-
return not any(l != o for l, o in zip(self, other))
|
|
118
|
+
return not any(l != o for l, o in zip(self, other, strict=False))
|
|
110
119
|
|
|
111
120
|
def __len__(self) -> int:
|
|
112
121
|
"""Get the number of loops in this wale.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
This module provides the Wale_Braid class which represents complex cable knitting patterns as mathematical braid structures,
|
|
4
4
|
using concepts from algebraic topology to model how wales cross over and under each other.
|
|
5
5
|
"""
|
|
6
|
+
|
|
6
7
|
from knit_graphs.artin_wale_braids.Wale_Braid_Word import Wale_Braid_Word
|
|
7
8
|
from knit_graphs.artin_wale_braids.Wale_Group import Wale_Group
|
|
8
9
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This module provides the Wale_Braid_Word class which represents a single step in a braid operation, describing how loops cross over each other within a course of knitting.
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from __future__ import annotations
|
|
6
7
|
|
|
7
8
|
from knit_graphs.artin_wale_braids.Crossing_Direction import Crossing_Direction
|
|
@@ -59,7 +60,7 @@ class Wale_Braid_Word:
|
|
|
59
60
|
new_crossings = {i: ~c for i, c in self.crossings.items()}
|
|
60
61
|
return Wale_Braid_Word(new_loops, new_crossings)
|
|
61
62
|
|
|
62
|
-
def __eq__(self, other:
|
|
63
|
+
def __eq__(self, other: object) -> bool:
|
|
63
64
|
"""Check equality with another wale braid word.
|
|
64
65
|
|
|
65
66
|
Two braid words are equal if they have the same loops in the same order and the same crossing operations at the same indices.
|
|
@@ -70,13 +71,13 @@ class Wale_Braid_Word:
|
|
|
70
71
|
Returns:
|
|
71
72
|
bool: True if both braid words have identical loops, loop ordering, and crossing operations, False otherwise.
|
|
72
73
|
"""
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
return (
|
|
75
|
+
isinstance(other, Wale_Braid_Word)
|
|
76
|
+
and len(self) == len(other)
|
|
77
|
+
and all(l == o for l, o in zip(self.loops, other.loops, strict=False))
|
|
78
|
+
and all(i in other.crossings for i in self.crossings)
|
|
79
|
+
and all(other.crossings[i] == cd for i, cd in self.crossings.items())
|
|
80
|
+
)
|
|
80
81
|
|
|
81
82
|
def is_inversion(self, other: Wale_Braid_Word) -> bool:
|
|
82
83
|
"""Check if another braid word is the inverse of this braid word.
|
|
@@ -2,6 +2,7 @@
|
|
|
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
8
|
from typing import TYPE_CHECKING, cast
|
|
@@ -57,14 +58,16 @@ class Wale_Group:
|
|
|
57
58
|
for wale in full_wales:
|
|
58
59
|
u_loops: list[Loop] = cast(list[Loop], wale[:-1])
|
|
59
60
|
v_loops: list[Loop] = cast(list[Loop], wale[1:])
|
|
60
|
-
for u, v in zip(u_loops, v_loops):
|
|
61
|
+
for u, v in zip(u_loops, v_loops, strict=False):
|
|
61
62
|
self.stitch_graph.add_edge(u, v, pull_direction=self._knit_graph.get_pull_direction(u, v))
|
|
62
63
|
wales_to_split = full_wales
|
|
63
64
|
while len(wales_to_split) > 0:
|
|
64
65
|
wale_to_split = wales_to_split.pop()
|
|
65
66
|
split = False
|
|
66
67
|
upper_loops = cast(list[Loop], wale_to_split[1:])
|
|
67
|
-
for
|
|
68
|
+
for (
|
|
69
|
+
loop
|
|
70
|
+
) in upper_loops: # skip first loop in each wale as it may be already connected to a discovered decrease.
|
|
68
71
|
if len(loop.parent_loops) > 1: # Focal of a decrease.
|
|
69
72
|
clean_wale, remaining_wale = wale_to_split.split_wale(loop)
|
|
70
73
|
if not self.wale_graph.has_node(clean_wale):
|
|
@@ -75,7 +78,7 @@ class Wale_Group:
|
|
|
75
78
|
break
|
|
76
79
|
if not split:
|
|
77
80
|
self._add_wale(wale_to_split)
|
|
78
|
-
for
|
|
81
|
+
for _bot_loop, lower_wale in self.bottom_loops.items():
|
|
79
82
|
if lower_wale.last_loop in self.bottom_loops:
|
|
80
83
|
self.wale_graph.add_edge(lower_wale, self.bottom_loops[lower_wale.last_loop])
|
|
81
84
|
|
|
@@ -111,7 +114,7 @@ class Wale_Group:
|
|
|
111
114
|
int: The height of the wale group from the base loops to the tallest terminal, measured in total number of loops.
|
|
112
115
|
"""
|
|
113
116
|
max_len = 0
|
|
114
|
-
for
|
|
117
|
+
for _bot_loop, wale in self.bottom_loops.items():
|
|
115
118
|
path_len = sum(len(successor) for successor in dfs_preorder_nodes(self.wale_graph, wale))
|
|
116
119
|
max_len = max(max_len, path_len)
|
|
117
120
|
return max_len
|
|
@@ -131,7 +134,7 @@ class Wale_Group:
|
|
|
131
134
|
Returns:
|
|
132
135
|
bool: True if the given loop, loop_id (int), or wale is in this group.
|
|
133
136
|
"""
|
|
134
|
-
if isinstance(item, Loop
|
|
137
|
+
if isinstance(item, (Loop, int)):
|
|
135
138
|
return item in self.stitch_graph.nodes
|
|
136
139
|
else: # isinstance(item, Wale):
|
|
137
140
|
return item in self.wale_graph
|
|
@@ -3,6 +3,7 @@
|
|
|
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 knit_graphs.artin_wale_braids.Crossing_Direction import Crossing_Direction
|
|
7
8
|
from knit_graphs.Knit_Graph import Knit_Graph
|
|
8
9
|
from knit_graphs.Loop import Loop
|
|
@@ -69,15 +70,19 @@ def jersey_tube(tube_width: int, height: int) -> Knit_Graph:
|
|
|
69
70
|
"""Internal helper function to set up float connections between front and back of tube."""
|
|
70
71
|
front_loops = last_course[0:tube_width]
|
|
71
72
|
back_loops = last_course[tube_width:]
|
|
72
|
-
for first_front, second_front, back in zip(
|
|
73
|
+
for first_front, second_front, back in zip(
|
|
74
|
+
front_loops[0:-1], front_loops[1:], reversed(back_loops), strict=False
|
|
75
|
+
):
|
|
73
76
|
yarn.add_loop_behind_float(back, first_front, second_front)
|
|
74
|
-
for
|
|
77
|
+
for first_back, second_back, front in zip(
|
|
78
|
+
back_loops[0:-1], back_loops[1:], reversed(front_loops), strict=False
|
|
79
|
+
):
|
|
75
80
|
yarn.add_loop_in_front_of_float(front, first_back, second_back)
|
|
76
81
|
|
|
77
82
|
_set_tube_floats()
|
|
78
83
|
for _ in range(0, height):
|
|
79
84
|
next_course = [yarn.make_loop_on_end() for _p in last_course]
|
|
80
|
-
for parent_loop, child_loop in zip(last_course, next_course):
|
|
85
|
+
for parent_loop, child_loop in zip(last_course, next_course, strict=False):
|
|
81
86
|
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=Pull_Direction.BtF)
|
|
82
87
|
last_course = next_course
|
|
83
88
|
_set_tube_floats()
|
|
@@ -181,19 +186,44 @@ def lace_mesh(width: int, height: int) -> Knit_Graph:
|
|
|
181
186
|
for i, parent_loop in enumerate(reversed(last_course)):
|
|
182
187
|
child_loop = yarn.make_loop_on_end()
|
|
183
188
|
if i % 3 == 0: # Just knit every third stitch
|
|
184
|
-
knit_graph.connect_loops(
|
|
189
|
+
knit_graph.connect_loops(
|
|
190
|
+
parent_loop,
|
|
191
|
+
child_loop,
|
|
192
|
+
pull_direction=Pull_Direction.BtF,
|
|
193
|
+
stack_position=0,
|
|
194
|
+
)
|
|
185
195
|
elif i % 6 == 1: # Second of every 6 stitches (0 indexed) is yarn over before a decrease.
|
|
186
196
|
yo_parent = parent_loop
|
|
187
197
|
elif i % 6 == 2: # Third of every 6 stitches is bottom of decrease with prior yarn-over's parent
|
|
188
|
-
knit_graph.connect_loops(
|
|
198
|
+
knit_graph.connect_loops(
|
|
199
|
+
parent_loop,
|
|
200
|
+
child_loop,
|
|
201
|
+
pull_direction=Pull_Direction.BtF,
|
|
202
|
+
stack_position=0,
|
|
203
|
+
)
|
|
189
204
|
assert isinstance(yo_parent, Loop)
|
|
190
|
-
knit_graph.connect_loops(
|
|
205
|
+
knit_graph.connect_loops(
|
|
206
|
+
yo_parent,
|
|
207
|
+
child_loop,
|
|
208
|
+
pull_direction=Pull_Direction.BtF,
|
|
209
|
+
stack_position=1,
|
|
210
|
+
)
|
|
191
211
|
elif i % 6 == 4: # Fifth of every six stitches is bottom of decrease with next yarn-over's parent
|
|
192
|
-
knit_graph.connect_loops(
|
|
212
|
+
knit_graph.connect_loops(
|
|
213
|
+
parent_loop,
|
|
214
|
+
child_loop,
|
|
215
|
+
pull_direction=Pull_Direction.BtF,
|
|
216
|
+
stack_position=0,
|
|
217
|
+
)
|
|
193
218
|
prior_child = child_loop
|
|
194
219
|
elif i % 6 == 5: # The last of six stitches is the top of the prior decrease and new yarn-over
|
|
195
220
|
assert isinstance(prior_child, Loop)
|
|
196
|
-
knit_graph.connect_loops(
|
|
221
|
+
knit_graph.connect_loops(
|
|
222
|
+
parent_loop,
|
|
223
|
+
prior_child,
|
|
224
|
+
pull_direction=Pull_Direction.BtF,
|
|
225
|
+
stack_position=1,
|
|
226
|
+
)
|
|
197
227
|
next_course.append(child_loop)
|
|
198
228
|
last_course = next_course
|
|
199
229
|
# Make a basic jersey course
|
|
@@ -226,7 +256,12 @@ def twist_cable(width: int, height: int) -> Knit_Graph:
|
|
|
226
256
|
knit_graph, yarn = co_loops(width)
|
|
227
257
|
last_course = knit_graph.get_courses()[0]
|
|
228
258
|
next_course = []
|
|
229
|
-
pull_directions = [
|
|
259
|
+
pull_directions = [
|
|
260
|
+
Pull_Direction.FtB,
|
|
261
|
+
Pull_Direction.BtF,
|
|
262
|
+
Pull_Direction.BtF,
|
|
263
|
+
Pull_Direction.FtB,
|
|
264
|
+
]
|
|
230
265
|
for i, parent_loop in enumerate(reversed(last_course)):
|
|
231
266
|
child_loop = yarn.make_loop_on_end()
|
|
232
267
|
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=pull_directions[i % 4])
|
|
@@ -244,7 +279,7 @@ def twist_cable(width: int, height: int) -> Knit_Graph:
|
|
|
244
279
|
child_loop = next_course[i - 1]
|
|
245
280
|
knit_graph.connect_loops(parent_loop, child_loop, pull_direction=pull_directions[i % 4])
|
|
246
281
|
if r % 2 == 1: # cable row
|
|
247
|
-
for left_loop, right_loop in zip(next_course[1::4], next_course[2::4]):
|
|
282
|
+
for left_loop, right_loop in zip(next_course[1::4], next_course[2::4], strict=False):
|
|
248
283
|
knit_graph.add_crossing(left_loop, right_loop, crossing)
|
|
249
284
|
crossing = ~crossing
|
|
250
285
|
last_course = next_course
|
knit_graphs/py.typed
ADDED
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: knit-graphs
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.11
|
|
4
4
|
Summary: A graph representation of knitted structures where each loop is a node and edges represent yarn and stitch relationships.
|
|
5
5
|
Home-page: https://mhofmann-khoury.github.io/knit_graph/
|
|
6
6
|
License: MIT
|
|
@@ -20,8 +20,9 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
21
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
22
22
|
Classifier: Topic :: Scientific/Engineering
|
|
23
|
+
Classifier: Typing :: Typed
|
|
23
24
|
Requires-Dist: networkx (>=3.5)
|
|
24
|
-
Requires-Dist: plotly (>=6.3.0
|
|
25
|
+
Requires-Dist: plotly (>=6.3.0)
|
|
25
26
|
Project-URL: Documentation, https://mhofmann-khoury.github.io/knit_graph/
|
|
26
27
|
Project-URL: Repository, https://github.com/mhofmann-Khoury/knit_graph/
|
|
27
28
|
Description-Content-Type: text/markdown
|
|
@@ -17,25 +17,26 @@ docs/source/api/knit_graphs.artin_wale_braids.Wale_Group.rst,sha256=bAGHs3s8dW6l
|
|
|
17
17
|
docs/source/api/knit_graphs.artin_wale_braids.rst,sha256=ESKgE9gg830yJ6w5mKuv3MHgH3tMZ-Ee2y3b-bSnU4Y,547
|
|
18
18
|
docs/source/api/knit_graphs.basic_knit_graph_generators.rst,sha256=OgV2jkEMY0LfRq8v0cNhJUk3fbUOS9VcP8zRv4VBvC4,213
|
|
19
19
|
docs/source/api/knit_graphs.rst,sha256=w9HIhWI8P0_gG0H_efRUMHYBtWbgCprcS9moclgM_3I,499
|
|
20
|
-
docs/source/conf.py,sha256=
|
|
21
|
-
docs/source/index.rst,sha256=
|
|
20
|
+
docs/source/conf.py,sha256=qfKxtgms3gNDSoXGpOzWEDMzKJH20ovRMqTC57LkYF4,13282
|
|
21
|
+
docs/source/index.rst,sha256=E82Y_wpDU2hR8w6bSt2k6ZstslCe7u63Ld6ZFgT70RY,1284
|
|
22
22
|
docs/source/installation.rst,sha256=GyNRk_oXKVgOZ4KFLAgkXLwjHYzDYsx8gcokLRrS0ZI,1247
|
|
23
|
-
knit_graphs/Course.py,sha256=
|
|
24
|
-
knit_graphs/Knit_Graph.py,sha256=
|
|
25
|
-
knit_graphs/Knit_Graph_Visualizer.py,sha256=
|
|
26
|
-
knit_graphs/Loop.py,sha256=
|
|
27
|
-
knit_graphs/Pull_Direction.py,sha256=
|
|
28
|
-
knit_graphs/Yarn.py,sha256=
|
|
23
|
+
knit_graphs/Course.py,sha256=dcJvWtTYc66iiVpxtYzULDD2ttWuvuGnlahWpWs1wAY,6308
|
|
24
|
+
knit_graphs/Knit_Graph.py,sha256=ys4-oeu23_8yZ8yjun-QngeiErUK0l3F8lnNlg7cB70,12442
|
|
25
|
+
knit_graphs/Knit_Graph_Visualizer.py,sha256=R-iSEEq5_hDi3NLDjP0hVrArrynKUASHs7vA7MAccJg,42108
|
|
26
|
+
knit_graphs/Loop.py,sha256=B1YU6bjTsGYZ8QrBZN52vg1btf7jvzeviCAH-Exrmw8,9747
|
|
27
|
+
knit_graphs/Pull_Direction.py,sha256=3QW_TKEF3fb-Y7I8xDOHHTe6vCYK-ADi3_SDtqr5uSU,2336
|
|
28
|
+
knit_graphs/Yarn.py,sha256=RaU0_At-V6Yk0TGgrRbsKeWJsI4WMoHkZHzUfs7txAE,18391
|
|
29
29
|
knit_graphs/__init__.py,sha256=qzZAOxTqjgLkhoGnKNZwOkuYbKEyzfWKkKpKkV6lVfk,111
|
|
30
|
-
knit_graphs/artin_wale_braids/Crossing_Direction.py,sha256=
|
|
31
|
-
knit_graphs/artin_wale_braids/Loop_Braid_Graph.py,sha256=
|
|
32
|
-
knit_graphs/artin_wale_braids/Wale.py,sha256=
|
|
33
|
-
knit_graphs/artin_wale_braids/Wale_Braid.py,sha256=
|
|
34
|
-
knit_graphs/artin_wale_braids/Wale_Braid_Word.py,sha256=
|
|
35
|
-
knit_graphs/artin_wale_braids/Wale_Group.py,sha256=
|
|
30
|
+
knit_graphs/artin_wale_braids/Crossing_Direction.py,sha256=qQCxgsI5L_PMY16bX7_W_C0YG2SKTVcq05RO5eNcZDA,2822
|
|
31
|
+
knit_graphs/artin_wale_braids/Loop_Braid_Graph.py,sha256=A4KoqjBBw8mqvUyzXwCZcwSDDIePtUqgnVVKAWXTa-w,4997
|
|
32
|
+
knit_graphs/artin_wale_braids/Wale.py,sha256=G7Uci5wkE5y7gHGK2bbTpRyswGRSWhVXFxyIUYOprlo,7259
|
|
33
|
+
knit_graphs/artin_wale_braids/Wale_Braid.py,sha256=p2SsFQW6nQZTO89TtCnFSWTWkYAFDm6kykvhb9G7chg,2663
|
|
34
|
+
knit_graphs/artin_wale_braids/Wale_Braid_Word.py,sha256=rY1cB_PpAfz4vFGPh2qUaLf0yNDczk2l6pgxtYA6Sqg,4593
|
|
35
|
+
knit_graphs/artin_wale_braids/Wale_Group.py,sha256=Px-3yxKAUCeqI52IE6t6L2aSCFwgTTsVbN0bWdhQ518,6696
|
|
36
36
|
knit_graphs/artin_wale_braids/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
-
knit_graphs/basic_knit_graph_generators.py,sha256=
|
|
38
|
-
knit_graphs
|
|
39
|
-
knit_graphs-0.0.
|
|
40
|
-
knit_graphs-0.0.
|
|
41
|
-
knit_graphs-0.0.
|
|
37
|
+
knit_graphs/basic_knit_graph_generators.py,sha256=x1zHC2PYbzkmjE40xe5_3k2vDsT749L9iufUIfC2QUw,12353
|
|
38
|
+
knit_graphs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
+
knit_graphs-0.0.11.dist-info/LICENSE,sha256=Oazk3oiRu5ZN7b-EdYNYh0vu-I3Av2uIPQ-9L_cZ6Oo,1070
|
|
40
|
+
knit_graphs-0.0.11.dist-info/METADATA,sha256=I8Kkhsuu02YB0UX9W7Gzwzrq5Y9PrXmWvqo1j8JwUJA,5215
|
|
41
|
+
knit_graphs-0.0.11.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
42
|
+
knit_graphs-0.0.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|