|
21 | 21 | # SOFTWARE. |
22 | 22 | """ "Testing of repair tools.""" |
23 | 23 |
|
| 24 | +import pytest |
| 25 | + |
24 | 26 | from ansys.geometry.core.modeler import Modeler |
| 27 | +from ansys.geometry.core.tools.check_geometry import InspectResult |
| 28 | +from ansys.geometry.core.tools.problem_areas import ( |
| 29 | + DuplicateFaceProblemAreas, |
| 30 | + ExtraEdgeProblemAreas, |
| 31 | + InterferenceProblemAreas, |
| 32 | + MissingFaceProblemAreas, |
| 33 | + ProblemArea, |
| 34 | + ShortEdgeProblemAreas, |
| 35 | + SmallFaceProblemAreas, |
| 36 | + SplitEdgeProblemAreas, |
| 37 | + StitchFaceProblemAreas, |
| 38 | + UnsimplifiedFaceProblemAreas, |
| 39 | +) |
| 40 | +from ansys.geometry.core.tools.repair_tool_message import RepairToolMessage |
| 41 | +from ansys.geometry.core.tools.repair_tools import RepairTools |
25 | 42 |
|
26 | 43 | from .conftest import FILES_DIR |
27 | 44 |
|
@@ -219,7 +236,7 @@ def test_fix_small_face(modeler: Modeler): |
219 | 236 | def test_find_stitch_faces(modeler: Modeler): |
220 | 237 | """Test to read geometry and find it's stitch face problem areas.""" |
221 | 238 | design = modeler.open_file(FILES_DIR / "stitch_before.scdocx") |
222 | | - problem_areas = modeler.repair_tools.find_stitch_faces(design.bodies) |
| 239 | + problem_areas = modeler.repair_tools.find_stitch_faces(design.bodies, 0.0001) |
223 | 240 | assert len(problem_areas) == 1 |
224 | 241 |
|
225 | 242 |
|
@@ -283,28 +300,28 @@ def test_fix_interference(modeler: Modeler): |
283 | 300 |
|
284 | 301 | def test_find_and_fix_stitch_faces(modeler: Modeler): |
285 | 302 | """Test to find and fix stitch faces and validate that we get a solid.""" |
286 | | - design = modeler.open_file(FILES_DIR / "stitch_1200_bodies.dsco") |
287 | | - assert len(design.bodies) == 3600 |
| 303 | + design = modeler.open_file(FILES_DIR / "stitch_300_bodies.dsco") |
| 304 | + assert len(design.bodies) == 900 |
288 | 305 |
|
289 | | - stitch_faces = modeler.repair_tools.find_and_fix_stitch_faces(design.bodies) |
| 306 | + stitch_faces = modeler.repair_tools.find_and_fix_stitch_faces(design.bodies, 0.0001) |
290 | 307 | assert stitch_faces.found == 1 |
291 | 308 | assert stitch_faces.repaired == 1 |
292 | 309 |
|
293 | | - assert len(design.bodies) == 1200 |
| 310 | + assert len(design.bodies) == 300 |
294 | 311 |
|
295 | 312 |
|
296 | 313 | def test_find_and_fix_stitch_faces_comprehensive(modeler: Modeler): |
297 | 314 | """Test to find and fix stitch faces and validate that we get a solid.""" |
298 | | - design = modeler.open_file(FILES_DIR / "stitch_1200_bodies.dsco") |
299 | | - assert len(design.bodies) == 3600 |
| 315 | + design = modeler.open_file(FILES_DIR / "stitch_300_bodies.dsco") |
| 316 | + assert len(design.bodies) == 900 |
300 | 317 |
|
301 | 318 | stitch_faces = modeler.repair_tools.find_and_fix_stitch_faces( |
302 | 319 | design.bodies, comprehensive_result=True |
303 | 320 | ) |
304 | | - assert stitch_faces.found == 1200 |
305 | | - assert stitch_faces.repaired == 1200 |
| 321 | + assert stitch_faces.found == 300 |
| 322 | + assert stitch_faces.repaired == 300 |
306 | 323 |
|
307 | | - assert len(design.bodies) == 1200 |
| 324 | + assert len(design.bodies) == 300 |
308 | 325 |
|
309 | 326 |
|
310 | 327 | def test_find_and_fix_duplicate_faces(modeler: Modeler): |
@@ -393,14 +410,16 @@ def test_find_and_fix_missing_faces(modeler: Modeler): |
393 | 410 | def test_find_and_fix_missing_faces_angle_distance(modeler: Modeler): |
394 | 411 | """Test to read geometry, find and fix missing faces specify angle and distance.""" |
395 | 412 | design = modeler.open_file(FILES_DIR / "MissingFaces_AngleDistance.scdocx") |
396 | | - assert len(design.bodies) == 1 |
397 | | - assert len(design.bodies[0].faces) == 11 |
398 | | - missing_faces = modeler.repair_tools.find_missing_faces(design.bodies, 0.785398, 0.0005) |
| 413 | + assert len(design.bodies) == 4 |
| 414 | + total_faces = sum(len(body.faces) for body in design.bodies) |
| 415 | + assert total_faces == 22 |
| 416 | + missing_faces = modeler.repair_tools.find_missing_faces(design.bodies, 0.698131, 0.015) |
399 | 417 | assert len(missing_faces) == 4 |
400 | 418 | for face in missing_faces: |
401 | 419 | face.fix() |
402 | | - assert len(design.bodies) == 1 |
403 | | - assert len(design.bodies[0].faces) == 15 |
| 420 | + assert len(design.bodies) == 4 |
| 421 | + total_faces = sum(len(body.faces) for body in design.bodies) |
| 422 | + assert total_faces == 26 |
404 | 423 |
|
405 | 424 |
|
406 | 425 | def test_find_and_fix_short_edges_problem_areas(modeler: Modeler): |
@@ -560,3 +579,190 @@ def test_find_and_fix_simplify(modeler: Modeler): |
560 | 579 | assert result |
561 | 580 | assert result.found == 23 |
562 | 581 | assert result.repaired == 23 # There is a SC bug where success is always true |
| 582 | + |
| 583 | + |
| 584 | +def test_design_import_check_geometry(modeler: Modeler): |
| 585 | + """Test importing a design with check geometry.""" |
| 586 | + # Open the design |
| 587 | + design = modeler.open_file(FILES_DIR / "Nonmanifold_CheckGeometry.scdocx") |
| 588 | + inspect_results = modeler.repair_tools.inspect_geometry(design.bodies) |
| 589 | + |
| 590 | + # Assert the number of inspect results and issues |
| 591 | + assert len(inspect_results) == 1 |
| 592 | + issues = inspect_results[0].issues |
| 593 | + assert len(issues) == 5 |
| 594 | + |
| 595 | + # Expected messages, message IDs, and message types |
| 596 | + expected_data = [ |
| 597 | + { |
| 598 | + "message": "Geometry intersects itself.", |
| 599 | + "message_id": 26, |
| 600 | + "message_type": 3, |
| 601 | + "faces": 0, |
| 602 | + "edges": 0, |
| 603 | + }, |
| 604 | + { |
| 605 | + "message": "Geometry intersects itself.", |
| 606 | + "message_id": 26, |
| 607 | + "message_type": 3, |
| 608 | + "faces": 0, |
| 609 | + "edges": 0, |
| 610 | + }, |
| 611 | + { |
| 612 | + "message": "Geometry intersects itself.", |
| 613 | + "message_id": 26, |
| 614 | + "message_type": 3, |
| 615 | + "faces": 0, |
| 616 | + "edges": 0, |
| 617 | + }, |
| 618 | + { |
| 619 | + "message": "Geometry intersects itself.", |
| 620 | + "message_id": 26, |
| 621 | + "message_type": 3, |
| 622 | + "faces": 0, |
| 623 | + "edges": 0, |
| 624 | + }, |
| 625 | + { |
| 626 | + "message": "Face illegally intersects or abuts another face.", |
| 627 | + "message_id": 25, |
| 628 | + "message_type": 3, |
| 629 | + "faces": 2, |
| 630 | + "edges": 0, |
| 631 | + }, |
| 632 | + ] |
| 633 | + |
| 634 | + # Convert issues and expected data to sets of tuples for comparison |
| 635 | + actual_data = { |
| 636 | + ( |
| 637 | + issue.message, |
| 638 | + issue.message_id, |
| 639 | + issue.message_type, |
| 640 | + len(issue.faces), |
| 641 | + len(issue.edges), |
| 642 | + ) |
| 643 | + for issue in issues |
| 644 | + } |
| 645 | + |
| 646 | + expected_data_set = { |
| 647 | + ( |
| 648 | + item["message"], |
| 649 | + item["message_id"], |
| 650 | + item["message_type"], |
| 651 | + item["faces"], |
| 652 | + item["edges"], |
| 653 | + ) |
| 654 | + for item in expected_data |
| 655 | + } |
| 656 | + |
| 657 | + # Assert that the actual data matches the expected data regardless of order |
| 658 | + assert actual_data == expected_data_set |
| 659 | + |
| 660 | + # Test repair functionality |
| 661 | + repair_message = inspect_results[0].repair() |
| 662 | + assert repair_message.success is True |
| 663 | + assert repair_message.created_bodies == [] |
| 664 | + assert repair_message.modified_bodies == [] |
| 665 | + |
| 666 | + |
| 667 | +def test_repair_no_body(modeler: Modeler): |
| 668 | + """Test the repair method when body is None.""" |
| 669 | + grpc_client = modeler.client |
| 670 | + # Create an instance of InspectResult with body set to None |
| 671 | + inspect_result = InspectResult(grpc_client=grpc_client, body=None, issues=[]) |
| 672 | + # Call the repair method |
| 673 | + repair_message = inspect_result.repair() |
| 674 | + # Assert the returned RepairToolMessage |
| 675 | + assert isinstance(repair_message, RepairToolMessage) |
| 676 | + assert repair_message.success is False |
| 677 | + assert repair_message.created_bodies == [] |
| 678 | + assert repair_message.modified_bodies == [] |
| 679 | + |
| 680 | + |
| 681 | +def test_problem_area_fix_not_implemented(modeler: Modeler): |
| 682 | + """Test that the fix method in the ProblemArea base class raises NotImplementedError.""" |
| 683 | + grpc_client = modeler.client |
| 684 | + # Create an instance of ProblemArea |
| 685 | + problem_area = ProblemArea(id="123", grpc_client=grpc_client) |
| 686 | + # Assert that calling fix raises NotImplementedError |
| 687 | + with pytest.raises( |
| 688 | + NotImplementedError, match="Fix method is not implemented in the base class." |
| 689 | + ): |
| 690 | + problem_area.fix() |
| 691 | + |
| 692 | + |
| 693 | +@pytest.mark.parametrize( |
| 694 | + "problem_area_class, kwargs", |
| 695 | + [ |
| 696 | + (DuplicateFaceProblemAreas, {"faces": []}), |
| 697 | + (MissingFaceProblemAreas, {"edges": []}), |
| 698 | + (ExtraEdgeProblemAreas, {"edges": []}), |
| 699 | + (ShortEdgeProblemAreas, {"edges": []}), |
| 700 | + (SmallFaceProblemAreas, {"faces": []}), |
| 701 | + (SplitEdgeProblemAreas, {"edges": []}), |
| 702 | + (StitchFaceProblemAreas, {"bodies": []}), |
| 703 | + (UnsimplifiedFaceProblemAreas, {"faces": []}), |
| 704 | + (InterferenceProblemAreas, {"bodies": []}), |
| 705 | + ], |
| 706 | +) |
| 707 | +def test_problem_area_fix_no_data(modeler: Modeler, problem_area_class, kwargs): |
| 708 | + """Test the fix method for various ProblemArea subclasses when required attributes are empty.""" |
| 709 | + grpc_client = modeler.client |
| 710 | + problem_area = problem_area_class(id="123", grpc_client=grpc_client, **kwargs) |
| 711 | + repair_message = problem_area.fix() |
| 712 | + assert isinstance(repair_message, RepairToolMessage) |
| 713 | + assert repair_message.success is False |
| 714 | + assert repair_message.created_bodies == [] |
| 715 | + assert repair_message.modified_bodies == [] |
| 716 | + |
| 717 | + |
| 718 | +@pytest.mark.parametrize( |
| 719 | + "method_name", |
| 720 | + [ |
| 721 | + "find_split_edges", |
| 722 | + "find_extra_edges", |
| 723 | + "find_inexact_edges", |
| 724 | + "find_short_edges", |
| 725 | + "find_duplicate_faces", |
| 726 | + "find_missing_faces", |
| 727 | + "find_small_faces", |
| 728 | + "find_interferences", |
| 729 | + ], |
| 730 | +) |
| 731 | +def test_repair_tools_no_bodies(modeler: Modeler, method_name): |
| 732 | + """Test RepairTools methods when bodies is empty or None.""" |
| 733 | + grpc_client = modeler.client |
| 734 | + repair_tools = RepairTools(grpc_client, modeler) |
| 735 | + method = getattr(repair_tools, method_name) |
| 736 | + |
| 737 | + # Test with an empty list of bodies |
| 738 | + result = method(bodies=[]) |
| 739 | + assert result == [] |
| 740 | + |
| 741 | + # Test with None as bodies |
| 742 | + result = method(bodies=None) |
| 743 | + assert result == [] |
| 744 | + |
| 745 | + |
| 746 | +@pytest.mark.parametrize( |
| 747 | + "method_name", |
| 748 | + [ |
| 749 | + "find_and_fix_short_edges", |
| 750 | + "find_and_fix_extra_edges", |
| 751 | + "find_and_fix_split_edges", |
| 752 | + "find_and_fix_simplify", |
| 753 | + ], |
| 754 | +) |
| 755 | +def test_repair_tools_find_and_fix_no_bodies(modeler: Modeler, method_name): |
| 756 | + """Test RepairTools find_and_fix methods when bodies is empty or None.""" |
| 757 | + grpc_client = modeler.client |
| 758 | + repair_tools = RepairTools(grpc_client, modeler) |
| 759 | + method = getattr(repair_tools, method_name) |
| 760 | + |
| 761 | + # Test with an empty list of bodies |
| 762 | + result = method(bodies=[]) |
| 763 | + assert isinstance(result, RepairToolMessage) |
| 764 | + assert result.success is False |
| 765 | + assert result.created_bodies == [] |
| 766 | + assert result.modified_bodies == [] |
| 767 | + assert result.found == 0 |
| 768 | + assert result.repaired == 0 |
0 commit comments