Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
daa09f8
Clean up tox file
RobPasMue Oct 27, 2022
0e0820c
Implement beam deletion (no tests)
RobPasMue Oct 27, 2022
d31ec22
Adding test - though failing
RobPasMue Oct 27, 2022
e6e34b7
Merge branch 'main' into feat/delete-beam
RobPasMue Oct 27, 2022
8c8729e
Beartype complaining about return type
RobPasMue Oct 27, 2022
0de658e
Merge branch 'main' into feat/delete-beam
RobPasMue Oct 27, 2022
dfca21a
Merge branch 'main' into feat/delete-beam
RobPasMue Oct 28, 2022
0ee3016
Update ansys-api-geometry dep
RobPasMue Oct 28, 2022
d9c327f
Deleting beams and beam profiles part 2
RobPasMue Oct 28, 2022
77caf4f
Merge branch 'main' into feat/delete-beam
RobPasMue Oct 30, 2022
17e5f27
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 2, 2022
081fd4f
Typos
RobPasMue Nov 2, 2022
d82ed06
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 4, 2022
dc85a8d
Improving beams test
RobPasMue Nov 4, 2022
5aeaaad
Fix id setting for DeleteBeamProfile
chadqueen Nov 4, 2022
ad11ae6
Improvements to legibility
RobPasMue Nov 4, 2022
1564403
Apply suggestions from code review
RobPasMue Nov 4, 2022
72249b8
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 10, 2022
c5c952e
Update pyproject.toml
RobPasMue Nov 10, 2022
fe6f6ae
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 11, 2022
bf8b919
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 14, 2022
e741669
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 15, 2022
d832c7b
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 18, 2022
bd0c73c
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 21, 2022
ead7537
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 22, 2022
a5f4778
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 22, 2022
326a1dc
Merge branch 'main' into feat/delete-beam
Revathyvenugopal162 Nov 23, 2022
f3c3d2d
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 24, 2022
f7a4a99
Merge branch 'main' into feat/delete-beam
RobPasMue Nov 30, 2022
c02bfca
Merge branch 'main' into feat/delete-beam
RobPasMue Dec 1, 2022
631e10a
Merge branch 'main' into feat/delete-beam
RobPasMue Dec 2, 2022
b59fa3b
Merge branch 'main' into feat/delete-beam
RobPasMue Dec 4, 2022
d8463e8
Merge branch 'main' into feat/delete-beam
Revathyvenugopal162 Dec 5, 2022
98d2708
Merge branch 'main' into feat/delete-beam
RobPasMue Dec 7, 2022
3be771f
Merge branch 'main' into feat/delete-beam
RobPasMue Dec 7, 2022
d6bec51
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 2, 2023
077ebf0
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 9, 2023
3e786c3
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 11, 2023
ebd0334
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 11, 2023
cd0669d
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 20, 2023
375942a
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 25, 2023
2f9a3b0
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 30, 2023
040264b
Merge branch 'main' into feat/delete-beam
RobPasMue Jan 30, 2023
75d4004
Merge branch 'main' into feat/delete-beam
RobPasMue Feb 1, 2023
2ea89e7
Merge branch 'main' into feat/delete-beam
RobPasMue Feb 1, 2023
9d1c3f8
Merge conflicts
RobPasMue Feb 1, 2023
fe6cc21
Unnecessary line
RobPasMue Feb 1, 2023
128c872
Merge branch 'main' into feat/delete-beam
RobPasMue Feb 2, 2023
6d0fd4f
Merge branch 'main' into feat/delete-beam
RobPasMue Feb 16, 2023
7a9d914
Merge branch 'main' into feat/delete-beam
RobPasMue Feb 17, 2023
e63b4e2
Merge branch 'main' into feat/delete-beam
RobPasMue Feb 21, 2023
534f72e
Merge branch 'main' into feat/delete-beam
RobPasMue Mar 3, 2023
53aea34
Merge branch 'main' into feat/delete-beam
RobPasMue Mar 9, 2023
4aae722
Merge branch 'main' into feat/delete-beam
RobPasMue Mar 29, 2023
a45aa40
Merge branch 'main' into feat/delete-beam
RobPasMue Mar 30, 2023
5485c1f
Merge branch 'main' into feat/delete-beam
RobPasMue Apr 7, 2023
01c0b13
Merge branch 'main' into feat/delete-beam
RobPasMue Apr 7, 2023
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
7 changes: 7 additions & 0 deletions src/ansys/geometry/core/designer/beam.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ def __init__(
self._end = end
self._profile = profile
self._parent_component = parent_component
self._is_alive = True

@property
def id(self) -> str:
Expand All @@ -194,9 +195,15 @@ def parent_component(self) -> Union["Component", None]:
"""Component node that the beam`` is under."""
return self._parent_component

@property
def is_alive(self) -> bool:
"""Boolean indicating whether the beam is still alive on the server side."""
return self._is_alive

def __repr__(self) -> str:
"""String representation of the beam."""
lines = [f"ansys.geometry.core.designer.Beam {hex(id(self))}"]
lines.append(f" Exists : {self.is_alive}")
lines.append(
f" Start : [{','.join([str(x) for x in self.start])}] in meters"
)
Expand Down
93 changes: 81 additions & 12 deletions src/ansys/geometry/core/designer/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,10 +674,10 @@ def delete_component(self, component: Union["Component", str]) -> None:

Parameters
----------
id : Union[Component, str]
Name of the component or instance to delete.
component : Union[Component, str]
ID of the component or instance to delete.
"""
id = component.id if not isinstance(component, str) else component
id = component if isinstance(component, str) else component.id
component_requested = self.search_component(id)

if component_requested:
Expand Down Expand Up @@ -708,10 +708,10 @@ def delete_body(self, body: Union[Body, str]) -> None:

Parameters
----------
id : Union[Body, str]
Name of the body or instance to delete.
body : Union[Body, str]
ID of the body or instance to delete.
"""
id = body.id if not isinstance(body, str) else body
id = body if isinstance(body, str) else body.id
body_requested = self.search_body(id)

if body_requested:
Expand All @@ -730,6 +730,44 @@ def delete_body(self, body: Union[Body, str]) -> None:
)
pass

@protect_grpc
@check_input_types
def delete_beam(self, beam: Union[Beam, str]) -> None:
"""Deletes an existing beam belonging to this component (or its children).

Notes
-----
If the beam does not belong to this component (or its children), it
will not be deleted.

Parameters
----------
beam : Union[Beam, str]
ID of the beam or instance to delete.
"""
id = beam if isinstance(beam, str) else beam.id
beam_requested = self.search_beam(id)

if beam_requested:
# If the beam belongs to this component (or nested components)
# call the server deletion mechanism
#
# Server-side, the same deletion request has to be performed
# as for deleting a Body
#
self._commands_stub.DeleteBeam(EntityIdentifier(id=beam_requested.id))

# If the beam was deleted from the server side... "kill" it
# on the client side
beam_requested._is_alive = False
self._grpc_client.log.debug(f"Beam {beam_requested.id} has been deleted.")
else:
self._grpc_client.log.warning(
f"Beam {id} not found in this component (or sub-components)."
+ " Ignoring deletion request."
)
pass

@check_input_types
def search_component(self, id: str) -> Union["Component", None]:
"""Search nested components recursively for a component.
Expand Down Expand Up @@ -787,17 +825,46 @@ def search_body(self, id: str) -> Union[Body, None]:
# If you reached this point... this means that no body was found!
return None

@check_input_types
def search_beam(self, id: str) -> Union[Beam, None]:
"""Search beams in component and nested components recursively for a beam.

Parameters
----------
id : str
The ``Beam`` ID we are searching for.

Returns
-------
Union[Beam, None]
The ``Beam`` with the requested ID. If not found, it will return ``None``.
"""
# Search in component's beams
for beam in self.beams:
if beam.id == id and beam.is_alive:
return beam

# If no luck, search on nested components
result = None
for component in self.components:
result = component.search_beam(id)
if result:
return result

# If you reached this point... this means that no beam was found!
return None

def _kill_component_on_client(self) -> None:
"""Set the ``is_alive`` property of nested components and bodies to ``False``.
"""Sets the ``is_alive`` property of nested objects to ``False``.

Notes
-----
This method is recursive. It is only to be used by the
``delete_component()`` method and itself."""

# Kill all its bodies
for body in self.bodies:
body._is_alive = False
# Kill all its bodies, beams and coordinate systems
for elem in [*self.bodies, *self.beams, *self._coordinate_systems]:
elem._is_alive = False

# Now, go to the nested components and kill them as well
for component in self.components:
Expand Down Expand Up @@ -971,13 +1038,15 @@ def plot(
def __repr__(self) -> str:
"""String representation of the component."""
alive_bodies = [1 if body.is_alive else 0 for body in self.bodies]
alive_beams = [1 if beam.is_alive else 0 for beam in self.beams]
alive_coords = [1 if cs.is_alive else 0 for cs in self.coordinate_systems]
alive_comps = [1 if comp.is_alive else 0 for comp in self.components]
lines = [f"ansys.geometry.core.designer.Component {hex(id(self))}"]
lines.append(f" Name : {self.name}")
lines.append(f" Exists : {self.is_alive}")
lines.append(f" Parent component : {self.parent_component.name}")
lines.append(f" N Bodies : {sum(alive_bodies)}")
lines.append(f" N Beams : {len(self.beams)}")
lines.append(f" N Beams : {sum(alive_beams)}")
lines.append(f" N Coordinate Systems : {sum(alive_coords)}")
lines.append(f" N Components : {sum(alive_comps)}")
lines.append(f" N Coordinate Systems : {len(self.coordinate_systems)}")
return "\n".join(lines)
7 changes: 7 additions & 0 deletions src/ansys/geometry/core/designer/coordinate_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def __init__(
]
),
)
self._is_alive = True

@property
def id(self) -> str:
Expand All @@ -97,10 +98,16 @@ def parent_component(self) -> "Component":
"""Parent component of the coordinate system."""
return self._parent_component

@property
def is_alive(self) -> bool:
"""Boolean indicating whether the CoordinateSystem is still alive on the server side."""
return self._is_alive

def __repr__(self):
"""String representation of the coordinate system."""
lines = [f"ansys.geometry.core.designer.CoordinateSystem {hex(id(self))}"]
lines.append(f" Name : {self.name}")
lines.append(f" Exists : {self.is_alive}")
lines.append(f" Parent component : {self.parent_component.name}")
lines.append(
f" Frame origin : [{','.join([str(x) for x in self.frame.origin])}] in meters"
Expand Down
27 changes: 26 additions & 1 deletion src/ansys/geometry/core/designer/design.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ def delete_named_selection(self, named_selection: Union[NamedSelection, str]) ->
removal_name = named_selection.name
removal_id = named_selection.id

self._grpc_client.log.debug(f"Named selection {removal_name} deletion request received.")
self._named_selections_stub.Delete(EntityIdentifier(id=removal_id))

try:
Expand Down Expand Up @@ -290,7 +291,7 @@ def delete_component(self, component: Union["Component", str]) -> None:
ValueError
The design itself cannot be deleted.
"""
id = component.id if not isinstance(component, str) else component
id = component if isinstance(component, str) else component.id
if id == self.id:
raise ValueError("The design itself cannot be deleted.")
else:
Expand Down Expand Up @@ -442,6 +443,30 @@ def add_midsurface_offset(self, offset_type: MidSurfaceOffsetType, bodies: List[
for body in ids_bodies:
body._surface_offset = offset_type

@protect_grpc
@check_input_types
def delete_beam_profile(self, beam_profile: Union[BeamProfile, str]) -> None:
"""Removes a beam profile on the active geometry server instance.

Parameters
----------
beam_profile : Union[BeamProfile, str]
A beam profile name or instance that should be deleted.
"""
removal_name = beam_profile if isinstance(beam_profile, str) else beam_profile.name
self._grpc_client.log.debug(f"Beam profile {removal_name} deletion request received.")
removal_obj = self._beam_profiles.get(removal_name, None)

if removal_obj:
self._commands_stub.DeleteBeamProfile(EntityIdentifier(id=removal_obj.id))
self._beam_profiles.pop(removal_name)
self._grpc_client.log.debug(f"Beam profile {removal_name} successfully deleted.")
else:
self._grpc_client.log.warning(
f"Attempted beam profile deletion failed, with name {removal_name}."
+ " Ignoring request."
)

def __repr__(self):
"""String representation of the design."""
alive_bodies = [1 if body.is_alive else 0 for body in self.bodies]
Expand Down
65 changes: 63 additions & 2 deletions tests/integration/test_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ def test_coordinate_system_creation(modeler: Modeler):
nested_comp_cs1_str = str(nested_comp_cs1)
assert "ansys.geometry.core.designer.CoordinateSystem" in nested_comp_cs1_str
assert " Name : CompCS1" in nested_comp_cs1_str
assert " Exists : True" in nested_comp_cs1_str
assert " Parent component : NestedComponent" in nested_comp_cs1_str
assert " Frame origin : [0.01,0.2,3.0] in meters" in nested_comp_cs1_str
assert " Frame X-direction : " in nested_comp_cs1_str
Expand Down Expand Up @@ -974,6 +975,7 @@ def test_beams(modeler: Modeler, skip_not_on_linux_service):
UnitVector3D([-1, -1, -1]),
)

# Create a beam at the root component level
beam_1 = design.create_beam(
Point3D([9, 99, 999], UNITS.mm), Point3D([8, 88, 888], UNITS.mm), circle_profile_1
)
Expand All @@ -983,11 +985,13 @@ def test_beams(modeler: Modeler, skip_not_on_linux_service):
assert beam_1.end == Point3D([8, 88, 888], UNITS.mm)
assert beam_1.profile == circle_profile_1
assert beam_1.parent_component.id == design.id
assert beam_1.is_alive
assert len(design.beams) == 1
assert design.beams[0] == beam_1

beam_1_str = str(beam_1)
assert "ansys.geometry.core.designer.Beam" in beam_1_str
assert " Exists : True" in beam_1_str
assert " Start : [0.009" in beam_1_str
assert " End : [0.008" in beam_1_str
assert " Parent component : BeamCreation" in beam_1_str
Expand All @@ -1000,17 +1004,74 @@ def test_beams(modeler: Modeler, skip_not_on_linux_service):
assert " Direction x : [1.0,0.0,0.0]" in beam_1_str
assert " Direction y : [0.0,1.0,0.0]" in beam_1_str

# Now, let's create two beams at a nested component, with the same profile
nested_component = design.add_component("NestedComponent")

beam_2 = nested_component.create_beam(
Point3D([7, 77, 777], UNITS.mm), Point3D([6, 66, 666], UNITS.mm), circle_profile_2
)
beam_3 = nested_component.create_beam(
Point3D([8, 88, 888], UNITS.mm), Point3D([7, 77, 777], UNITS.mm), circle_profile_2
)

assert beam_2.id is not None
assert beam_2.profile == circle_profile_2
assert beam_2.parent_component.id == nested_component.id
assert len(nested_component.beams) == 1
assert beam_2.is_alive
assert beam_3.id is not None
assert beam_3.profile == circle_profile_2
assert beam_3.parent_component.id == nested_component.id
assert beam_3.is_alive
assert beam_2.id != beam_3.id
assert len(nested_component.beams) == 2
assert nested_component.beams[0] == beam_2
assert nested_component.beams[1] == beam_3

# Once the beams are created, let's try deleting it.
# For example, we shouldn't be able to delete beam_1 from the nested component.
nested_component.delete_beam(beam_1)

assert beam_2.is_alive
assert nested_component.beams[0].is_alive
assert beam_3.is_alive
assert nested_component.beams[1].is_alive
assert beam_1.is_alive
assert design.beams[0].is_alive

# Let's try deleting one of the beams from the nested component
nested_component.delete_beam(beam_2)
assert not beam_2.is_alive
assert not nested_component.beams[0].is_alive
assert beam_3.is_alive
assert nested_component.beams[1].is_alive
assert beam_1.is_alive
assert design.beams[0].is_alive

# Now, let's try deleting it from the design directly - this should be possible
design.delete_beam(beam_3)
assert not beam_2.is_alive
assert not nested_component.beams[0].is_alive
assert not beam_3.is_alive
assert not nested_component.beams[1].is_alive
assert beam_1.is_alive
assert design.beams[0].is_alive

# Finally, let's delete the beam from the root component
design.delete_beam(beam_1)
assert not beam_2.is_alive
assert not nested_component.beams[0].is_alive
assert not beam_3.is_alive
assert not nested_component.beams[1].is_alive
assert not beam_1.is_alive
assert not design.beams[0].is_alive

# Now, let's try deleting the beam profiles!
assert len(design.beam_profiles) == 2
design.delete_beam_profile("MyInventedBeamProfile")
assert len(design.beam_profiles) == 2
design.delete_beam_profile(circle_profile_1)
assert len(design.beam_profiles) == 1
design.delete_beam_profile(circle_profile_2)
assert len(design.beam_profiles) == 0


def test_midsurface_properties(modeler: Modeler):
Expand Down