File size: 2,737 Bytes
395651c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import pytest
from solver.dsl_parser import DSLParser
from solver.engine import GeometryEngine
from solver.models import Point, Constraint

def test_solve_square_pyramid():
    """
    Test solving for a square pyramid S.ABCD.
    Base ABCD is a square with side 10.
    Height SO = 15, where O is the center of ABCD.
    """
    dsl = """
    POINT(A, 0, 0, 0)
    POINT(B, 10, 0, 0)
    POINT(C, 10, 10, 0)
    POINT(D, 0, 10, 0)
    POINT(S)
    POINT(O)
    MIDPOINT(M1, AB)
    MIDPOINT(M2, AC)
    SECTION(O, A, C, 0.5)
    LENGTH(SO, 15)
    PERPENDICULAR(SO, AC)
    PERPENDICULAR(SO, AB)
    PYRAMID(S_ABCD)
    """
    parser = DSLParser()
    engine = GeometryEngine()
    
    points, constraints, is_3d = parser.parse(dsl)
    result = engine.solve(points, constraints, is_3d)
    
    assert result is not None
    coords = result["coordinates"]
    
    # Check base points
    assert coords["A"] == [0.0, 0.0, 0.0]
    assert coords["B"] == [10.0, 0.0, 0.0]
    assert coords["C"] == [10.0, 10.0, 0.0]
    assert coords["D"] == [0.0, 10.0, 0.0]
    
    # Check center O (should be (5, 5, 0))
    assert coords["O"][0] == pytest.approx(5.0)
    assert coords["O"][1] == pytest.approx(5.0)
    assert coords["O"][2] == pytest.approx(0.0)
    
    # Check apex S (should be (5, 5, 15) or (5, 5, -15))
    assert coords["S"][0] == pytest.approx(5.0)
    assert coords["S"][1] == pytest.approx(5.0)
    assert abs(coords["S"][2]) == pytest.approx(15.0)

def test_solve_prism():
    """
    Triangular prism ABC_DEF.
    Base ABC is right triangle at A. AB=3, AC=4.
    Height AD=10.
    """
    dsl = """
    POINT(A, 0, 0, 0)
    POINT(B, 3, 0, 0)
    POINT(C, 0, 4, 0)
    POINT(D)
    POINT(E)
    POINT(F)
    LENGTH(AD, 10)
    PERPENDICULAR(AD, AB)
    PERPENDICULAR(AD, AC)
    PRISM(ABC_DEF)
    """
    parser = DSLParser()
    engine = GeometryEngine()
    
    points, constraints, is_3d = parser.parse(dsl)
    result = engine.solve(points, constraints, is_3d)
    
    assert result is not None
    coords = result["coordinates"]
    
    # D should be (0, 0, 10)
    assert coords["D"][0] == pytest.approx(0.0, abs=1e-3)
    assert coords["D"][1] == pytest.approx(0.0, abs=1e-3)
    assert abs(coords["D"][2]) == pytest.approx(10.0, rel=1e-4, abs=1e-3)

def test_explicit_z_zero_on_xy_plane_does_not_force_is_3d():
    """POINT with z=0 must not flip is_3d; 2D triangle stays 2D (regression vs POINT(A,x,y,0) bug)."""
    dsl = """
    POINT(A, 0, 0, 0)
    POINT(B, 3, 0, 0)
    POINT(C, 0, 4, 0)
    TRIANGLE(ABC)
    """
    parser = DSLParser()
    points, constraints, is_3d = parser.parse(dsl)
    assert is_3d is False
    assert len(points) >= 3


if __name__ == "__main__":
    pytest.main([__file__])