Skip to content

Commit 4094b48

Browse files
RobPasMuepyansys-ci-botb-matteopre-commit-ci[bot]
authored
feat: inserting document into existing design (#930)
Co-authored-by: pyansys-ci-bot <pyansys.github.bot@ansys.com> Co-authored-by: m-bini <matteo.bini@ansys.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 140e8de commit 4094b48

File tree

9 files changed

+223
-75
lines changed

9 files changed

+223
-75
lines changed

doc/changelog.d/930.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
feat: inserting document into existing design

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

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
from pathlib import Path
2626

2727
from ansys.api.dbu.v0.dbumodels_pb2 import EntityIdentifier, PartExportFormat
28-
from ansys.api.dbu.v0.designs_pb2 import NewRequest, SaveAsRequest
28+
from ansys.api.dbu.v0.designs_pb2 import InsertRequest, NewRequest, SaveAsRequest
2929
from ansys.api.dbu.v0.designs_pb2_grpc import DesignsStub
3030
from ansys.api.geometry.v0.commands_pb2 import (
3131
AssignMidSurfaceOffsetTypeRequest,
@@ -68,7 +68,7 @@
6868
from ansys.geometry.core.math.plane import Plane
6969
from ansys.geometry.core.math.point import Point3D
7070
from ansys.geometry.core.math.vector import UnitVector3D, Vector3D
71-
from ansys.geometry.core.misc.checks import ensure_design_is_active
71+
from ansys.geometry.core.misc.checks import ensure_design_is_active, min_backend_version
7272
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS, Distance
7373
from ansys.geometry.core.modeler import Modeler
7474
from ansys.geometry.core.typing import RealSequence
@@ -581,6 +581,58 @@ def delete_beam_profile(self, beam_profile: Union[BeamProfile, str]) -> None:
581581
+ " Ignoring request."
582582
)
583583

584+
@protect_grpc
585+
@check_input_types
586+
@ensure_design_is_active
587+
@min_backend_version(24, 2, 0)
588+
def insert_file(self, file_location: Union[Path, str]) -> Component:
589+
"""
590+
Insert a file into the design.
591+
592+
Parameters
593+
----------
594+
file_location : Union[~pathlib.Path, str]
595+
Location on disk where the file is located.
596+
597+
Returns
598+
-------
599+
Component
600+
The newly inserted component.
601+
"""
602+
# Upload the file to the server
603+
filepath_server = self._modeler._upload_file(file_location)
604+
605+
# Insert the file into the design
606+
self._design_stub.Insert(InsertRequest(filepath=filepath_server))
607+
self._grpc_client.log.debug(f"File {file_location} successfully inserted into design.")
608+
609+
# Get a temporal design object to update the current one
610+
tmp_design = Design("", self._modeler, read_existing_design=True)
611+
612+
# Update the reference to the design
613+
for component in tmp_design.components:
614+
component._parent_component = self
615+
616+
# Update the design's components - add the new one
617+
#
618+
# If the list is empty, add the components from the new design
619+
if not self._components:
620+
self._components.extend(tmp_design.components)
621+
else:
622+
# Insert operation adds the inserted file as a component to the design.
623+
for tmp_component in tmp_design.components:
624+
# Otherwise, check which is the new component added
625+
for component in self._components:
626+
if component.id == tmp_component.id:
627+
break
628+
# If not equal, add the component - since it has not been found
629+
self._components.append(tmp_component)
630+
631+
self._grpc_client.log.debug(f"Design {self.name} is successfully updated.")
632+
633+
# Return the newly inserted component
634+
return self._components[-1]
635+
584636
def __repr__(self) -> str:
585637
"""Represent the ``Design`` as a string."""
586638
alive_bodies = [1 if body.is_alive else 0 for body in self.bodies]

tests/integration/__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.

tests/integration/conftest.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@
4343
pv.OFF_SCREEN = True
4444

4545

46+
# TODO: re-enable when Linux service is able to use measurement tools
47+
def skip_if_linux(modeler: Modeler, test_name: str, element_not_available: str):
48+
"""Skip test if running on Linux."""
49+
if modeler.client.backend_type == BackendType.LINUX_SERVICE:
50+
pytest.skip(
51+
f"Skipping '{test_name}'. '{element_not_available}' not available on Linux service."
52+
) # skip!
53+
54+
4655
@pytest.fixture(scope="session")
4756
def docker_instance(use_existing_service):
4857
# This will only have a value in case that:

tests/integration/test_design.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,7 @@
6060
from ansys.geometry.core.shapes.parameterization import Interval, ParamUV
6161
from ansys.geometry.core.sketch import Sketch
6262

63-
64-
# TODO: re-enable when Linux service is able to use measurement tools
65-
def skip_if_linux(modeler: Modeler):
66-
"""Skip test if running on Linux."""
67-
if modeler.client.backend_type == BackendType.LINUX_SERVICE:
68-
pytest.skip("Measurement tools not available on Linux service.")
63+
from .conftest import skip_if_linux
6964

7065

7166
def test_design_extrusion_and_material_assignment(modeler: Modeler):
@@ -1932,7 +1927,7 @@ def test_get_active_design(modeler: Modeler):
19321927

19331928
def test_get_collision(modeler: Modeler):
19341929
"""Test the collision state between two bodies."""
1935-
skip_if_linux(modeler) # Skip test on Linux
1930+
skip_if_linux(modeler, test_get_collision.__name__, "get_collision") # Skip test on Linux
19361931
design = modeler.open_file("./tests/integration/files/MixingTank.scdocx")
19371932
body1 = design.bodies[0]
19381933
body2 = design.bodies[1]
@@ -1959,7 +1954,7 @@ def test_body_scale(modeler: Modeler):
19591954

19601955
def test_body_mapping(modeler: Modeler):
19611956
"""Verify the correct mapping of a body."""
1962-
skip_if_linux(modeler)
1957+
skip_if_linux(modeler, test_body_mapping.__name__, "map")
19631958
design = modeler.create_design("BodyMap_Test")
19641959

19651960
# non-symmetric shape to allow determination of mirroring
@@ -2052,7 +2047,7 @@ def test_body_mapping(modeler: Modeler):
20522047

20532048
def test_sphere_creation(modeler: Modeler):
20542049
"""Test the creation of a sphere body with a given radius."""
2055-
skip_if_linux(modeler)
2050+
skip_if_linux(modeler, test_sphere_creation.__name__, "create_sphere")
20562051
design = modeler.create_design("Spheretest")
20572052
center_point = Point3D([10, 10, 10], UNITS.m)
20582053
radius = Distance(1, UNITS.m)
@@ -2064,7 +2059,7 @@ def test_sphere_creation(modeler: Modeler):
20642059

20652060
def test_body_mirror(modeler: Modeler):
20662061
"""Test the mirroring of a body."""
2067-
skip_if_linux(modeler)
2062+
skip_if_linux(modeler, test_body_mirror.__name__, "mirror")
20682063
design = modeler.create_design("Design1")
20692064

20702065
# Create shape with no lines of symmetry in any axis
@@ -2183,7 +2178,7 @@ def test_body_mirror(modeler: Modeler):
21832178
def test_sweep_sketch(modeler: Modeler):
21842179
"""Test revolving a circle profile around a circular axis to make a donut."""
21852180

2186-
skip_if_linux(modeler)
2181+
skip_if_linux(modeler, test_sweep_sketch.__name__, "sweep_sketch")
21872182
design_sketch = modeler.create_design("donut")
21882183

21892184
path_radius = 5
@@ -2221,7 +2216,7 @@ def test_sweep_chain(modeler: Modeler):
22212216
"""Test revolving a semi-elliptical profile around a circular axis to make a
22222217
bowl."""
22232218

2224-
skip_if_linux(modeler)
2219+
skip_if_linux(modeler, test_sweep_chain.__name__, "sweep_chain")
22252220
design_chain = modeler.create_design("bowl")
22262221

22272222
radius = 10
@@ -2269,7 +2264,9 @@ def test_sweep_chain(modeler: Modeler):
22692264

22702265
def test_create_body_from_loft_profile(modeler: Modeler):
22712266
"""Test the ``create_body_from_loft_profile()`` method to create a vase shape."""
2272-
skip_if_linux(modeler)
2267+
skip_if_linux(
2268+
modeler, test_create_body_from_loft_profile.__name__, "'create_body_from_loft_profile'"
2269+
)
22732270
design_sketch = modeler.create_design("loftprofile")
22742271

22752272
profile1 = Circle(origin=[0, 0, 0], radius=8).trim(Interval(0, 2 * np.pi))

tests/integration/test_design_import.py

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
from ansys.geometry.core.misc import UNITS
3434
from ansys.geometry.core.sketch import Sketch
3535

36+
from .conftest import skip_if_linux
37+
3638

3739
def _checker_method(comp: Component, comp_ref: Component, precise_check: bool = True) -> None:
3840
# Check component features
@@ -130,18 +132,19 @@ def test_design_import_with_surfaces_issue834(modeler: Modeler):
130132
For more info see https://github.com/ansys/pyansys-geometry/issues/834
131133
"""
132134
# TODO: to be reactivated by https://github.com/ansys/pyansys-geometry/issues/799
133-
if modeler.client.backend_type != BackendType.LINUX_SERVICE:
134-
# Open the design
135-
design = modeler.open_file("./tests/integration/files/DuplicateFacesDesignBefore.scdocx")
135+
skip_if_linux(modeler, test_design_import_with_surfaces_issue834.__name__, "open_file")
136+
137+
# Open the design
138+
design = modeler.open_file("./tests/integration/files/DuplicateFacesDesignBefore.scdocx")
136139

137-
# Check that there are two bodies
138-
assert len(design.bodies) == 2
140+
# Check that there are two bodies
141+
assert len(design.bodies) == 2
139142

140-
# Check some basic properties - whether they are surfaces or not!
141-
assert design.bodies[0].name == "BoxBody"
142-
assert design.bodies[0].is_surface == False
143-
assert design.bodies[1].name == "DuplicatesSurface"
144-
assert design.bodies[1].is_surface == True
143+
# Check some basic properties - whether they are surfaces or not!
144+
assert design.bodies[0].name == "BoxBody"
145+
assert design.bodies[0].is_surface == False
146+
assert design.bodies[1].name == "DuplicatesSurface"
147+
assert design.bodies[1].is_surface == True
145148

146149

147150
@pytest.mark.skip(reason="Get the OpenSSL GeometryService through before fixing hoops")
@@ -240,3 +243,48 @@ def test_open_file(modeler: Modeler, tmp_path_factory: pytest.TempPathFactory):
240243
# .prt
241244
design2 = modeler.open_file("./tests/integration/files/import/disk1.prt")
242245
assert len(design2.bodies) == 1
246+
247+
248+
def test_design_insert(modeler: Modeler):
249+
"""Test inserting a file into the design."""
250+
251+
# Skip for Linux service
252+
skip_if_linux(modeler, test_design_insert.__name__, "insert_file")
253+
254+
# Create a design and sketch a circle
255+
design = modeler.create_design("Insert")
256+
sketch = Sketch()
257+
sketch.circle(Point2D([0, 0]), 10)
258+
comp = design.add_component("Component_Cylinder")
259+
comp.extrude_sketch("Body_Cylinder", sketch, 5)
260+
261+
# Insert a different file
262+
design.insert_file("./tests/integration/files/DuplicateFacesDesignBefore.scdocx")
263+
264+
# Check that there are two components
265+
assert len(design.components) == 2
266+
assert design.components[0].name == "Component_Cylinder"
267+
assert design.components[1].name == "DuplicatesDesign"
268+
269+
270+
def test_design_insert_with_import(modeler: Modeler):
271+
"""Test inserting a file into the design through the external format import
272+
process."""
273+
274+
# Skip for Linux service
275+
skip_if_linux(modeler, test_design_insert_with_import.__name__, "insert_file")
276+
277+
# Create a design and sketch a circle
278+
design = modeler.create_design("Insert")
279+
sketch = Sketch()
280+
sketch.circle(Point2D([0, 0]), 10)
281+
comp = design.add_component("Component_Cylinder")
282+
comp.extrude_sketch("Body_Cylinder", sketch, 5)
283+
284+
# Import and insert a different file
285+
design.insert_file("./tests/integration/files/import/catia_car/Wheel1.CATPart")
286+
287+
# Check that there are two components
288+
assert len(design.components) == 2
289+
assert design.components[0].name == "Component_Cylinder"
290+
assert design.components[1].name == "Wheel1"

tests/integration/test_measurement_tools.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,11 @@
2121
# SOFTWARE.
2222
""""Testing of measurement tools."""
2323

24-
import pytest
25-
26-
from ansys.geometry.core.connection.backend import BackendType
2724
from ansys.geometry.core.misc.measurements import Distance
2825
from ansys.geometry.core.modeler import Modeler
2926
from ansys.geometry.core.tools.measurement_tools import Gap
3027

31-
32-
# TODO: re-enable when Linux service is able to use measurement tools
33-
def skip_if_linux(modeler: Modeler):
34-
"""Skip test if running on Linux."""
35-
if modeler.client.backend_type == BackendType.LINUX_SERVICE:
36-
pytest.skip("Measurement tools not available on Linux service.")
28+
from .conftest import skip_if_linux
3729

3830

3931
def test_distance_property(modeler: Modeler):
@@ -44,7 +36,9 @@ def test_distance_property(modeler: Modeler):
4436

4537
def test_min_distance_between_objects(modeler: Modeler):
4638
"""Test if split edge problem areas are detectable."""
47-
skip_if_linux(modeler) # Skip test on Linux
39+
skip_if_linux(
40+
modeler, test_min_distance_between_objects.__name__, "measurement_tools"
41+
) # Skip test on Linux
4842
design = modeler.open_file("./tests/integration/files/MixingTank.scdocx")
4943
gap = modeler.measurement_tools.min_distance_between_objects(design.bodies[2], design.bodies[1])
5044
assert abs(gap.distance._value - 0.0892) <= 0.01

0 commit comments

Comments
 (0)