summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/2geom/src/cython/test-conicsection.py
blob: 9fc1c20cb69bb2fadb7cca7b2d880bcf86cf6d8c (plain)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import unittest
import math
from random import randint, uniform

import cy2geom

from cy2geom import Point, IntPoint
from cy2geom import Interval, IntInterval, OptInterval, OptIntInterval

from cy2geom import Affine
from cy2geom import Translate, Scale, Rotate, VShear, HShear, Zoom
from cy2geom import Eigen

from cy2geom import Curve
from cy2geom import Linear
from cy2geom import SBasis, SBasisCurve
from cy2geom import Bezier, BezierCurve

from cy2geom import LineSegment, QuadraticBezier, CubicBezier
from cy2geom import HLineSegment, VLineSegment

from cy2geom import EllipticalArc

from cy2geom import Path

from cy2geom import Circle, Ellipse


class TestPrimitives(unittest.TestCase):
    def test_circle(self):
        C = Circle()
        self.assertEqual(C.center(), Point())
        
        D = Circle(Point(2, 4), 2)
        Dp = D.getPath()
        self.assertEqual(D.center(), Point(2, 4))
        self.assertEqual(D.ray(), 2)

        for i in range(11):
            t = i/10.0
            #Circle approximated by SBasis is not perfect
            self.assertAlmostEqual( abs(D.center()-Dp(t)), D.ray(), delta=0.1 )

        half_circle = D.arc(Dp(0), Dp(0.3), Dp(0.5))

        self.assertTrue(half_circle.is_SVG_compliant())

        self.assertAlmostEqual(Dp(0.25), half_circle(0.5), delta=0.1)

        points = [Point(2, 5), Point(1, 4), Point(9, 0)]
        D.set_points(points)
        for p in points:
            self.assertAlmostEqual( abs(p-D.center()), D.ray() )
        Dc = Circle.from_points(points)
        self.assertAlmostEqual(Dc.center(), D.center())
        self.assertAlmostEqual(Dc.ray(), D.ray())
        
        coeffs = (2, 4, 1, -4)
        E = Circle.from_coefficients(*coeffs)
        def param(x, y):
            A, B, C, D = coeffs
            return A*x**2 + A*y**2 + B*x + C*y + D
        Ec = E.arc(E.center()+Point(E.ray(), 0), E.center()-Point(E.ray(), 0), E.center()+Point(E.ray(), 0) )
        for i in range(11):
            t = i/10.0
            self.assertAlmostEqual(param(Ec.value_at(t, 0), Ec.value_at(t, 1)), 0)
        
        E.set(3, 5, 9)
        self.assertAlmostEqual(E.center(), Point(3, 5))
        self.assertAlmostEqual(E.ray(), 9)
        
        E.set_coefficients(*coeffs)
        #radius and center from parametric equation 
        ca = float(coeffs[1])/coeffs[0]
        cb = float(coeffs[2])/coeffs[0]
        cc = float(coeffs[3])/coeffs[0]
        self.assertAlmostEqual( 4*E.ray()**2 , ca**2 + cb**2 -4*cc )
        self.assertAlmostEqual( E.center(), -Point(ca, cb)/2)
    
    def test_ellipse(self):
        #TODO: maybe a bug in arc? get_curve(F) returns different ellipse than F
        def get_curve(ellipse):
            p = Point(ellipse.ray(0), 0)*Rotate(ellipse.rot_angle())
            return ellipse.arc(ellipse.center()+p, ellipse.center()-p, ellipse.center()+p*(1-1e-7))
        E = Ellipse()
        self.assertAlmostEqual(E.center(), Point())
        self.assertAlmostEqual(E.ray(0), 0)
        self.assertAlmostEqual(E.ray(1), 0)
        
        F = Ellipse(Point(), 3, 2, 0)
        self.assertAlmostEqual(F.center(), Point())
        self.assertAlmostEqual(F.ray(0), 3)
        self.assertAlmostEqual(F.ray(1), 2)
        self.assertAlmostEqual(F.rot_angle(), 0)
        # x**2/9 + y**2/4 = 1
        self.assertAlmostEqual(F.implicit_form_coefficients()[0], 1/9.0)
        self.assertAlmostEqual(F.implicit_form_coefficients()[2], 1/4.0)
        self.assertAlmostEqual(F.implicit_form_coefficients()[5], -1)
        
        coeffs = (1/3.0, 0, 1/16.0, 1, 0, -1/4.0)
        G = Ellipse.from_coefficients(*coeffs)
        self.assertAlmostEqual(G.center(), Point(-3/2.0, 0))
        self.assertAlmostEqual(G.ray(0), math.sqrt(3))
        self.assertAlmostEqual(G.ray(1), 4)
        self.assertAlmostEqual(G.rot_angle(), 0)
        
        points = [Point(1, 2), Point(2 ,9), Point(0, 3), Point(-3, 8), Point(5, 8)]
        G.set_points(points)
        coeffs_G = tuple(G.implicit_form_coefficients())
        def paramG(x, y):
            A, B, C, D, E, F = coeffs_G
            return A*x**2 + B*x*y + C*y**2 + D*x + E*y + F
        for p in points:
            self.assertAlmostEqual(paramG(p.x, p.y), 0)

        G2 = Ellipse.from_points(points)
        coeffs_G2 = tuple(G.implicit_form_coefficients())
        def paramG2(x, y):
            A, B, C, D, E, F = coeffs_G2
            return A*x**2 + B*x*y + C*y**2 + D*x + E*y + F
        for p in points:
            self.assertAlmostEqual(paramG2(p.x, p.y), 0)
        
        E.set_coefficients(*coeffs_G2)
        for a1, a2 in zip(E.implicit_form_coefficients(), G2.implicit_form_coefficients()):
            self.assertAlmostEqual(a1, a2)

        H = Ellipse.from_circle(Circle(Point(2, 8), 5))
        self.assertAlmostEqual(H.center(), Point(2, 8))
        self.assertAlmostEqual(H.ray(0), 5)
        self.assertAlmostEqual(H.ray(1), 5)
        
        Ft = F.transformed( Rotate(math.pi/2) )
        self.assertAlmostEqual(F.ray(0), Ft.ray(1))
        self.assertAlmostEqual(F.ray(1), Ft.ray(0))
        
unittest.main()