diff --git a/preprocess_cancellation/__init__.py b/preprocess_cancellation/__init__.py index da322d5..f190151 100644 --- a/preprocess_cancellation/__init__.py +++ b/preprocess_cancellation/__init__.py @@ -11,21 +11,28 @@ * GCode with Marlin M486 tags """ +from __future__ import annotations + import io import logging import os import pathlib import shutil import tempfile -from typing import Any, Callable, Generator, Optional, TypeVar +from typing import TYPE_CHECKING from .layers import LayerFilter -from .slicers import Preprocessor, identify_slicer_marker +from .slicers import identify_slicer_marker -logger = logging.getLogger(__name__) +if TYPE_CHECKING: + from typing import TYPE_CHECKING, Any, Callable, Generator, Optional, TypeVar + + from .slicers import Preprocessor + PathLike = TypeVar("PathLike", str, pathlib.Path) -PathLike = TypeVar("PathLike", str, pathlib.Path) + +logger = logging.getLogger(__name__) def preprocess_pipe(infile: io.TextIOBase, **_kw: Any) -> Generator[str, None, None]: diff --git a/preprocess_cancellation/slicers/__init__.py b/preprocess_cancellation/slicers/__init__.py index 9df60da..79ece01 100644 --- a/preprocess_cancellation/slicers/__init__.py +++ b/preprocess_cancellation/slicers/__init__.py @@ -2,9 +2,7 @@ import io import logging -from typing import Callable, Dict, Generator, Optional, Tuple - -from mypy_extensions import Arg, DefaultNamedArg, NamedArg +from typing import TYPE_CHECKING from ..layers import LayerFilter from .cura import preprocess_cura_to_klipper @@ -12,16 +10,22 @@ from .m486 import preprocess_m486_to_klipper from .slic3r import preprocess_slicer_to_klipper -logger = logging.getLogger(__name__) +if TYPE_CHECKING: + from typing import Callable, Dict, Generator, Optional, Tuple + + from mypy_extensions import Arg, DefaultNamedArg, NamedArg -Preprocessor = Callable[ - [ - Arg(io.TextIOBase, "infile"), - DefaultNamedArg(bool, "use_shapely"), - NamedArg(LayerFilter, "layer_filter"), - ], - Generator[str, None, None], -] + Preprocessor = Callable[ + [ + Arg(io.TextIOBase, "infile"), + DefaultNamedArg(bool, "use_shapely"), + NamedArg(LayerFilter, "layer_filter"), + ], + Generator[str, None, None], + ] + + +logger = logging.getLogger(__name__) # Note: diff --git a/preprocess_cancellation/slicers/cura.py b/preprocess_cancellation/slicers/cura.py index 4f2781e..edd09b1 100644 --- a/preprocess_cancellation/slicers/cura.py +++ b/preprocess_cancellation/slicers/cura.py @@ -53,12 +53,15 @@ def preprocess_cura_to_klipper( infile.seek(0) for line in infile: + if line.strip() and not line.startswith(";"): + yield from exclude_object_header(known_objects.values()) + yield line + if line.strip() and not line.startswith(";"): break # Inject custom marker - yield from exclude_object_header(known_objects.values()) current_object = None for line in infile: diff --git a/preprocess_cancellation/slicers/ideamaker.py b/preprocess_cancellation/slicers/ideamaker.py index a11e8c3..e0736fb 100644 --- a/preprocess_cancellation/slicers/ideamaker.py +++ b/preprocess_cancellation/slicers/ideamaker.py @@ -60,13 +60,15 @@ def preprocess_ideamaker_to_klipper( current_object = None for line in infile: + if line.strip() and not line.startswith(";"): + yield from exclude_object_header(known_objects.values()) + yield line - if line.startswith(";TOTAL_NUM:"): - total_num = int(line.split(":")[1].strip()) - assert total_num == len(known_objects) - yield from exclude_object_header(known_objects.values()) + if line.strip() and not line.startswith(";"): + break + for line in infile: if line.startswith(";PRINTING_ID:"): printing_id = line.split(":")[1].strip() if current_object: diff --git a/preprocess_cancellation/slicers/m486.py b/preprocess_cancellation/slicers/m486.py index dad823e..3827f7d 100644 --- a/preprocess_cancellation/slicers/m486.py +++ b/preprocess_cancellation/slicers/m486.py @@ -50,16 +50,21 @@ def preprocess_m486_to_klipper( infile.seek(0) current_object = None + for line in infile: + if line.strip() and not line.startswith(";"): + yield from exclude_object_header( + [known_object for known_object in known_objects.values() if known_object.name != "-1"] + ) + + yield line + + if line.strip() and not line.startswith(";"): + break + for line in infile: if line.upper().startswith("M486"): _, params = parse_gcode(line) - if "T" in params: - # Inject custom marker - yield from exclude_object_header( - [known_object for known_object in known_objects.values() if known_object.name != "-1"] - ) - if "S" in params: if current_object: yield from exclude_object_end(current_object.name) diff --git a/preprocess_cancellation/slicers/slic3r.py b/preprocess_cancellation/slicers/slic3r.py index 94fce8f..52528c1 100644 --- a/preprocess_cancellation/slicers/slic3r.py +++ b/preprocess_cancellation/slicers/slic3r.py @@ -48,12 +48,14 @@ def preprocess_slicer_to_klipper( infile.seek(0) for line in infile: + if line.strip() and not line.startswith(";"): + yield from exclude_object_header(known_objects.values()) + yield line + if line.strip() and not line.startswith(";"): break - yield from exclude_object_header(known_objects.values()) - for line in infile: yield line diff --git a/pyproject.toml b/pyproject.toml index f2e22f1..c57a45a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "preprocess_cancellation" -version = "0.3.a1" +version = "0.3.a2" description = "GCode processor to add klipper exclude-object markers" readme = "README.md" authors = ["Franklyn Tackitt "] diff --git a/tests/test_hulls.py b/tests/test_hulls.py index d26b44e..aa3a88e 100644 --- a/tests/test_hulls.py +++ b/tests/test_hulls.py @@ -1,33 +1,9 @@ import math -from preprocess_cancellation.hulls import ShapelyHullTracker, SimpleHullTracker +from preprocess_cancellation.hulls import SimpleHullTracker from preprocess_cancellation.types import Point -def test_shapely_hulls_simple(): - hull_tracker = ShapelyHullTracker() - - hull_tracker.add_point(Point(0.0, 0.0)) - hull_tracker.add_point(Point(0.0, 1.0)) - hull_tracker.add_point(Point(1.0, 1.0)) - hull_tracker.add_point(Point(1.0, 0.0)) - - assert hull_tracker.exterior() == [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)] - assert hull_tracker.center() == (0.5, 0.5) - - -def test_shapely_hulls_rhombus(): - hull_tracker = ShapelyHullTracker() - - hull_tracker.add_point(Point(0.0, 5.0)) - hull_tracker.add_point(Point(5.0, 10.0)) - hull_tracker.add_point(Point(10.0, 5.0)) - hull_tracker.add_point(Point(5.0, 0.0)) - - assert hull_tracker.exterior() == [(5.0, 0.0), (0.0, 5.0), (5.0, 10.0), (10.0, 5.0), (5.0, 0.0)] - assert hull_tracker.center() == (5.0, 5.0) - - def test_plain_hulls_simple(): hull_tracker = SimpleHullTracker() hull_tracker.add_point(Point(0.0, 0.0)) @@ -65,21 +41,3 @@ def test_plain_hulls_circle(): assert hull_tracker.exterior() == [(0.0, 0.0), (0.0, 10.0), (10.0, 10.0), (10.0, 0.0)] assert hull_tracker.center() == (5.0, 5.0) - - -def test_shapely_hulls_circle(): - hull_tracker = ShapelyHullTracker() - center = Point(5.0, 5.0) - - for i in range(0, 360, 1): - hull_tracker.add_point( - Point( - center.x + 5 * math.cos(math.radians(i)), - center.y + 5 * math.sin(math.radians(i)), - ) - ) - - # Yeah, its approxamitely a circle? All points are within 0.1mm of the expected circle - for x, y in hull_tracker.exterior(): - assert 4.9 <= math.sqrt((5 - x) ** 2 + (5 - y) ** 2) <= 5.1 - assert hull_tracker.center() == (5.0, 5.0) diff --git a/tests/test_hulls_shapely.py b/tests/test_hulls_shapely.py new file mode 100644 index 0000000..d46a1eb --- /dev/null +++ b/tests/test_hulls_shapely.py @@ -0,0 +1,55 @@ +import math + +import pytest + +from preprocess_cancellation.hulls import ShapelyHullTracker +from preprocess_cancellation.types import Point + +try: + import shapely.geometry # pylint: disable=unused-import +except ImportError: + pytest.skip("Requires shapely installed", allow_module_level=True) +except OSError: + pytest.skip("Requires libgeos installed", allow_module_level=True) + + +def test_shapely_hulls_simple(): + hull_tracker = ShapelyHullTracker() + + hull_tracker.add_point(Point(0.0, 0.0)) + hull_tracker.add_point(Point(0.0, 1.0)) + hull_tracker.add_point(Point(1.0, 1.0)) + hull_tracker.add_point(Point(1.0, 0.0)) + + assert hull_tracker.exterior() == [(0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)] + assert hull_tracker.center() == (0.5, 0.5) + + +def test_shapely_hulls_rhombus(): + hull_tracker = ShapelyHullTracker() + + hull_tracker.add_point(Point(0.0, 5.0)) + hull_tracker.add_point(Point(5.0, 10.0)) + hull_tracker.add_point(Point(10.0, 5.0)) + hull_tracker.add_point(Point(5.0, 0.0)) + + assert hull_tracker.exterior() == [(5.0, 0.0), (0.0, 5.0), (5.0, 10.0), (10.0, 5.0), (5.0, 0.0)] + assert hull_tracker.center() == (5.0, 5.0) + + +def test_shapely_hulls_circle(): + hull_tracker = ShapelyHullTracker() + center = Point(5.0, 5.0) + + for i in range(0, 360, 1): + hull_tracker.add_point( + Point( + center.x + 5 * math.cos(math.radians(i)), + center.y + 5 * math.sin(math.radians(i)), + ) + ) + + # Yeah, its approxamitely a circle? All points are within 0.1mm of the expected circle + for x, y in hull_tracker.exterior(): + assert 4.9 <= math.sqrt((5 - x) ** 2 + (5 - y) ** 2) <= 5.1 + assert hull_tracker.center() == (5.0, 5.0) diff --git a/tests/test_preprocessor_with_shapely.py b/tests/test_preprocessor_with_shapely.py index e0b9013..62eb8f0 100644 --- a/tests/test_preprocessor_with_shapely.py +++ b/tests/test_preprocessor_with_shapely.py @@ -15,9 +15,11 @@ ) try: - import shapely # pylint: disable=unused-import -except ImportError: + import shapely.geometry # pylint: disable=unused-import +except (OSError, ImportError): pytest.skip("Requires shapely installed", allow_module_level=True) +except OSError: + pytest.skip("Requires libgeos installed", allow_module_level=True) gcode_path = pathlib.Path("./GCode")