Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c364e66
added the client side implementations of sweeping chain and sweeping …
dastan-ansys Mar 13, 2024
39ba4a5
Adding changelog entry: 1056.added.md
pyansys-ci-bot Mar 13, 2024
f6c1b27
Adding changelog entry: 1056.added.md
pyansys-ci-bot Mar 13, 2024
4434fa9
Merge branch 'main' into feat/sweep-chain-and-profile
RobPasMue Mar 14, 2024
a443fb6
Update src/ansys/geometry/core/designer/component.py
dastan-ansys Mar 14, 2024
6aee11a
implemented suggestions from initial review
dastan-ansys Mar 14, 2024
b4ede77
Merge branch 'feat/sweep-chain-and-profile' of https://github.com/pya…
dastan-ansys Mar 14, 2024
6b11e65
for some reason the is_surface did not update
dastan-ansys Mar 14, 2024
b012fb5
Update pyproject.toml
jonahrb Mar 14, 2024
829d18c
Merge branch 'main' into feat/sweep-chain-and-profile
jonahrb Mar 14, 2024
61963f2
Update component.py
dastan-ansys Mar 14, 2024
7c4493f
Add trim() method to curve/surface
jonahrb Mar 14, 2024
641f03b
Merge branch 'feat/sweep-chain-and-profile' of https://github.com/ans…
jonahrb Mar 14, 2024
30ac7b3
added unit tests for sweeps
dastan-ansys Mar 15, 2024
66db338
volume is body property not face
dastan-ansys Mar 15, 2024
33cb4d1
fix is_surface assignment, fix and move tests
jonahrb Mar 16, 2024
84b2739
Update test_design.py
jonahrb Mar 16, 2024
72b3770
Adding changelog entry: 1056.added.md
pyansys-ci-bot Mar 18, 2024
55fe98d
Update src/ansys/geometry/core/shapes/surfaces/surface.py
jonahrb Mar 18, 2024
044306c
Update tests/integration/test_design.py
jonahrb Mar 18, 2024
2c0a3dc
Update tests/integration/test_design.py
jonahrb Mar 18, 2024
0ef7c4a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 18, 2024
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
1 change: 1 addition & 0 deletions doc/changelog.d/1056.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
feat: sweeping chains and profiles
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ classifiers = [
]

dependencies = [
"ansys-api-geometry==0.3.12",
"ansys-api-geometry==0.3.13",
"ansys-tools-path>=0.3,<1",
"beartype>=0.11.0,<1",
"google-api-python-client>=1.7.11,<3",
Expand Down
5 changes: 0 additions & 5 deletions src/ansys/geometry/core/connection/conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,16 +583,11 @@ def trimmed_curve_to_grpc_trimmed_curve(curve: "TrimmedCurve") -> GRPCTrimmedCur
Geometry service gRPC ``TrimmedCurve`` message.
"""
curve_geometry = curve_to_grpc_curve(curve.geometry)
start = point3d_to_grpc_point(curve.start)
end = point3d_to_grpc_point(curve.end)
i_start = curve.interval.start
i_end = curve.interval.end

return GRPCTrimmedCurve(
curve=curve_geometry,
start=start,
end=end,
interval_start=i_start,
interval_end=i_end,
length=curve.length.m,
)
104 changes: 104 additions & 0 deletions src/ansys/geometry/core/designer/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
CreateExtrudedBodyRequest,
CreatePlanarBodyRequest,
CreateSphereBodyRequest,
CreateSweepingChainRequest,
CreateSweepingProfileRequest,
TranslateRequest,
)
from ansys.api.geometry.v0.bodies_pb2_grpc import BodiesStub
Expand All @@ -53,6 +55,7 @@
plane_to_grpc_plane,
point3d_to_grpc_point,
sketch_shapes_to_grpc_geometries,
trimmed_curve_to_grpc_trimmed_curve,
unit_vector_to_grpc_direction,
)
from ansys.geometry.core.designer.beam import Beam, BeamProfile
Expand All @@ -69,6 +72,7 @@
from ansys.geometry.core.math.vector import UnitVector3D, Vector3D
from ansys.geometry.core.misc.checks import ensure_design_is_active, min_backend_version
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS, Angle, Distance
from ansys.geometry.core.shapes.curves.trimmed_curve import TrimmedCurve
from ansys.geometry.core.sketch.sketch import Sketch
from ansys.geometry.core.typing import Real

Expand Down Expand Up @@ -485,6 +489,106 @@ def extrude_sketch(
self._master_component.part.bodies.append(tb)
return Body(response.id, response.name, self, tb)

@min_backend_version(24, 2, 0)
@protect_grpc
@check_input_types
@ensure_design_is_active
def sweep_sketch(
self,
name: str,
sketch: Sketch,
path: List[TrimmedCurve],
) -> Body:
"""
Create a body by sweeping a planar profile along a path.

Notes
-----
The newly created body is placed under this component within the design assembly.

Parameters
----------
name : str
User-defined label for the new solid body.
sketch : Sketch
Two-dimensional sketch source for the extrusion.
path : List[TrimmedCurve]
The path to sweep the profile along.

Returns
-------
Body
Created body from the given sketch.
"""
# Convert each ``TrimmedCurve`` in path to equivalent gRPC type
path_grpc = []
for tc in path:
path_grpc.append(trimmed_curve_to_grpc_trimmed_curve(tc))

request = CreateSweepingProfileRequest(
name=name,
parent=self.id,
plane=plane_to_grpc_plane(sketch._plane),
geometries=sketch_shapes_to_grpc_geometries(sketch._plane, sketch.edges, sketch.faces),
path=path_grpc,
)

self._grpc_client.log.debug(f"Creating a sweeping profile on {self.id}. Creating body...")
response = self._bodies_stub.CreateSweepingProfile(request)
tb = MasterBody(response.master_id, name, self._grpc_client, is_surface=False)
self._master_component.part.bodies.append(tb)
return Body(response.id, response.name, self, tb)

@min_backend_version(24, 2, 0)
@protect_grpc
@check_input_types
@ensure_design_is_active
def sweep_chain(
self,
name: str,
path: List[TrimmedCurve],
chain: List[TrimmedCurve],
) -> Body:
"""
Create a body by sweeping a chain of curves along a path.

Notes
-----
The newly created body is placed under this component within the design assembly.

Parameters
----------
name : str
User-defined label for the new solid body.
sketch : Sketch
Two-dimensional sketch source for the extrusion.
path : List[TrimmedCurve]
The path to sweep the chain along.
chain : List[TrimmedCurve]
A chain of trimmed curves.

Returns
-------
Body
Created body from the given sketch.
"""
# Convert each ``TrimmedCurve`` in path and chain to equivalent gRPC types
path_grpc = [trimmed_curve_to_grpc_trimmed_curve(tc) for tc in path]
chain_grpc = [trimmed_curve_to_grpc_trimmed_curve(tc) for tc in chain]

request = CreateSweepingChainRequest(
name=name,
parent=self.id,
path=path_grpc,
chain=chain_grpc,
)

self._grpc_client.log.debug(f"Creating a sweeping chain on {self.id}. Creating body...")
response = self._bodies_stub.CreateSweepingChain(request)
tb = MasterBody(response.master_id, name, self._grpc_client, is_surface=True)
self._master_component.part.bodies.append(tb)
return Body(response.id, response.name, self, tb)

@protect_grpc
@check_input_types
@ensure_design_is_active
Expand Down
10 changes: 8 additions & 2 deletions src/ansys/geometry/core/designer/face.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from ansys.geometry.core.math.vector import UnitVector3D
from ansys.geometry.core.misc.checks import ensure_design_is_active
from ansys.geometry.core.misc.measurements import DEFAULT_UNITS
from ansys.geometry.core.shapes.box_uv import BoxUV
from ansys.geometry.core.shapes.curves.trimmed_curve import TrimmedCurve
from ansys.geometry.core.shapes.parameterization import Interval
from ansys.geometry.core.shapes.surfaces.trimmed_surface import (
Expand Down Expand Up @@ -203,12 +204,17 @@ def shape(self) -> TrimmedSurface:
direction of the normal vector to ensure it is always facing outward.
"""
if self._shape is None:
self._grpc_client.log.debug("Requesting face properties from server.")

surface_response = self._faces_stub.GetSurface(self._grpc_id)
geometry = grpc_surface_to_surface(surface_response, self._surface_type)
box = self._faces_stub.GetBoxUV(self._grpc_id)
box_uv = BoxUV(Interval(box.start_u, box.end_u), Interval(box.start_v, box.end_v))

self._shape = (
ReversedTrimmedSurface(self, geometry)
ReversedTrimmedSurface(geometry, box_uv)
if self.is_reversed
else TrimmedSurface(self, geometry)
else TrimmedSurface(geometry, box_uv)
)
return self._shape

Expand Down
26 changes: 25 additions & 1 deletion src/ansys/geometry/core/shapes/curves/curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@
"""Provides the ``Curve`` class."""
from abc import ABC, abstractmethod

from beartype.typing import TYPE_CHECKING

from ansys.geometry.core.math.matrix import Matrix44
from ansys.geometry.core.math.point import Point3D
from ansys.geometry.core.shapes.curves.curve_evaluation import CurveEvaluation
from ansys.geometry.core.shapes.parameterization import Parameterization
from ansys.geometry.core.shapes.parameterization import Interval, Parameterization
from ansys.geometry.core.typing import Real

if TYPE_CHECKING: # pragma: no cover
from ansys.geometry.core.shapes.curves.trimmed_curve import TrimmedCurve


class Curve(ABC):
"""Provides the abstract base class representing a 3D curve."""
Expand Down Expand Up @@ -74,3 +79,22 @@ def project_point(self, point: Point3D) -> CurveEvaluation:
This method returns the evaluation at the closest point.
"""
return

def trim(self, interval: Interval) -> "TrimmedCurve":
"""
Trim this curve by bounding it with an interval.

Returns
-------
TrimmedCurve
The resulting bounded curve.
"""
from ansys.geometry.core.shapes.curves.trimmed_curve import TrimmedCurve

return TrimmedCurve(
self,
self.evaluate(interval.start).position,
self.evaluate(interval.end).position,
interval,
None, # TODO: calculate length on client?
)
19 changes: 18 additions & 1 deletion src/ansys/geometry/core/shapes/surfaces/surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@
"""Provides the ``Surface`` class."""
from abc import ABC, abstractmethod

from beartype.typing import Tuple
from beartype.typing import TYPE_CHECKING, Tuple

from ansys.geometry.core.math.matrix import Matrix44
from ansys.geometry.core.math.point import Point3D
from ansys.geometry.core.shapes.box_uv import BoxUV
from ansys.geometry.core.shapes.parameterization import Parameterization, ParamUV
from ansys.geometry.core.shapes.surfaces.surface_evaluation import SurfaceEvaluation

if TYPE_CHECKING: # pragma: no cover
from ansys.geometry.core.shapes.surfaces.trimmed_surface import TrimmedSurface


class Surface(ABC):
"""Provides the abstract base class for a 3D surface."""
Expand Down Expand Up @@ -75,3 +79,16 @@ def project_point(self, point: Point3D) -> SurfaceEvaluation:
This method returns the evaluation at the closest point.
"""
return

def trim(self, box_uv: BoxUV) -> "TrimmedSurface":
"""
Trim this surface by bounding it with a BoxUV.

Returns
-------
TrimmedSurface
The resulting bounded surface.
"""
from ansys.geometry.core.shapes.surfaces.trimmed_surface import TrimmedSurface

return TrimmedSurface(self, box_uv)
26 changes: 7 additions & 19 deletions src/ansys/geometry/core/shapes/surfaces/trimmed_surface.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,14 @@
# SOFTWARE.
"""Provides the ``TrimmedSurface`` class."""

from beartype.typing import TYPE_CHECKING

from ansys.geometry.core.math.point import Point3D
from ansys.geometry.core.math.vector import UnitVector3D
from ansys.geometry.core.shapes.box_uv import BoxUV
from ansys.geometry.core.shapes.parameterization import Interval, ParamUV
from ansys.geometry.core.shapes.parameterization import ParamUV
from ansys.geometry.core.shapes.surfaces.surface import Surface
from ansys.geometry.core.shapes.surfaces.surface_evaluation import SurfaceEvaluation
from ansys.geometry.core.typing import Real

if TYPE_CHECKING:
from ansys.geometry.core.designer.face import Face


class TrimmedSurface:
"""
Expand All @@ -50,15 +45,10 @@ class TrimmedSurface:
Underlying mathematical representation of the surface.
"""

def __init__(self, face: "Face", geometry: Surface):
def __init__(self, geometry: Surface, box_uv: BoxUV):
"""Initialize an instance of a trimmed surface."""
self._face = face
self._geometry = geometry

@property
def face(self) -> "Face":
"""Face the trimmed surface belongs to."""
return self._face
self._box_uv = box_uv

@property
def geometry(self) -> Surface:
Expand All @@ -68,9 +58,7 @@ def geometry(self) -> Surface:
@property
def box_uv(self) -> BoxUV:
"""Bounding BoxUV of the surface."""
self._face._grpc_client.log.debug("Requesting box UV from server.")
box = self._face._faces_stub.GetBoxUV(self.face._grpc_id)
return BoxUV(Interval(box.start_u, box.end_u), Interval(box.start_v, box.end_v))
return self._box_uv

def get_proportional_parameters(self, param_uv: ParamUV) -> ParamUV:
"""
Expand Down Expand Up @@ -154,7 +142,7 @@ def evaluate_proportion(self, u: Real, v: Real) -> SurfaceEvaluation:
)
)

# TODO: perimeter
# TODO: perimeter, area?


class ReversedTrimmedSurface(TrimmedSurface):
Expand All @@ -172,9 +160,9 @@ class ReversedTrimmedSurface(TrimmedSurface):
Underlying mathematical representation of the surface.
"""

def __init__(self, face: "Face", geometry: Surface):
def __init__(self, geometry: Surface, box_uv: BoxUV):
"""Initialize an instance of a reversed trimmed surface."""
super().__init__(face, geometry)
super().__init__(geometry, box_uv)

def normal(self, u: Real, v: Real) -> UnitVector3D: # noqa: D102
return -self.evaluate_proportion(u, v).normal
Expand Down
Loading