diff --git a/doc/changelog.d/952.added.md b/doc/changelog.d/952.added.md new file mode 100644 index 0000000000..b7e8642e75 --- /dev/null +++ b/doc/changelog.d/952.added.md @@ -0,0 +1 @@ +feat: Integrate geometry imports \ No newline at end of file diff --git a/examples/gallery/10_wheel_ground_contact_patch.py b/examples/gallery/10_wheel_ground_contact_patch.py index e11002185a..d53f244184 100644 --- a/examples/gallery/10_wheel_ground_contact_patch.py +++ b/examples/gallery/10_wheel_ground_contact_patch.py @@ -100,13 +100,13 @@ ################### # Visualize results -# ================= +# ~~~~~~~~~~~~~~~~~ # .. code-block:: python # # display = PrimePlotter() # display.plot(model, scope=prime.ScopeDefinition(model, label_expression="ground, wheel")) # display.show() - +# print(model) ############################################################################### @@ -167,8 +167,8 @@ # model, scope=prime.ScopeDefinition(model, label_expression="ground, patch*, wheel") # ) # display.show() - -############################################################################### +# +####################### # Wrap the fluid region # ~~~~~~~~~~~~~~~~~~~~~ # The largest internal region in this instance is the fluid region around the wheel. @@ -192,7 +192,7 @@ ######################### # Open a pyvistaqt window -# ======================= +# ~~~~~~~~~~~~~~~~~~~~~~~ # .. code-block:: python # # display = PrimePlotter() @@ -201,7 +201,7 @@ # scope=prime.ScopeDefinition(model, label_expression="ground, patch*, wheel"), update=True # ) # display.show() - +# print(model) ############################################################################### diff --git a/examples/gallery/12_import_from_pygeometry.py b/examples/gallery/12_import_from_pygeometry.py new file mode 100644 index 0000000000..ffb2c2d0b4 --- /dev/null +++ b/examples/gallery/12_import_from_pygeometry.py @@ -0,0 +1,98 @@ +# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""" +.. _ref_pygeometry_import: + +================================= +Import a geometry from PyGeometry +================================= + +**Summary**: This example demonstrates how to create a simple geometry using +PyGeometry and import it into PyPrimeMesh. + + + +Procedure +~~~~~~~~~ +#. Launch Ansys Prime Server. +#. Create a CAD geometry with PyGeometry. +#. Import the geometry into PyPrimeMesh. +#. Exit the PyPrimeMesh session. + + + +Create the geometry +~~~~~~~~~~~~~~~~~~~ +First we create a simple geometry using PyGeometry. The geometry is a plate +with a hole in the center: + +.. code-block:: python + + from pint import Quantity + + from ansys.geometry.core import launch_modeler + from ansys.geometry.core.math import Point2D + from ansys.geometry.core.misc import UNITS + from ansys.geometry.core.sketch import Sketch + from ansys.geometry.core.math import Point2D + + sketch = Sketch() + ( + sketch.segment(Point2D([-4, 5], unit=UNITS.m), Point2D([4, 5], unit=UNITS.m)) + .segment_to_point(Point2D([4, -5], unit=UNITS.m)) + .segment_to_point(Point2D([-4, -5], unit=UNITS.m)) + .segment_to_point(Point2D([-4, 5], unit=UNITS.m)) + .box(Point2D([0, 0], unit=UNITS.m), Quantity(3, UNITS.m), Quantity(3, UNITS.m)) + ) + modeler = launch_modeler(hidden=True) + design = modeler.create_design("ExtrudedPlateNoHoles") + body = design.extrude_sketch(f"PlateLayer", sketch, Quantity(2, UNITS.m)) + +Import the geometry into PyPrimeMesh +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once the geometry is created, we can pass the Design object to PyPrimeMesh to +create a mesh: + +.. code-block:: python + + import ansys.meshing.prime as prime + from ansys.meshing.prime.graphics.plotter import PrimePlotter + + prime_client = prime.launch_prime() + model = prime_client.model + mesh_util = prime.lucid.Mesh(model=model) + mesh_util.from_geometry(design) + + +Mesh the geometry and display it +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +With the geometry imported, we can now mesh it and display the mesh: + +.. code-block:: python + + mesh_util.surface_mesh(min_size=0.1, max_size=0.5) + display = PrimePlotter() + display.plot(model) + display.show() + modeler.close() +""" diff --git a/pyproject.toml b/pyproject.toml index 632ebc3cfa..a690404545 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,9 @@ dependencies = [ graphics = [ "ansys-tools-visualization-interface>=0.4.7,<1", ] +pygeometry = [ + "ansys-geometry-core>=0.7.6,<1", +] tests = [ "ansys-tools-visualization-interface==0.6.0", "pytest==8.3.4", @@ -55,6 +58,7 @@ doc = [ ] all = [ "ansys-tools-visualization-interface>=0.2.6,<1", + "ansys-geometry-core>=0.7.6,<1", ] [project.urls] diff --git a/src/ansys/meshing/prime/lucid/mesh_util.py b/src/ansys/meshing/prime/lucid/mesh_util.py index 0788d0b042..0975d551bc 100644 --- a/src/ansys/meshing/prime/lucid/mesh_util.py +++ b/src/ansys/meshing/prime/lucid/mesh_util.py @@ -23,6 +23,7 @@ """Module for meshing utility functions.""" import enum import os +import tempfile from typing import Iterable, List import ansys.meshing.prime as prime @@ -31,6 +32,18 @@ from .utils import check_name_pattern +class ImportTypes(enum.Enum): + """Allowed geometry import types.""" + + PMDB = 0 + FMD = 1 + IGES = 2 + STEP = 3 + PARA_BIN = 4 + PARA_TEXT = 5 + SCDOCX = 6 + + class LabelToZoneMethod(enum.IntEnum): """Provides for creating zones from labels.""" @@ -69,6 +82,34 @@ def __init__(self, model: prime.Model): self._model = model self._logger = model.python_logger + def from_geometry( + self, design: "ansys.geometry.core.Design", import_type: ImportTypes = ImportTypes.FMD + ): + """Import geometry from an Ansys Design object. + + Parameters + ---------- + design : ansys.geometry.core.Design + Ansys Design object to import geometry from. + import_type : ImportTypes, optional + Type of import. The default is ImportTypes.FMD. + """ + with tempfile.TemporaryDirectory() as tmpdir: + file_path = os.path.join(tmpdir) + if import_type == ImportTypes.FMD: + design.export_to_fmd(file_path) + elif import_type == ImportTypes.IGES: + design.export_to_iges(file_path) + elif import_type == ImportTypes.STEP: + design.export_to_step(file_path) + elif import_type == ImportTypes.PARA_BIN: + design.export_to_parasolid_bin(file_path) + elif import_type == ImportTypes.PARA_TEXT: + design.export_to_parasolid_text(file_path) + elif import_type == ImportTypes.SCDOCX: + design.export_to_scdocx(file_path) + self.read(str(file_path)) + def read( self, file_name: str, append: bool = False, cad_reader_route: prime.CadReaderRoute = None ):