Skip to content

Commit

Permalink
feat: add split body and tests (#1669)
Browse files Browse the repository at this point in the history
Co-authored-by: pyansys-ci-bot <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 22, 2025
1 parent 0beb35d commit 8397962
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/changelog.d/1669.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add split body and tests
77 changes: 77 additions & 0 deletions src/ansys/geometry/core/designer/geometry_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,28 @@
RevolveFacesByHelixRequest,
RevolveFacesRequest,
RevolveFacesUpToRequest,
SplitBodyRequest,
)
from ansys.api.geometry.v0.commands_pb2_grpc import CommandsStub
from ansys.geometry.core.connection import GrpcClient
from ansys.geometry.core.connection.conversions import (
line_to_grpc_line,
plane_to_grpc_plane,
point3d_to_grpc_point,
unit_vector_to_grpc_direction,
)
from ansys.geometry.core.errors import protect_grpc
from ansys.geometry.core.math import Point3D, UnitVector3D
from ansys.geometry.core.math.plane import Plane
from ansys.geometry.core.misc.auxiliary import (
get_bodies_from_ids,
get_design_from_body,
get_design_from_edge,
get_design_from_face,
)
from ansys.geometry.core.misc.checks import (
check_is_float_int,
check_type,
check_type_all_elements_in_iterable,
min_backend_version,
)
Expand Down Expand Up @@ -1063,3 +1068,75 @@ def replace_face(
)

return result.success

@protect_grpc
@min_backend_version(25, 2, 0)
def split_body(
self,
bodies: List["Body"],
plane: Plane,
slicers: Union["Edge", List["Edge"], "Face", List["Face"]],
faces: List["Face"],
extendfaces: bool,
) -> bool:
"""Split bodies with a plane, slicers, or faces.
Parameters
----------
bodies : List[Body]
Bodies to split
plane : Plane
Plane to split with
slicers : Edge | list[Edge] | Face | list[Face]
Slicers to split with
faces : List[Face]
Faces to split with
extendFaces : bool
Extend faces if split with faces
Returns
-------
bool
``True`` when successful, ``False`` when failed.
"""
from ansys.geometry.core.designer.body import Body
from ansys.geometry.core.designer.edge import Edge
from ansys.geometry.core.designer.face import Face

check_type_all_elements_in_iterable(bodies, Body)

for body in bodies:
body._reset_tessellation_cache()

plane_item = None
if plane is not None:
check_type(plane, Plane)
plane_item = plane_to_grpc_plane(plane)

slicer_items = None
if slicers is not None:
slicers: list["Face", "Edge"] = slicers if isinstance(slicers, list) else [slicers]
check_type_all_elements_in_iterable(slicers, (Edge, Face))
slicer_items = [slicer._grpc_id for slicer in slicers]

face_items = None
if faces is not None:
faces: list["Face"] = faces if isinstance(faces, list) else [faces]
check_type_all_elements_in_iterable(faces, Face)
face_items = [face._grpc_id for face in faces]

result = self._commands_stub.SplitBody(
SplitBodyRequest(
selection=[body._grpc_id for body in bodies],
split_by_plane=plane_item,
split_by_slicer=slicer_items,
split_by_faces=face_items,
extend_surfaces=extendfaces,
)
)

if result.success:
design = get_design_from_body(bodies[0])
design._update_design_inplace()

return result.success
Binary file added tests/integration/files/Edge_Slice_Test.dsco
Binary file not shown.
1 change: 1 addition & 0 deletions tests/integration/test_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -2766,6 +2766,7 @@ def test_surface_body_creation(modeler: Modeler):

def test_design_parameters(modeler: Modeler):
"""Test the design parameter's functionality."""
# DISCLAIMER : This is a workaround to get batch tests working
modeler.close_all_designs()
design = modeler.open_file(FILES_DIR / "blockswithparameters.dsco")
test_parameters = design.get_all_parameters()
Expand Down
135 changes: 135 additions & 0 deletions tests/integration/test_geometry_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
from ansys.geometry.core.shapes.curves.line import Line
from ansys.geometry.core.sketch.sketch import Sketch

from .conftest import FILES_DIR, skip_if_linux


def test_chamfer(modeler: Modeler):
"""Test chamfer on edges and faces."""
Expand Down Expand Up @@ -627,3 +629,136 @@ def test_replace_face(modeler: Modeler):
Quantity(0.992146018366, UNITS.m**3).m, rel=1e-6, abs=1e-8
)
assert len(base.faces) == 7


def test_split_body_by_plane(modeler: Modeler):
"Test split body by plane"
from ansys.geometry.core.math import Plane, Point2D, Point3D

# DISCLAIMER : This is a workaround to get batch tests working
modeler.close_all_designs()

design = modeler.create_design("split_body_by_plane")

body = design.extrude_sketch("box", Sketch().box(Point2D([0, 0]), 1, 1), 1)
assert len(body.faces) == 6
assert len(body.edges) == 12
assert body.volume.m == pytest.approx(Quantity(1, UNITS.m**3).m, rel=1e-6, abs=1e-8)

origin = Point3D([0, 0, 0.5])
plane = Plane(origin, direction_x=[1, 0, 0], direction_y=[0, 1, 0])

success = modeler.geometry_commands.split_body([body], plane, None, None, True)
assert success is True

assert len(design.bodies) == 2

assert design.bodies[0].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)
assert design.bodies[1].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)


def test_split_body_by_slicer_face(modeler: Modeler):
"Test split body by slicer face"

# DISCLAIMER : This is a workaround to get batch tests working
modeler.close_all_designs()

design = modeler.create_design("split_body_by_slicer_face")

body = design.extrude_sketch("box", Sketch().box(Point2D([0, 0]), 1, 1), 1)
assert len(body.faces) == 6
assert len(body.edges) == 12
assert body.volume.m == pytest.approx(Quantity(1, UNITS.m**3).m, rel=1e-6, abs=1e-8)

body2 = design.extrude_sketch("box2", Sketch().box(Point2D([3, 0]), 1, 1), 0.5)
assert len(body2.faces) == 6
assert len(body2.edges) == 12
assert body2.volume.m == pytest.approx(Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8)

face_to_split = body2.faces[1]

success = modeler.geometry_commands.split_body([body], None, [face_to_split], None, True)
assert success is True

assert len(design.bodies) == 3

assert design.bodies[0].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)
assert design.bodies[1].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)
assert design.bodies[2].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)


def test_split_body_by_slicer_edge(modeler: Modeler):
"Test split body by slicer edge"

# Skip for Linux service
skip_if_linux(modeler, test_split_body_by_slicer_edge.__name__, "split_body_by_slicer_edge")

design = modeler.open_file(FILES_DIR / "Edge_Slice_test.dsco")

assert len(design.bodies) == 1
body = design.bodies[0]
assert len(body.faces) == 4
assert len(body.edges) == 3
assert body.volume.m == pytest.approx(
Quantity(6.283185307179587e-06, UNITS.m**3).m, rel=1e-5, abs=1e-8
)

edge_to_split = body.edges[2]

success = modeler.geometry_commands.split_body([body], None, [edge_to_split], None, True)
assert success is True

assert len(design.bodies) == 2

assert design.bodies[0].volume.m == pytest.approx(
Quantity(3.1415927e-06, UNITS.m**3).m, rel=1e-5, abs=1e-8
)
assert design.bodies[1].volume.m == pytest.approx(
Quantity(3.1415927e-06, UNITS.m**3).m, rel=1e-5, abs=1e-8
)


def test_split_body_by_face(modeler: Modeler):
"Test split body by face"

# DISCLAIMER : This is a workaround to get batch tests working
modeler.close_all_designs()

design = modeler.create_design("split_body_by_face")

body = design.extrude_sketch("box", Sketch().box(Point2D([0, 0]), 1, 1), 1)
assert len(body.faces) == 6
assert len(body.edges) == 12
assert body.volume.m == pytest.approx(Quantity(1, UNITS.m**3).m, rel=1e-6, abs=1e-8)

body2 = design.extrude_sketch("box2", Sketch().box(Point2D([3, 0]), 1, 1), 0.5)
assert len(body2.faces) == 6
assert len(body2.edges) == 12
assert body2.volume.m == pytest.approx(Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8)

face_to_split = body2.faces[1]

success = modeler.geometry_commands.split_body([body], None, None, [face_to_split], True)
assert success is True

assert len(design.bodies) == 3

assert design.bodies[0].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)
assert design.bodies[1].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)
assert design.bodies[2].volume.m == pytest.approx(
Quantity(0.5, UNITS.m**3).m, rel=1e-6, abs=1e-8
)

0 comments on commit 8397962

Please sign in to comment.