"""Module containing structure that define course-wise boundary instructions of swatch programs."""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from typing import TYPE_CHECKING
from knitout_interpreter.knitout_operations.needle_instructions import Xfer_Instruction
from virtual_knitting_machine.machine_components.carriage_system.Carriage_Pass_Direction import (
Carriage_Pass_Direction,
)
from quilt_knit.swatch.swatch_boundary_instruction import Swatch_Boundary_Instruction
from quilt_knit.swatch.Swatch_Side import Swatch_Side
if TYPE_CHECKING:
from knitout_interpreter.knitout_operations.needle_instructions import (
Needle_Instruction,
)
[docs]
class Course_Side(Swatch_Side, Enum):
"""Enumeration of the side of a swatch an instruction exists on. Used to differentiate between entrance-exit seam directions."""
Left = "Left" # Indicates that an instruction is on the left side of the swatch
Right = "Right" # Indicates that an instruction is on the right side of the swatch
[docs]
@staticmethod
def entrance_by_direction(direction: Carriage_Pass_Direction) -> Course_Side:
"""
Args:
direction (Carriage_Pass_Direction): The direction of a carriage pass to find the entrance side of a course.
Returns:
Course_Side: The side of the course that would be entered by the given carriage pass direction
"""
if direction is Carriage_Pass_Direction.Leftward:
return Course_Side.Right
else:
return Course_Side.Left
[docs]
@staticmethod
def exit_by_direction(direction: Carriage_Pass_Direction) -> Course_Side:
"""
Args:
direction (Carriage_Pass_Direction): The direction of a carriage pass to find the exit side of a course.
Returns:
Course_Side: The side of the course that would be exited by the given carriage pass direction
"""
if direction is Carriage_Pass_Direction.Leftward:
return Course_Side.Left
else:
return Course_Side.Right
[docs]
def __str__(self) -> str:
"""
Returns:
(str): The name of this course side.
"""
return self.name
[docs]
def __repr__(self) -> str:
"""
Returns:
(str): The name of this course side.
"""
return str(self)
@property
def opposite(self) -> Course_Side:
"""
Returns:
Course_Side: The opposite of this course side.
"""
if self is Course_Side.Left:
return Course_Side.Right
else:
return Course_Side.Left
[docs]
def __invert__(self) -> Course_Side:
"""
Returns:
Course_Side: The opposite of this course side.
"""
return self.opposite
[docs]
def __neg__(self) -> Course_Side:
"""
Returns:
Course_Side: The opposite of this course side.
"""
return self.opposite
[docs]
class Course_Boundary_Type(Enum):
"""Enumeration of the course-wise boundary entrance/exit types."""
exit_boundary = "exit" # Implies that this boundary can exit the carriage pass.
entrance = "entrance" # Implies that this boundary can enter the carriage pass.
entrance_exit = "entrance-exit" # Implies that this boundary can enter or exit the carriage pass.
blocked = "blocked" # Implies that this boundary is neither an exit nor entrance to the carriage pass.
[docs]
def is_exit(self) -> bool:
"""
Returns:
True if the boundary is an exit. False, otherwise.
"""
return self in {Course_Boundary_Type.exit_boundary, Course_Boundary_Type.entrance_exit}
[docs]
def is_entrance(self) -> bool:
"""
Returns:
True if the boundary is an entrance. False, otherwise.
"""
return self in {Course_Boundary_Type.entrance, Course_Boundary_Type.entrance_exit}
[docs]
def __str__(self) -> str:
"""
Returns:
(str): The name of this boundary type.
"""
return self.name
[docs]
def __repr__(self) -> str:
"""
Returns:
(str): The name of this boundary type.
"""
return str(self)
[docs]
def __hash__(self) -> int:
"""
Returns:
int: The hash value of the name of this boundary type
"""
return hash(self.name)
@property
def opposite(self) -> Course_Boundary_Type:
"""
Returns:
Course_Boundary_Type: The opposite of this boundary type. Entrance-Exits and blocked boundaries remain unchanged.
"""
if self is Course_Boundary_Type.exit_boundary:
return Course_Boundary_Type.entrance
elif self is Course_Boundary_Type.entrance:
return Course_Boundary_Type.exit_boundary
else: # Entrance Exits and Blocked boundaries
return self
[docs]
def __invert__(self) -> Course_Boundary_Type:
"""
Returns:
Course_Boundary_Type: The opposite of this boundary type.
"""
return self.opposite
[docs]
def __neg__(self) -> Course_Boundary_Type:
"""
Returns:
Course_Boundary_Type: The opposite of this boundary type.
"""
return self.opposite
[docs]
@dataclass(unsafe_hash=True)
class Course_Boundary_Instruction(Swatch_Boundary_Instruction):
""" A class to represent instructions on the course-wise boundary of a swatch program."""
left_boundary_type: Course_Boundary_Type # The boundary type from the left side of the swatch.
right_boundary_type: Course_Boundary_Type # The boundary type from the right side of the swatch.
carriage_pass_rack: int # The racking alignment of the carriage pass of this instruction
carriage_pass_is_all_needle: bool # True if the carriage pass is racked for all-needle knitting
carriage_pass_index: int # The index of the carriage pass in the swatch program that formed this boundary instruction.
@property
def is_left(self) -> bool:
"""
Returns:
bool: True if the boundary instruction can enter or exit the left side of its carriage pass.
"""
return self.left_boundary_type is not Course_Boundary_Type.blocked
@property
def is_right(self) -> bool:
"""
Returns:
bool: True if the boundary instruction can enter or exit the right side of its carriage pass.
"""
return self.right_boundary_type is not Course_Boundary_Type.blocked
@property
def is_left_exit(self) -> bool:
"""
Returns:
bool: True if the boundary instruction can exit the left side of its carriage pass.
"""
return self.left_boundary_type.is_exit()
@property
def is_right_exit(self) -> bool:
"""
Returns:
bool: True if the boundary instruction can exit the right side of its carriage pass.
"""
return self.right_boundary_type.is_exit()
@property
def is_left_entrance(self) -> bool:
"""
Returns:
bool: True if the boundary instruction can enter the left side of its carriage pass.
"""
return self.left_boundary_type.is_entrance()
@property
def is_right_entrance(self) -> bool:
"""
Returns:
bool: True if the boundary instruction can enter the right side of its carriage pass.
"""
return self.right_boundary_type.is_entrance()
[docs]
def has_potential_left_to_right_connection(self, right_boundary_instruction: Course_Boundary_Instruction) -> bool:
"""
Args:
right_boundary_instruction (Course_Boundary_Instruction): The boundary instruction to find potential connection to, presuming it is on the right side of the boundary.
Returns:
bool: True if the boundaries are on opposite course sides, proceed in the same carriage pass direction, and are an entrance exit pair. False, otherwise.
"""
if not self._matching_carriage_pass_types(right_boundary_instruction):
return False
if self.is_left_exit:
return right_boundary_instruction.is_right_entrance
elif self.is_left_entrance:
return right_boundary_instruction.is_right_exit
return False
def _matching_carriage_pass_types(self, other_boundary_instruction: Course_Boundary_Instruction) -> bool:
"""
Carriage passes can be connected if they are in the same direction, occur at the same racking, and if they are both loop-forming or xfer passes.
Args:
other_boundary_instruction (Course_Boundary_Instruction): The boundary instruction to check for possible connections to.
Returns:
bool: True if the two instructions are of similar enough types for a valid connection of their carriage passes.
"""
if self.direction != other_boundary_instruction.direction:
return False
elif isinstance(self.instruction, Xfer_Instruction) and not isinstance(other_boundary_instruction.instruction, Xfer_Instruction):
return False
return self.carriage_pass_rack == other_boundary_instruction.carriage_pass_rack and self.carriage_pass_is_all_needle == other_boundary_instruction.carriage_pass_is_all_needle
[docs]
def __str__(self) -> str:
"""
Returns:
str: A string expressing the entrance-exit direction and blocked status of this boundary instruction.
"""
left = "\\"
right = "\\"
if self.is_left_entrance:
if self.is_left_exit:
left = "<>"
else:
left = "->"
elif self.is_left_exit:
left = "<-"
if self.is_right_entrance:
if self.is_right_exit:
right = "<>"
else:
right = "<-"
elif self.is_right_exit:
left = "->"
i_str = str(self.instruction)[:-1]
return f"{left}{i_str}{right}"