Skip to content

Commit 05dbe8e

Browse files
jonahrbpyansys-ci-botRyanJWardRobPasMue
authored
feat: option to write body facets on save (#2169)
Co-authored-by: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Co-authored-by: rward <ryan.ward@ansys.com> Co-authored-by: Roberto Pastor Muela <37798125+RobPasMue@users.noreply.github.com>
1 parent 725e55e commit 05dbe8e

File tree

6 files changed

+107
-10
lines changed

6 files changed

+107
-10
lines changed

doc/changelog.d/2169.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Option to write body facets on save

src/ansys/geometry/core/_grpc/_services/v0/conversions.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,3 +1161,23 @@ def _nurbs_curves_compatibility(backend_version: "semver.Version", grpc_geometri
11611161
+ "26.1.0, but the current version used is "
11621162
+ f"{backend_version}."
11631163
)
1164+
1165+
1166+
def _check_write_body_facets_input(backend_version: "semver.Version", write_body_facets: bool):
1167+
"""Check if the backend version is compatible with NURBS curves in sketches.
1168+
1169+
Parameters
1170+
----------
1171+
backend_version : semver.Version
1172+
The version of the backend.
1173+
write_body_facets : bool
1174+
Option to write out body facets.
1175+
"""
1176+
if write_body_facets and backend_version < (26, 1, 0):
1177+
from ansys.geometry.core.logger import LOG
1178+
1179+
LOG.warning(
1180+
"The usage of write_body_facets requires a minimum Ansys release version of "
1181+
+ "26.1.0, but the current version used is "
1182+
+ f"{backend_version}."
1183+
)

src/ansys/geometry/core/_grpc/_services/v0/designs.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626
from ansys.geometry.core.errors import protect_grpc
2727

2828
from ..base.designs import GRPCDesignsService
29-
from .conversions import build_grpc_id, from_design_file_format_to_grpc_part_export_format
29+
from .conversions import (
30+
_check_write_body_facets_input,
31+
build_grpc_id,
32+
from_design_file_format_to_grpc_part_export_format,
33+
)
3034

3135

3236
class GRPCDesignsServiceV0(GRPCDesignsService): # pragma: no cover
@@ -106,8 +110,12 @@ def put_active(self, **kwargs) -> dict: # noqa: D102
106110
def save_as(self, **kwargs) -> dict: # noqa: D102
107111
from ansys.api.dbu.v0.designs_pb2 import SaveAsRequest
108112

113+
_check_write_body_facets_input(kwargs["backend_version"], kwargs["write_body_facets"])
114+
109115
# Create the request - assumes all inputs are valid and of the proper type
110-
request = SaveAsRequest(filepath=kwargs["filepath"])
116+
request = SaveAsRequest(
117+
filepath=kwargs["filepath"], write_body_facets=kwargs["write_body_facets"]
118+
)
111119

112120
# Call the gRPC service
113121
_ = self.stub.SaveAs(request)
@@ -119,9 +127,12 @@ def save_as(self, **kwargs) -> dict: # noqa: D102
119127
def download_export(self, **kwargs) -> dict: # noqa: D102
120128
from ansys.api.dbu.v0.designs_pb2 import DownloadExportFileRequest
121129

130+
_check_write_body_facets_input(kwargs["backend_version"], kwargs["write_body_facets"])
131+
122132
# Create the request - assumes all inputs are valid and of the proper type
123133
request = DownloadExportFileRequest(
124-
format=from_design_file_format_to_grpc_part_export_format(kwargs["format"])
134+
format=from_design_file_format_to_grpc_part_export_format(kwargs["format"]),
135+
write_body_facets=kwargs["write_body_facets"],
125136
)
126137

127138
# Call the gRPC service
@@ -136,9 +147,12 @@ def download_export(self, **kwargs) -> dict: # noqa: D102
136147
def stream_download_export(self, **kwargs) -> dict: # noqa: D102
137148
from ansys.api.dbu.v0.designs_pb2 import DownloadExportFileRequest
138149

150+
_check_write_body_facets_input(kwargs["backend_version"], kwargs["write_body_facets"])
151+
139152
# Create the request - assumes all inputs are valid and of the proper type
140153
request = DownloadExportFileRequest(
141-
format=from_design_file_format_to_grpc_part_export_format(kwargs["format"])
154+
format=from_design_file_format_to_grpc_part_export_format(kwargs["format"]),
155+
write_body_facets=kwargs["write_body_facets"],
142156
)
143157

144158
# Call the gRPC service

src/ansys/geometry/core/designer/design.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,19 +229,25 @@ def add_material(self, material: Material) -> None:
229229

230230
@check_input_types
231231
@ensure_design_is_active
232-
def save(self, file_location: Path | str) -> None:
232+
def save(self, file_location: Path | str, write_body_facets: bool = False) -> None:
233233
"""Save a design to disk on the active Geometry server instance.
234234
235235
Parameters
236236
----------
237237
file_location : ~pathlib.Path | str
238238
Location on disk to save the file to.
239+
write_body_facets : bool, default: False
240+
Option to write body facets into the saved file. 26R1 and later.
239241
"""
240242
# Sanity checks on inputs
241243
if isinstance(file_location, Path):
242244
file_location = str(file_location)
243245

244-
self._grpc_client.services.designs.save_as(filepath=file_location)
246+
self._grpc_client.services.designs.save_as(
247+
filepath=file_location,
248+
write_body_facets=write_body_facets,
249+
backend_version=self._grpc_client.backend_version,
250+
)
245251
self._grpc_client.log.debug(f"Design successfully saved at location {file_location}.")
246252

247253
@protect_grpc
@@ -251,6 +257,7 @@ def download(
251257
self,
252258
file_location: Path | str,
253259
format: DesignFileFormat = DesignFileFormat.SCDOCX,
260+
write_body_facets: bool = False,
254261
) -> None:
255262
"""Export and download the design from the server.
256263
@@ -260,6 +267,8 @@ def download(
260267
Location on disk to save the file to.
261268
format : DesignFileFormat, default: DesignFileFormat.SCDOCX
262269
Format for the file to save to.
270+
write_body_facets : bool, default: False
271+
Option to write body facets into the saved file. SCDOCX only, 26R1 and later.
263272
"""
264273
# Sanity checks on inputs
265274
if isinstance(file_location, str):
@@ -275,7 +284,9 @@ def download(
275284
if self._modeler.client.backend_version < (25, 2, 0):
276285
received_bytes = self.__export_and_download_legacy(format=format)
277286
else:
278-
received_bytes = self.__export_and_download(format=format)
287+
received_bytes = self.__export_and_download(
288+
format=format, write_body_facets=write_body_facets
289+
)
279290

280291
# Write to file
281292
file_location.write_bytes(received_bytes)
@@ -323,7 +334,11 @@ def __export_and_download_legacy(self, format: DesignFileFormat) -> bytes:
323334

324335
return received_bytes
325336

326-
def __export_and_download(self, format: DesignFileFormat) -> bytes:
337+
def __export_and_download(
338+
self,
339+
format: DesignFileFormat,
340+
write_body_facets: bool = False,
341+
) -> bytes:
327342
"""Export and download the design from the server.
328343
329344
Parameters
@@ -351,14 +366,22 @@ def __export_and_download(self, format: DesignFileFormat) -> bytes:
351366
DesignFileFormat.STRIDE,
352367
]:
353368
try:
354-
response = self._grpc_client.services.designs.download_export(format=format)
369+
response = self._grpc_client.services.designs.download_export(
370+
format=format,
371+
write_body_facets=write_body_facets,
372+
backend_version=self._grpc_client.backend_version,
373+
)
355374
except Exception:
356375
self._grpc_client.log.warning(
357376
f"Failed to download the file in {format} format."
358377
" Attempting to stream download."
359378
)
360379
# Attempt to download the file via streaming
361-
response = self._grpc_client.services.designs.stream_download_export(format=format)
380+
response = self._grpc_client.services.designs.stream_download_export(
381+
format=format,
382+
write_body_facets=write_body_facets,
383+
backend_version=self._grpc_client.backend_version,
384+
)
362385
else:
363386
self._grpc_client.log.warning(
364387
f"{format} format requested is not supported. Ignoring download request."

tests/_incompatible_tests.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ backends:
102102
# Bug fix included from 26.1 onwards
103103
- tests/integration/test_design_import.py::test_named_selections_after_file_insert
104104
- tests/integration/test_design_import.py::test_named_selections_after_file_open
105+
# Export body facets add in 26.1
106+
- tests/integration/test_design.py::test_write_body_facets_on_save
105107

106108
- version: "24.2"
107109
incompatible_tests:
@@ -198,6 +200,8 @@ backends:
198200
# Bug fix included from 26.1 onwards
199201
- tests/integration/test_design_import.py::test_named_selections_after_file_insert
200202
- tests/integration/test_design_import.py::test_named_selections_after_file_open
203+
# Export body facets add in 26.1
204+
- tests/integration/test_design.py::test_write_body_facets_on_save
201205

202206
- version: "25.1"
203207
incompatible_tests:
@@ -263,6 +267,8 @@ backends:
263267
# Bug fix included from 26.1 onwards
264268
- tests/integration/test_design_import.py::test_named_selections_after_file_insert
265269
- tests/integration/test_design_import.py::test_named_selections_after_file_open
270+
# Export body facets add in 26.1
271+
- tests/integration/test_design.py::test_write_body_facets_on_save
266272

267273
- version: "25.2"
268274
incompatible_tests:
@@ -292,3 +298,5 @@ backends:
292298
# Bug fix included from 26.1 onwards
293299
- tests/integration/test_design_import.py::test_named_selections_after_file_insert
294300
- tests/integration/test_design_import.py::test_named_selections_after_file_open
301+
# Export body facets add in 26.1
302+
- tests/integration/test_design.py::test_write_body_facets_on_save

tests/integration/test_design.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import os
2525
from pathlib import Path
26+
import zipfile
2627

2728
import matplotlib.colors as mcolors
2829
import numpy as np
@@ -3579,3 +3580,33 @@ def test_component_make_independent(modeler: Modeler):
35793580
comp = design.components[0].components[-1].components[-1] # stale from update-design-in-place
35803581

35813582
assert not Accuracy.length_is_equal(comp.bodies[0].volume.m, face.body.volume.m)
3583+
3584+
3585+
def test_write_body_facets_on_save(modeler: Modeler, tmp_path_factory: pytest.TempPathFactory):
3586+
design = modeler.open_file(Path(FILES_DIR, "cars.scdocx"))
3587+
3588+
# First file without body facets
3589+
filepath_no_facets = tmp_path_factory.mktemp("test_design") / "cars_no_facets.scdocx"
3590+
design.download(filepath_no_facets)
3591+
3592+
# Second file with body facets
3593+
filepath_with_facets = tmp_path_factory.mktemp("test_design") / "cars_with_facets.scdocx"
3594+
design.download(filepath_with_facets, write_body_facets=True)
3595+
3596+
# Compare file sizes
3597+
size_no_facets = filepath_no_facets.stat().st_size
3598+
size_with_facets = filepath_with_facets.stat().st_size
3599+
3600+
assert size_with_facets > size_no_facets
3601+
3602+
# Ensure facets.bin and renderlist.xml files exist
3603+
with zipfile.ZipFile(filepath_with_facets, "r") as zip_ref:
3604+
namelist = set(zip_ref.namelist())
3605+
3606+
expected_files = {
3607+
"SpaceClaim/Graphics/facets.bin",
3608+
"SpaceClaim/Graphics/renderlist.xml",
3609+
}
3610+
3611+
missing = expected_files - namelist
3612+
assert not missing

0 commit comments

Comments
 (0)