Skip to content

Commit 8e723a1

Browse files
committed
Merge branch 'feat/commands_for_merge_and_intersect' of https://github.com/ansys/pyansys-geometry into feat/commands_for_merge_and_intersect
2 parents 086f6dd + a2b7aa0 commit 8e723a1

23 files changed

+901
-69
lines changed

doc/changelog.d/1633.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
interference repair tool

doc/changelog.d/1673.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shell methods

doc/changelog.d/1675.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
implementation of NURBS curves

doc/changelog.d/1683.test.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add unit tests for 3 repair tools

doc/changelog.d/1684.added.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
get assigned material

doc/changelog.d/1685.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
filter set export id to only CoreService based backends

doc/changelog.d/1690.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cleanup unsupported module

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dependencies = [
2929
"ansys-tools-visualization-interface>=0.2.6,<1",
3030
"attrs!=24.3.0",
3131
"beartype>=0.11.0,<0.20",
32+
"geomdl>=5,<6",
3233
"grpcio>=1.35.0,<1.68",
3334
"grpcio-health-checking>=1.45.0,<1.68",
3435
"numpy>=1.20.3,<3",
@@ -54,6 +55,7 @@ tests = [
5455
"ansys-tools-visualization-interface==0.8.1",
5556
"beartype==0.19.0",
5657
"docker==7.1.0",
58+
"geomdl==5.3.1",
5759
"grpcio==1.67.1",
5860
"grpcio-health-checking==1.67.1",
5961
"numpy==2.2.1",
@@ -82,6 +84,7 @@ doc = [
8284
"ansys-tools-visualization-interface==0.8.1",
8385
"beartype==0.19.0",
8486
"docker==7.1.0",
87+
"geomdl==5.3.1",
8588
"grpcio==1.67.1",
8689
"grpcio-health-checking==1.67.1",
8790
"ipyvtklink==0.2.3",

src/ansys/geometry/core/connection/conversions.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
from typing import TYPE_CHECKING
2525

26+
from pint import Quantity, UndefinedUnitError
27+
2628
from ansys.api.geometry.v0.models_pb2 import (
2729
Arc as GRPCArc,
2830
Circle as GRPCCircle,
@@ -32,6 +34,8 @@
3234
Frame as GRPCFrame,
3335
Geometries as GRPCGeometries,
3436
Line as GRPCLine,
37+
Material as GRPCMaterial,
38+
MaterialProperty as GRPCMaterialProperty,
3539
Matrix as GRPCMatrix,
3640
Plane as GRPCPlane,
3741
Point as GRPCPoint,
@@ -42,12 +46,17 @@
4246
TrimmedCurve as GRPCTrimmedCurve,
4347
TrimmedSurface as GRPCTrimmedSurface,
4448
)
49+
from ansys.geometry.core.materials.material import (
50+
Material,
51+
MaterialProperty,
52+
MaterialPropertyType,
53+
)
4554
from ansys.geometry.core.math.frame import Frame
4655
from ansys.geometry.core.math.matrix import Matrix44
4756
from ansys.geometry.core.math.plane import Plane
4857
from ansys.geometry.core.math.point import Point2D, Point3D
4958
from ansys.geometry.core.math.vector import UnitVector3D
50-
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS
59+
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS, UNITS
5160
from ansys.geometry.core.shapes.curves.circle import Circle
5261
from ansys.geometry.core.shapes.curves.curve import Curve
5362
from ansys.geometry.core.shapes.curves.ellipse import Ellipse
@@ -680,3 +689,37 @@ def line_to_grpc_line(line: Line) -> GRPCLine:
680689
start = line.origin
681690
end = line.origin + line.direction
682691
return GRPCLine(start=point3d_to_grpc_point(start), end=point3d_to_grpc_point(end))
692+
693+
694+
def grpc_material_to_material(material: GRPCMaterial) -> Material:
695+
"""Convert a material gRPC message to a ``Material`` class."""
696+
properties = []
697+
density = Quantity(0, UNITS.kg / UNITS.m**3)
698+
for property in material.material_properties:
699+
mp = grpc_material_property_to_material_property(property)
700+
properties.append(mp)
701+
if mp.type == MaterialPropertyType.DENSITY:
702+
density = mp.quantity
703+
704+
return Material(material.name, density, properties)
705+
706+
707+
def grpc_material_property_to_material_property(
708+
material_property: GRPCMaterialProperty,
709+
) -> MaterialProperty:
710+
"""Convert a material property gRPC message to a ``MaterialProperty`` class."""
711+
try:
712+
mp_type = MaterialPropertyType.from_id(material_property.id)
713+
except ValueError:
714+
mp_type = material_property.id
715+
716+
try:
717+
mp_quantity = Quantity(material_property.value, material_property.units)
718+
except (
719+
UndefinedUnitError,
720+
TypeError,
721+
):
722+
mp_quantity = material_property.value
723+
724+
mp = MaterialProperty(mp_type, material_property.display_name, mp_quantity)
725+
return mp

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

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@
5555
CombineMergeBodiesRequest,
5656
ImprintCurvesRequest,
5757
ProjectCurvesRequest,
58+
RemoveFacesRequest,
59+
ShellRequest,
5860
)
5961
from ansys.api.geometry.v0.commands_pb2_grpc import CommandsStub
6062
from ansys.geometry.core.connection.client import GrpcClient
6163
from ansys.geometry.core.connection.conversions import (
6264
frame_to_grpc_frame,
65+
grpc_material_to_material,
6366
plane_to_grpc_plane,
6467
point3d_to_grpc_point,
6568
sketch_shapes_to_grpc_geometries,
@@ -79,6 +82,7 @@
7982
from ansys.geometry.core.misc.auxiliary import get_design_from_body
8083
from ansys.geometry.core.misc.checks import (
8184
check_type,
85+
check_type_all_elements_in_iterable,
8286
ensure_design_is_active,
8387
min_backend_version,
8488
)
@@ -254,6 +258,17 @@ def assign_material(self, material: Material) -> None:
254258
"""
255259
return
256260

261+
@abstractmethod
262+
def get_assigned_material(self) -> Material:
263+
"""Get the assigned material of the body.
264+
265+
Returns
266+
-------
267+
Material
268+
Material assigned to the body.
269+
"""
270+
return
271+
257272
@abstractmethod
258273
def add_midsurface_thickness(self, thickness: Quantity) -> None:
259274
"""Add a mid-surface thickness to a surface body.
@@ -555,6 +570,39 @@ def tessellate(self, merge: bool = False) -> Union["PolyData", "MultiBlock"]:
555570
"""
556571
return
557572

573+
@abstractmethod
574+
def shell_body(self, offset: Real) -> bool:
575+
"""Shell the body to the thickness specified.
576+
577+
Parameters
578+
----------
579+
offset : Real
580+
Shell thickness.
581+
582+
Returns
583+
-------
584+
bool
585+
``True`` when successful, ``False`` when failed.
586+
"""
587+
return
588+
589+
@abstractmethod
590+
def remove_faces(self, selection: Union["Face", list["Face"]], offset: Real) -> bool:
591+
"""Shell by removing a given set of faces.
592+
593+
Parameters
594+
----------
595+
selection : Face | List[Face]
596+
Face or faces to be removed.
597+
offset : Real
598+
Shell thickness.
599+
600+
Returns
601+
-------
602+
bool
603+
``True`` when successful, ``False`` when failed.
604+
"""
605+
558606
@abstractmethod
559607
def plot(
560608
self,
@@ -871,6 +919,13 @@ def assign_material(self, material: Material) -> None: # noqa: D102
871919
SetAssignedMaterialRequest(id=self._id, material=material.name)
872920
)
873921

922+
@property
923+
@protect_grpc
924+
def get_assigned_material(self) -> Material: # noqa: D102
925+
self._grpc_client.log.debug(f"Retrieving assigned material for body {self.id}.")
926+
material_response = self._bodies_stub.GetAssignedMaterial(self._grpc_id)
927+
return grpc_material_to_material(material_response)
928+
874929
@protect_grpc
875930
@check_input_types
876931
def add_midsurface_thickness(self, thickness: Quantity) -> None: # noqa: D102
@@ -1161,6 +1216,43 @@ def tessellate( # noqa: D102
11611216
else:
11621217
return comp
11631218

1219+
@protect_grpc
1220+
@check_input_types
1221+
def shell_body(self, offset: Real) -> bool: # noqa: D102
1222+
self._grpc_client.log.debug(f"Shelling body {self.id} to offset {offset}.")
1223+
1224+
result = self._commands_stub.Shell(
1225+
ShellRequest(
1226+
selection=self._grpc_id,
1227+
offset=offset,
1228+
)
1229+
)
1230+
1231+
return result.success
1232+
1233+
@protect_grpc
1234+
@reset_tessellation_cache
1235+
@check_input_types
1236+
def remove_faces(self, selection: Union["Face", list["Face"]], offset: Real) -> bool: # noqa: D102
1237+
selection: list[Face] = selection if isinstance(selection, list) else [selection]
1238+
check_type_all_elements_in_iterable(selection, Face)
1239+
1240+
# check if faces belong to this body
1241+
for face in selection:
1242+
if face.body.id != self.id:
1243+
raise ValueError(f"Face {face.id} does not belong to body {self.id}.")
1244+
1245+
self._grpc_client.log.debug(f"Removing faces to shell body {self.id}.")
1246+
1247+
result = self._commands_stub.RemoveFaces(
1248+
RemoveFacesRequest(
1249+
selection=[face._grpc_id for face in selection],
1250+
offset=offset,
1251+
)
1252+
)
1253+
1254+
return result.success
1255+
11641256
def plot( # noqa: D102
11651257
self,
11661258
merge: bool = True,
@@ -1389,6 +1481,11 @@ def volume(self) -> Quantity: # noqa: D102
13891481
def assign_material(self, material: Material) -> None: # noqa: D102
13901482
self._template.assign_material(material)
13911483

1484+
@property
1485+
@ensure_design_is_active
1486+
def get_assigned_material(self) -> Material: # noqa: D102
1487+
return self._template.get_assigned_material
1488+
13921489
@ensure_design_is_active
13931490
def add_midsurface_thickness(self, thickness: Quantity) -> None: # noqa: D102
13941491
self._template.add_midsurface_thickness(thickness)
@@ -1578,6 +1675,14 @@ def tessellate( # noqa: D102
15781675
) -> Union["PolyData", "MultiBlock"]:
15791676
return self._template.tessellate(merge, self.parent_component.get_world_transform())
15801677

1678+
@ensure_design_is_active
1679+
def shell_body(self, offset: Real) -> bool: # noqa: D102
1680+
return self._template.shell_body(offset)
1681+
1682+
@ensure_design_is_active
1683+
def remove_faces(self, selection: Union["Face", list["Face"]], offset: Real) -> bool: # noqa: D102
1684+
return self._template.remove_faces(selection, offset)
1685+
15811686
def plot( # noqa: D102
15821687
self,
15831688
merge: bool = True,

0 commit comments

Comments
 (0)