Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
dd8edec
Modernize project for Python 3.9+ and COMPAS 2.x
jf--- Dec 9, 2025
811b7b0
Add type hints to core geometry and slicer modules
jf--- Dec 9, 2025
9c17f7a
f-strings, ruff fixes, COMPAS 2.x API compat, fix circular imports
jf--- Dec 9, 2025
88bc60f
fix COMPAS 2.x API: edge_faces, fix circular imports
jf--- Dec 9, 2025
c11b34b
COMPAS 2.x serialization: __data__ and __from_data__ API
jf--- Dec 9, 2025
d368f46
fix mypy errors: direct imports, type annotations, mypy config
jf--- Dec 9, 2025
67ba43d
refactor: replace dicts with dataclasses throughout codebase
jf--- Dec 9, 2025
e80aee7
unify deps: environment.yml only, prefer conda
jf--- Dec 9, 2025
d9c48b2
use compas_libigl for geodesics/massmatrix, keep igl for cotmatrix/gr…
jf--- Dec 9, 2025
76c2f6f
refactor: replace igl with compas_libigl, drop libigl dep
jf--- Dec 9, 2025
fe53a41
refactor: replace os.path with pathlib.Path
jf--- Dec 9, 2025
c6fb9e6
add typed config module, type hints to slicers and print organizers
jf--- Dec 9, 2025
b004095
type hints for parameters module, add min/max layer height defaults
jf--- Dec 9, 2025
c0cb5af
type hints utils.py, Path return for get_output_directory
jf--- Dec 9, 2025
22ca36d
type hints post_processing, slice_utilities, planar_slicing
jf--- Dec 9, 2025
6996247
type hints pre_processing main modules, update save_to_json sig
jf--- Dec 9, 2025
89a081e
type hints preprocessing_utils, print_organization_utilities
jf--- Dec 9, 2025
acfd2c0
add examples to test suite, add compas_cgal dep, fix compas 2.x compat
jf--- Dec 9, 2025
1974d01
perf: numpy vectorization + KDTree for hot loops
jf--- Dec 9, 2025
448941f
fix up_vector serialization after smoothing
jf--- Dec 9, 2025
34577cd
unify rdp + add batch closest point, CGAL fallback
jf--- Dec 9, 2025
28ea19c
perf: geodesic caching + vectorized contour finding
jf--- Dec 9, 2025
be25b65
add CGAL features: polygon offset, holes, remesh
jf--- Dec 9, 2025
9ce4f8f
vectorize assign_interpolation_distance, 11s->9.7s
jf--- Dec 9, 2025
bacf624
simplify calculate_z_bounds
jf--- Dec 9, 2025
bcf4a31
switch geodesics default to heat_igl: 22s->3.4s (85%)
jf--- Dec 9, 2025
bb2fbb9
add CGAL heat geodesics method option
jf--- Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
[bumpversion]
current_version = 0.7.0
current_version = 0.8.0
message = Bump version to {new_version}
commit = True
tag = True

[bumpversion:file:setup.py]
search = version="{current_version}"
replace = version="{new_version}"
[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"

[bumpversion:file:docs/conf.py]
search = version = release = '{current_version}'
replace = version = release = '{new_version}'
search = version = release = "{current_version}"
replace = version = release = "{new_version}"

[bumpversion:file:docs/doc_versions.txt]
search = {current_version}
replace = {new_version}
{current_version}

[bumpversion:file:src/compas_slicer/__init__.py]
search = __version__ = '{current_version}'
replace = __version__ = '{new_version}'
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"

[bumpversion:file:CHANGELOG.rst]
search = Unreleased
Expand Down
44 changes: 25 additions & 19 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
name: build

on:
# [push]
push:
branches:
- master
Expand All @@ -10,33 +9,40 @@ on:
- master

jobs:
build-packages:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest]
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v2
- name: Setup miniconda with python ${{ matrix.python-version }}
uses: conda-incubator/setup-miniconda@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
activate-environment: compas_slicer
environment-file: environment.yml
python-version: 3.8
auto-activate-base: false
auto-update-conda: true
- name: Conda info
run: conda info
- name: Install project
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --no-cache-dir -r requirements-dev.txt
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Test import
run: |
python -c "import compas_slicer; print('COMPAS Slicer version: ' + compas_slicer.__version__)"
- name: Lint with flake8
python -c "import compas_slicer; print('COMPAS Slicer version: ' + compas_slicer.__version__)"

- name: Lint with ruff
run: |
invoke lint
ruff check src/

- name: Type check with mypy
run: |
mypy src/compas_slicer --ignore-missing-imports
continue-on-error: true

- name: Test with pytest
run: |
invoke test
pytest tests/ -v
27 changes: 0 additions & 27 deletions MANIFEST.in

This file was deleted.

46 changes: 22 additions & 24 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import os
import sphinx_compas_theme

import sphinx_compas_theme
from sphinx.ext.napoleon.docstring import NumpyDocstring

extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.coverage',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.extlinks',
'sphinx.ext.ifconfig',
'sphinx.ext.napoleon',
'sphinx.ext.todo',
'sphinx.ext.viewcode',
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"sphinx.ext.coverage",
"sphinx.ext.doctest",
"sphinx.ext.intersphinx",
"sphinx.ext.extlinks",
"sphinx.ext.ifconfig",
"sphinx.ext.napoleon",
"sphinx.ext.todo",
"sphinx.ext.viewcode",
]
if os.getenv('SPELLCHECK'):
extensions += 'sphinxcontrib.spelling',
if os.getenv("SPELLCHECK"):
extensions += ("sphinxcontrib.spelling",)
spelling_show_suggestions = True
spelling_lang = 'en_US'

source_suffix = '.rst'
master_doc = 'index'
project = 'COMPAS SLICER'
year = '2020'
author = 'Digital Building Technologies, Gramazio Kohler Research'
copyright = '{0}, {1}'.format(year, author)
version = release = '0.7.0'
spelling_lang = "en_US"

source_suffix = ".rst"
master_doc = "index"
project = "COMPAS SLICER"
year = "2020-2025"
author = "Digital Building Technologies, Gramazio Kohler Research"
copyright = f"{year}, {author}"
version = release = "0.8.0"

pygments_style = 'sphinx'
show_authors = True
Expand Down
32 changes: 25 additions & 7 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,29 @@ name: compas_slicer
channels:
- conda-forge
dependencies:
- python
- python>=3.9
- pip
- compas=1.16.0
- networkx
- numpy
- progressbar2=3.53
- pyclipper=1.2.0
- rdp=0.8
# core
- attrs>=21.0
- compas>=2.0
- compas_libigl>=0.8
- networkx>=3.0
- numpy>=1.24
- progressbar2>=4.0
- pyclipper>=1.3
- rdp>=0.8
# dev
- invoke>=2.0
- pytest>=7.0
- pytest-cov
- ruff
- mypy
- sphinx>=6.0
- sphinx_compas_theme>=0.24
- nbsphinx
- ipykernel
- ipython>=8.0
- twine
- pip:
- bump2version>=1.0
- -e .
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from compas_slicer.slicers import PlanarSlicer
from compas_slicer.post_processing import generate_brim
from compas_slicer.post_processing import generate_raft
from compas_slicer.post_processing import simplify_paths_rdp_igl
from compas_slicer.post_processing import simplify_paths_rdp
from compas_slicer.post_processing import seams_smooth
from compas_slicer.post_processing import seams_align
from compas_slicer.print_organization import PlanarPrintOrganizer
Expand Down Expand Up @@ -74,7 +74,7 @@ def main():
# Simplify the paths by removing points with a certain threshold
# change the threshold value to remove more or less points
# ==========================================================================
simplify_paths_rdp_igl(slicer, threshold=0.6)
simplify_paths_rdp(slicer, threshold=0.6)

# ==========================================================================
# Smooth the seams between layers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from compas_slicer.pre_processing import move_mesh_to_point
from compas_slicer.slicers import PlanarSlicer
from compas_slicer.post_processing import generate_brim
from compas_slicer.post_processing import simplify_paths_rdp_igl
from compas_slicer.post_processing import simplify_paths_rdp
from compas_slicer.post_processing import sort_into_vertical_layers
from compas_slicer.post_processing import reorder_vertical_layers
from compas_slicer.post_processing import seams_smooth
Expand Down Expand Up @@ -46,7 +46,7 @@ def main():

# Post-processing
generate_brim(slicer, layer_width=3.0, number_of_brim_offsets=5)
simplify_paths_rdp_igl(slicer, threshold=0.7)
simplify_paths_rdp(slicer, threshold=0.7)
seams_smooth(slicer, smooth_distance=10)
slicer.printout_info()
save_to_json(slicer.to_data(), OUTPUT_DIR, 'slicer_data.json')
Expand Down
4 changes: 2 additions & 2 deletions examples/4_gcode_generation/example_4_gcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from compas_slicer.pre_processing import move_mesh_to_point
from compas_slicer.slicers import PlanarSlicer
from compas_slicer.post_processing import generate_brim
from compas_slicer.post_processing import simplify_paths_rdp_igl
from compas_slicer.post_processing import simplify_paths_rdp
from compas_slicer.post_processing import seams_smooth
from compas_slicer.print_organization import PlanarPrintOrganizer
from compas_slicer.print_organization import set_extruder_toggle
Expand Down Expand Up @@ -37,7 +37,7 @@ def main():
slicer = PlanarSlicer(compas_mesh, slicer_type="cgal", layer_height=4.5)
slicer.slice_model()
generate_brim(slicer, layer_width=3.0, number_of_brim_offsets=4)
simplify_paths_rdp_igl(slicer, threshold=0.6)
simplify_paths_rdp(slicer, threshold=0.6)
seams_smooth(slicer, smooth_distance=10)
slicer.printout_info()
save_to_json(slicer.to_data(), OUTPUT_DIR, 'slicer_data.json')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import logging
from compas.geometry import distance_point_point
from pathlib import Path

from compas.datastructures import Mesh
import os
from compas.geometry import distance_point_point

import compas_slicer.utilities as slicer_utils
from compas_slicer.post_processing import simplify_paths_rdp_igl
from compas_slicer.slicers import ScalarFieldSlicer
import compas_slicer.utilities as utils
from compas_slicer.post_processing import simplify_paths_rdp
from compas_slicer.print_organization import ScalarFieldPrintOrganizer
from compas_slicer.slicers import ScalarFieldSlicer

logger = logging.getLogger('logger')
logging.basicConfig(format='%(levelname)s-%(message)s', level=logging.INFO)

DATA_PATH = os.path.join(os.path.dirname(__file__), 'data')
DATA_PATH = Path(__file__).parent / 'data'
OUTPUT_PATH = slicer_utils.get_output_directory(DATA_PATH)
MODEL = 'geom_to_slice.obj'
BASE = 'custom_base.obj'

if __name__ == '__main__':

def main():
# --- load meshes
mesh = Mesh.from_obj(os.path.join(DATA_PATH, MODEL))
base = Mesh.from_obj(os.path.join(DATA_PATH, BASE))
mesh = Mesh.from_obj(DATA_PATH / MODEL)
base = Mesh.from_obj(DATA_PATH / BASE)

# --- Create per-vertex scalar field (distance of every vertex from the custom base)
pts = [mesh.vertex_coordinates(v_key, axes='xyz') for v_key in
Expand All @@ -42,10 +44,14 @@
slicer_utils.save_to_json(slicer.to_data(), OUTPUT_PATH, 'isocontours.json') # save results to json

# --- Print organization calculations (i.e. generation of printpoints with fabrication-related information)
simplify_paths_rdp_igl(slicer, threshold=0.3)
simplify_paths_rdp(slicer, threshold=0.3)
print_organizer = ScalarFieldPrintOrganizer(slicer, parameters={}, DATA_PATH=DATA_PATH)
print_organizer.create_printpoints()

print_organizer.printout_info()
printpoints_data = print_organizer.output_printpoints_dict()
utils.save_to_json(printpoints_data, OUTPUT_PATH, 'out_printpoints.json') # save results to json


if __name__ == '__main__':
main()
29 changes: 18 additions & 11 deletions examples/6_attributes_transfer/example_6_attributes_transfer.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import logging
import os
from compas.geometry import Point, Vector, distance_point_plane, normalize_vector
from pathlib import Path

import numpy as np
from compas.datastructures import Mesh
from compas.geometry import Point, Vector, distance_point_plane, normalize_vector

import compas_slicer.utilities as slicer_utils
from compas_slicer.post_processing import simplify_paths_rdp_igl
from compas_slicer.slicers import PlanarSlicer
import compas_slicer.utilities.utils as utils
from compas_slicer.utilities.attributes_transfer import transfer_mesh_attributes_to_printpoints
from compas_slicer.post_processing import simplify_paths_rdp
from compas_slicer.print_organization import PlanarPrintOrganizer
import numpy as np
from compas_slicer.slicers import PlanarSlicer
from compas_slicer.utilities.attributes_transfer import transfer_mesh_attributes_to_printpoints

logger = logging.getLogger('logger')
logging.basicConfig(format='%(levelname)s-%(message)s', level=logging.INFO)

DATA_PATH = os.path.join(os.path.dirname(__file__), 'data')
DATA_PATH = Path(__file__).parent / 'data'
OUTPUT_PATH = slicer_utils.get_output_directory(DATA_PATH)
MODEL = 'distorted_v_closed_low_res.obj'

if __name__ == '__main__':

def main():
# load mesh
mesh = Mesh.from_obj(os.path.join(DATA_PATH, MODEL))
mesh = Mesh.from_obj(DATA_PATH / MODEL)

# --------------- Add attributes to mesh
# Face attributes can be anything (ex. float, bool, array, text ...)
Expand Down Expand Up @@ -55,15 +58,15 @@
# --------------- Slice mesh
slicer = PlanarSlicer(mesh, slicer_type="default", layer_height=5.0)
slicer.slice_model()
simplify_paths_rdp_igl(slicer, threshold=1.0)
simplify_paths_rdp(slicer, threshold=1.0)
slicer_utils.save_to_json(slicer.to_data(), OUTPUT_PATH, 'slicer_data.json')

# --------------- Create printpoints
print_organizer = PlanarPrintOrganizer(slicer)
print_organizer.create_printpoints()

# --------------- Transfer mesh attributes to printpoints
transfer_mesh_attributes_to_printpoints(mesh, print_organizer.printpoints_dict)
transfer_mesh_attributes_to_printpoints(mesh, print_organizer.printpoints)

# --------------- Save printpoints to json (only json-serializable attributes are saved)
printpoints_data = print_organizer.output_printpoints_dict()
Expand All @@ -82,3 +85,7 @@
utils.save_to_json(positive_y_axis_list, OUTPUT_PATH, 'positive_y_axis_list.json')
utils.save_to_json(dist_from_plane_list, OUTPUT_PATH, 'dist_from_plane_list.json')
utils.save_to_json(utils.point_list_to_dict(direction_to_pt_list), OUTPUT_PATH, 'direction_to_pt_list.json')


if __name__ == '__main__':
main()
Loading
Loading