Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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/2046.test.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add more tests and update some tests
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,14 @@ def find_and_fix_stitch_faces(self, **kwargs) -> dict: # noqa: D102

from ansys.api.geometry.v0.repairtools_pb2 import FindStitchFacesRequest

from ..base.conversions import from_measurement_to_server_length

# Create the request - assumes all inputs are valid and of the proper type
request = FindStitchFacesRequest(
faces=kwargs["body_ids"],
maximum_distance=DoubleValue(value=kwargs["max_distance"])
maximum_distance=DoubleValue(
value=from_measurement_to_server_length(kwargs["max_distance"])
)
if kwargs["max_distance"] is not None
else None,
allow_multiple_bodies=BoolValue(value=kwargs["allow_multiple_bodies"]),
Expand Down
Binary file modified tests/integration/files/MissingFaces_AngleDistance.scdocx
Binary file not shown.
Binary file not shown.
Binary file removed tests/integration/files/stitch_1200_bodies.dsco
Binary file not shown.
Binary file added tests/integration/files/stitch_300_bodies.dsco
Binary file not shown.
50 changes: 50 additions & 0 deletions tests/integration/test_prepare_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ def test_remove_rounds(modeler: Modeler):
result = modeler.prepare_tools.remove_rounds(roundfaces)
assert len(design.bodies[0].faces) == 6
assert result is True
result = modeler.prepare_tools.remove_rounds([design.bodies[0].faces[0]])
# test removing a face that is not a round
assert result is True # remove round always returns True for success
result = modeler.prepare_tools.remove_rounds(None)
assert result == []


def test_share_topology(modeler: Modeler):
Expand All @@ -97,6 +102,8 @@ def test_share_topology(modeler: Modeler):
edges += len(body.edges)
assert faces == 13
assert edges == 27
result = modeler.prepare_tools.share_topology(None)
assert result is False


def test_enhanced_share_topology(modeler: Modeler):
Expand All @@ -113,6 +120,8 @@ def test_enhanced_share_topology(modeler: Modeler):
result = modeler.prepare_tools.enhanced_share_topology(design.bodies, 0.000554167, True)
assert result.found == 14
assert result.repaired == 14
result = modeler.prepare_tools.enhanced_share_topology(None, 0, False)
assert result.found == 0


def test_detect_logos(modeler: Modeler):
Expand All @@ -132,6 +141,12 @@ def test_detect_logos(modeler: Modeler):
success = modeler.prepare_tools.find_and_remove_logos(max_height=0.005)
assert success is True
assert len(body.faces) == 42
result = modeler.prepare_tools.find_and_remove_logos(None, min_height=0.001, max_height=0.005)
assert result is False
result = modeler.prepare_tools.find_and_remove_logos(
design.components[0].bodies, min_height=0.001, max_height=0.005
)
assert result is False


def test_detect_and_fix_logo_as_problem_area(modeler: Modeler):
Expand All @@ -155,3 +170,38 @@ def test_detect_and_fix_logo_as_problem_area(modeler: Modeler):
result.fix()
assert success is False
assert len(design.components[0].bodies[2].faces) == 42


def test_volume_extract_bad_faces(modeler: Modeler):
"""Test a volume extract with bad faces."""
design = modeler.open_file(FILES_DIR / "BoxWithRound.scdocx")

body = design.bodies[0]
inside_faces = []
sealing_faces = [body.faces[1], body.faces[4]]
created_bodies = modeler.prepare_tools.extract_volume_from_faces(sealing_faces, inside_faces)
assert len(created_bodies) == 0
inside_faces = [body.faces[6]]
sealing_faces = []
created_bodies = modeler.prepare_tools.extract_volume_from_faces(sealing_faces, inside_faces)
assert len(created_bodies) == 0
inside_faces = [body.faces[0]]
sealing_faces = [body.faces[1]]
created_bodies = modeler.prepare_tools.extract_volume_from_faces(sealing_faces, inside_faces)
assert len(created_bodies) == 0


def test_volume_extract_bad_edges(modeler: Modeler):
"""Test a volume extract with bad edges."""
design = modeler.open_file(FILES_DIR / "BoxWithRound.scdocx")
body = design.bodies[0]
sealing_edges = []
created_bodies = modeler.prepare_tools.extract_volume_from_edge_loops(
sealing_edges,
)
assert len(created_bodies) == 0
sealing_edges = [body.edges[0], body.edges[1]]
created_bodies = modeler.prepare_tools.extract_volume_from_edge_loops(
sealing_edges,
)
assert len(created_bodies) == 0
236 changes: 221 additions & 15 deletions tests/integration/test_repair_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,24 @@
# SOFTWARE.
""" "Testing of repair tools."""

import pytest

from ansys.geometry.core.modeler import Modeler
from ansys.geometry.core.tools.check_geometry import InspectResult
from ansys.geometry.core.tools.problem_areas import (
DuplicateFaceProblemAreas,
ExtraEdgeProblemAreas,
InterferenceProblemAreas,
MissingFaceProblemAreas,
ProblemArea,
ShortEdgeProblemAreas,
SmallFaceProblemAreas,
SplitEdgeProblemAreas,
StitchFaceProblemAreas,
UnsimplifiedFaceProblemAreas,
)
from ansys.geometry.core.tools.repair_tool_message import RepairToolMessage
from ansys.geometry.core.tools.repair_tools import RepairTools

from .conftest import FILES_DIR

Expand Down Expand Up @@ -219,7 +236,7 @@ def test_fix_small_face(modeler: Modeler):
def test_find_stitch_faces(modeler: Modeler):
"""Test to read geometry and find it's stitch face problem areas."""
design = modeler.open_file(FILES_DIR / "stitch_before.scdocx")
problem_areas = modeler.repair_tools.find_stitch_faces(design.bodies)
problem_areas = modeler.repair_tools.find_stitch_faces(design.bodies, 0.0001)
assert len(problem_areas) == 1


Expand Down Expand Up @@ -283,28 +300,28 @@ def test_fix_interference(modeler: Modeler):

def test_find_and_fix_stitch_faces(modeler: Modeler):
"""Test to find and fix stitch faces and validate that we get a solid."""
design = modeler.open_file(FILES_DIR / "stitch_1200_bodies.dsco")
assert len(design.bodies) == 3600
design = modeler.open_file(FILES_DIR / "stitch_300_bodies.dsco")
assert len(design.bodies) == 900

stitch_faces = modeler.repair_tools.find_and_fix_stitch_faces(design.bodies)
stitch_faces = modeler.repair_tools.find_and_fix_stitch_faces(design.bodies, 0.0001)
assert stitch_faces.found == 1
assert stitch_faces.repaired == 1

assert len(design.bodies) == 1200
assert len(design.bodies) == 300


def test_find_and_fix_stitch_faces_comprehensive(modeler: Modeler):
"""Test to find and fix stitch faces and validate that we get a solid."""
design = modeler.open_file(FILES_DIR / "stitch_1200_bodies.dsco")
assert len(design.bodies) == 3600
design = modeler.open_file(FILES_DIR / "stitch_300_bodies.dsco")
assert len(design.bodies) == 900

stitch_faces = modeler.repair_tools.find_and_fix_stitch_faces(
design.bodies, comprehensive_result=True
)
assert stitch_faces.found == 1200
assert stitch_faces.repaired == 1200
assert stitch_faces.found == 300
assert stitch_faces.repaired == 300

assert len(design.bodies) == 1200
assert len(design.bodies) == 300


def test_find_and_fix_duplicate_faces(modeler: Modeler):
Expand Down Expand Up @@ -393,14 +410,16 @@ def test_find_and_fix_missing_faces(modeler: Modeler):
def test_find_and_fix_missing_faces_angle_distance(modeler: Modeler):
"""Test to read geometry, find and fix missing faces specify angle and distance."""
design = modeler.open_file(FILES_DIR / "MissingFaces_AngleDistance.scdocx")
assert len(design.bodies) == 1
assert len(design.bodies[0].faces) == 11
missing_faces = modeler.repair_tools.find_missing_faces(design.bodies, 0.785398, 0.0005)
assert len(design.bodies) == 4
total_faces = sum(len(body.faces) for body in design.bodies)
assert total_faces == 22
missing_faces = modeler.repair_tools.find_missing_faces(design.bodies, 0.698131, 0.015)
assert len(missing_faces) == 4
for face in missing_faces:
face.fix()
assert len(design.bodies) == 1
assert len(design.bodies[0].faces) == 15
assert len(design.bodies) == 4
total_faces = sum(len(body.faces) for body in design.bodies)
assert total_faces == 26


def test_find_and_fix_short_edges_problem_areas(modeler: Modeler):
Expand Down Expand Up @@ -560,3 +579,190 @@ def test_find_and_fix_simplify(modeler: Modeler):
assert result
assert result.found == 23
assert result.repaired == 23 # There is a SC bug where success is always true


def test_design_import_check_geometry(modeler: Modeler):
"""Test importing a design with check geometry."""
# Open the design
design = modeler.open_file(FILES_DIR / "Nonmanifold_CheckGeometry.scdocx")
inspect_results = modeler.repair_tools.inspect_geometry(design.bodies)

# Assert the number of inspect results and issues
assert len(inspect_results) == 1
issues = inspect_results[0].issues
assert len(issues) == 5

# Expected messages, message IDs, and message types
expected_data = [
{
"message": "Geometry intersects itself.",
"message_id": 26,
"message_type": 3,
"faces": 0,
"edges": 0,
},
{
"message": "Geometry intersects itself.",
"message_id": 26,
"message_type": 3,
"faces": 0,
"edges": 0,
},
{
"message": "Geometry intersects itself.",
"message_id": 26,
"message_type": 3,
"faces": 0,
"edges": 0,
},
{
"message": "Geometry intersects itself.",
"message_id": 26,
"message_type": 3,
"faces": 0,
"edges": 0,
},
{
"message": "Face illegally intersects or abuts another face.",
"message_id": 25,
"message_type": 3,
"faces": 2,
"edges": 0,
},
]

# Convert issues and expected data to sets of tuples for comparison
actual_data = {
(
issue.message,
issue.message_id,
issue.message_type,
len(issue.faces),
len(issue.edges),
)
for issue in issues
}

expected_data_set = {
(
item["message"],
item["message_id"],
item["message_type"],
item["faces"],
item["edges"],
)
for item in expected_data
}

# Assert that the actual data matches the expected data regardless of order
assert actual_data == expected_data_set

# Test repair functionality
repair_message = inspect_results[0].repair()
assert repair_message.success is True
assert repair_message.created_bodies == []
assert repair_message.modified_bodies == []


def test_repair_no_body(modeler: Modeler):
"""Test the repair method when body is None."""
grpc_client = modeler.client
# Create an instance of InspectResult with body set to None
inspect_result = InspectResult(grpc_client=grpc_client, body=None, issues=[])
# Call the repair method
repair_message = inspect_result.repair()
# Assert the returned RepairToolMessage
assert isinstance(repair_message, RepairToolMessage)
assert repair_message.success is False
assert repair_message.created_bodies == []
assert repair_message.modified_bodies == []


def test_problem_area_fix_not_implemented(modeler: Modeler):
"""Test that the fix method in the ProblemArea base class raises NotImplementedError."""
grpc_client = modeler.client
# Create an instance of ProblemArea
problem_area = ProblemArea(id="123", grpc_client=grpc_client)
# Assert that calling fix raises NotImplementedError
with pytest.raises(
NotImplementedError, match="Fix method is not implemented in the base class."
):
problem_area.fix()


@pytest.mark.parametrize(
"problem_area_class, kwargs",
[
(DuplicateFaceProblemAreas, {"faces": []}),
(MissingFaceProblemAreas, {"edges": []}),
(ExtraEdgeProblemAreas, {"edges": []}),
(ShortEdgeProblemAreas, {"edges": []}),
(SmallFaceProblemAreas, {"faces": []}),
(SplitEdgeProblemAreas, {"edges": []}),
(StitchFaceProblemAreas, {"bodies": []}),
(UnsimplifiedFaceProblemAreas, {"faces": []}),
(InterferenceProblemAreas, {"bodies": []}),
],
)
def test_problem_area_fix_no_data(modeler: Modeler, problem_area_class, kwargs):
"""Test the fix method for various ProblemArea subclasses when required attributes are empty."""
grpc_client = modeler.client
problem_area = problem_area_class(id="123", grpc_client=grpc_client, **kwargs)
repair_message = problem_area.fix()
assert isinstance(repair_message, RepairToolMessage)
assert repair_message.success is False
assert repair_message.created_bodies == []
assert repair_message.modified_bodies == []


@pytest.mark.parametrize(
"method_name",
[
"find_split_edges",
"find_extra_edges",
"find_inexact_edges",
"find_short_edges",
"find_duplicate_faces",
"find_missing_faces",
"find_small_faces",
"find_interferences",
],
)
def test_repair_tools_no_bodies(modeler: Modeler, method_name):
"""Test RepairTools methods when bodies is empty or None."""
grpc_client = modeler.client
repair_tools = RepairTools(grpc_client, modeler)
method = getattr(repair_tools, method_name)

# Test with an empty list of bodies
result = method(bodies=[])
assert result == []

# Test with None as bodies
result = method(bodies=None)
assert result == []


@pytest.mark.parametrize(
"method_name",
[
"find_and_fix_short_edges",
"find_and_fix_extra_edges",
"find_and_fix_split_edges",
"find_and_fix_simplify",
],
)
def test_repair_tools_find_and_fix_no_bodies(modeler: Modeler, method_name):
"""Test RepairTools find_and_fix methods when bodies is empty or None."""
grpc_client = modeler.client
repair_tools = RepairTools(grpc_client, modeler)
method = getattr(repair_tools, method_name)

# Test with an empty list of bodies
result = method(bodies=[])
assert isinstance(result, RepairToolMessage)
assert result.success is False
assert result.created_bodies == []
assert result.modified_bodies == []
assert result.found == 0
assert result.repaired == 0
Loading