Skip to content

Commit

Permalink
Merge pull request #35 from CadQuery/multi-file
Browse files Browse the repository at this point in the history
Added FreeCAD Support
  • Loading branch information
jmwright authored Nov 8, 2024
2 parents b009833 + 68fc5ad commit ce49645
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 6 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/test_freecad.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Test FreeCAD

on: [push, pull_request]

jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout project
uses: actions/checkout@v4

- name: Install and Test
run: |
conda create -y -n freecad -c conda-forge python=3.11 freecad=0.21.2
conda init bash
source /usr/share/miniconda/bin/activate
conda activate freecad
python -m pip install --upgrade pip
pip install -e .
pip install -e .[dev]
python -m pytest -v tests/test_freecad.py
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
pip3 install -e .[dev]
- name: Run tests
run: |
python3 -m pytest -v
python3 -m pytest -v --ignore=tests/test_freecad.py
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,6 @@ dmypy.json

# Pyre type checker
.pyre/

# FreeCAD related files
updated_part*
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ dependencies = [
"typish",
"casadi",
"path",
"cadquery-freecad-import-plugin @ git+https://github.com/jmwright/cadquery-freecad-import-plugin.git"
]

[project.scripts]
Expand Down
50 changes: 45 additions & 5 deletions src/cq_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,55 @@
from cq_cli.cqcodecs import loader


def handle_freecad_file(file_path, params=None):
"""
Wrapper method that takes care of importing a FreeCAD file and applying parameters to it.
"""
from cadquery_freecad_import_plugin.plugin import import_freecad_part

# Construct a build result so that the rest of the code can handle it
build_result = cq.cqgi.BuildResult()

# Only apply parameters if there are any
if params != None and len(params) > 0:
# Assemble the FreeCAD params
freecad_params = {}
for key in params:
freecad_params[key] = {"value": params[key], "units": "mm"}

# Import the FreeCAD file using the parametric method
result = import_freecad_part(file_path, freecad_params)
shape_result = cq.cqgi.ShapeResult()
shape_result.shape = result
build_result.results.append(shape_result)
build_result.success = True
else:
# Import the FreeCAD file without applying parameters
result = import_freecad_part(file_path)
shape_result = cq.cqgi.ShapeResult()
shape_result.shape = result
build_result.results.append(shape_result)
build_result.success = True

return build_result


def build_and_parse(script_str, params, errfile, expression):
"""
Uses CQGI to parse and build a script, substituting in parameters if any were supplied.
"""

# We need to do a broad try/catch to let the user know if something higher-level fails
try:
# Do the CQGI handling of the script here and, if successful, pass the build result to the codec
if expression != None:
script_str += "\nshow_object({expr})".format(expr=expression)
cqModel = cqgi.parse(script_str)
build_result = cqModel.build(params)
# If we have a freecad file, handle it differently
if script_str.lower().endswith(".fcstd"):
build_result = handle_freecad_file(script_str, params)
else:
# Do the CQGI handling of the script here and, if successful, pass the build result to the codec
if expression != None:
script_str += "\nshow_object({expr})".format(expr=expression)
cqModel = cqgi.parse(script_str)
build_result = cqModel.build(params)

# Handle the case of the build not being successful, otherwise pass the codec the build result
if not build_result.success:
Expand Down Expand Up @@ -81,6 +119,8 @@ def get_script_from_infile(infile, outfile, errfile):
if infile == None:
# Grab the string from stdin
script_str = sys.stdin.read()
elif infile.lower().endswith(".fcstd"):
script_str = infile
else:
with open(infile, "r") as file:
script_str = file.read()
Expand Down
41 changes: 41 additions & 0 deletions tests/test_freecad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import tests.test_helpers as helpers


def test_static_freecad_file():
"""
Basic test of the FreeCAD (FCStd) codec plugin.
"""
test_file = helpers.get_test_file_location("shelf.FCStd")

command = [
"python",
"src/cq_cli/main.py",
"--codec",
"step",
"--infile",
test_file,
]
out, err, exitcode = helpers.cli_call(command)

assert "ISO-10303-21;" in out.decode()


def test_parametric_freecad_file():
"""
Basic test of the FreeCAD (FCStd) codec plugin.
"""
test_file = helpers.get_test_file_location("shelf.FCStd")

command = [
"python",
"src/cq_cli/main.py",
"--codec",
"step",
"--params",
"internal_rail_spacing:152.4;",
"--infile",
test_file,
]
out, err, exitcode = helpers.cli_call(command)

assert "ISO-10303-21;" in out.decode()
Binary file added tests/testdata/shelf.FCStd
Binary file not shown.

0 comments on commit ce49645

Please sign in to comment.