Beispiel #1
0
 def test_intInterval(self):
     I = IntInterval(2, 6)
     J = IntInterval(0, 1)
     self.interval_basic(I, J)
     p = [3, 2.3, 65.3, 43]
     K = IntInterval.from_list(p)
     self.assertAlmostEqual(K.max(), int(max(p)))
     self.assertAlmostEqual(int((K+IntInterval(1.0)).min()), int(min(p)+1))
     L = IntInterval(3)
     for i in range(3):
         K+=L
     self.assertAlmostEqual(K.max(), int(max(p))+9)
     
     self.assertEqual(Interval(3)|Interval(5), 
                 Interval(3, 5))
     self.assertAlmostEqual((K-L).max(), (K-3).max())
Beispiel #2
0
 def test_optInterval(self):
     I = OptInterval(2.2, 9.3)
     J = Interval(3, 13)
     K = OptInterval.from_Interval(J)
     self.assertEqual(K.Interval, J)
     self.interval_basic(K.Interval, I.Interval)
     
     L = OptInterval()
     
     self.assertFalse(L)
     self.assertTrue( (L&I).is_empty() )
     L.intersect_with(I)
     self.assertFalse(L)
     
     L |= I
     
     self.assertEqual(L.Interval, I.Interval)
     
     self.assertEqual((I & K).Interval, Interval(3, 9.3))
Beispiel #3
0
 def test_quadraticBezier(self):
     Q = QuadraticBezier(Point(2, 8), Point(1, 9), Point(-2, 3))
     R = QuadraticBezier.from_beziers(Bezier(2, 8, 4), Bezier(-1, 9, 9)) 
     self.curve(Q)
     self.curve(R)
     self.curve(Q.reverse())
     self.curve(Q.portion(interval=Interval(0.1, 0.9)))
     self.curve(Q.subdivide(0.8)[0])
     self.curve(Q.subdivide(0.8)[1])
     self.curve(Q.derivative())
     self.curve(Q.transformed(Scale(-3)*Translate(4, 8)))
     
     self.curve(QuadraticBezier())
Beispiel #4
0
 def ntest_lineSegment(self):
     L = LineSegment(Point(2, 8), Point(1, 9))
     K = LineSegment.from_beziers(Bezier(2, 8), Bezier(-1, 9)) 
     self.curve(L)
     self.curve(K)
     self.curve(L.reverse())
     self.curve(L.portion(Interval(0.2, 0.4)))
     self.curve(L.subdivide(0.3)[0])
     self.curve(L.subdivide(0.3)[1])
     self.curve(L.derivative())
     self.curve(L.transformed(Scale(30)*Translate(3, 9)))
     
     self.curve(LineSegment())
Beispiel #5
0
    def path(self, P):
        for curve in P:
            self.assertIsInstance(curve, Curve)

        self.assertAlmostEqual(P(0), P.front()(0))
        self.curves_equal(P.front(), P[0])

        self.curves_equal(P.back_default(), P[P.size_default() - 1])
        self.curves_equal(P.back_open(), P.back())
        self.assertEqual(P.size_open(), P.size())

        self.assertFalse(P.empty() ^ (P.size() == 0))

        exact = P.bounds_exact().Rect
        exact.expand_by(1e-5)

        fast = P.bounds_fast().Rect
        fast.expand_by(1e-5)
        A1 = Affine(3, 1, 8, 3, 9, 9)
        A2 = Rotate(0.231)

        for i in range(100 * P.size_open() + 1):
            t = i / 100.0
            self.assertTrue(exact.contains(P(t)))
            self.assertTrue(fast.contains(P(t)))
            self.assertAlmostEqual((P * A1)(t), P(t) * A1)
            self.assertAlmostEqual((P * A2)(t), P(t) * A2)

            self.assertAlmostEqual(P(t), P.point_at(t))
            self.assertAlmostEqual(P(t).x, P.value_at(t, 0))
            self.assertAlmostEqual(P(t).y, P.value_at(t, 1))

        if P.closed():
            self.curves_equal(P.back_default(), P.back_closed())
            self.assertEqual(P.size_default(), P.size_closed())
        else:
            self.curves_equal(P.back_default(), P.back_open())
            self.assertEqual(P.size_default(), P.size_open())

        for i in range(10):
            for root in P.roots(i, 0):
                if root < P.size_default():
                    self.assertAlmostEqual(P.value_at(root, 0), i)
            for root in P.roots(i, 1):
                if root < P.size_default():
                    self.assertAlmostEqual(P.value_at(root, 1), i)

        for t in P.all_nearest_times(P(0)):
            self.assertAlmostEqual(P(t), P(0))
        self.assertAlmostEqual(min(P.all_nearest_times(P(0))), 0)
        self.assertAlmostEqual(P.nearest_time(P(0), 0, 0.2), 0)
        self.assertEqual(len(P.nearest_time_per_curve(Point())),
                         P.size_default())

        t, distSq = P.nearest_time_and_dist_sq(Point(-1, -1), 0, P.size())
        self.assertAlmostEqual(distSq**0.5, abs(P(t) - Point(-1, -1)))

        self.assertAlmostEqual(P.portion(0.3, 0.4)(0), P(0.3))
        self.assertAlmostEqual(
            P.portion(interval=Interval(P.size(),
                                        P.size() * 2) / 3)(0),
            P(P.size() / 3.0))

        self.assertAlmostEqual(P(0.23), P.reverse()(P.size() - 0.23))

        self.assertAlmostEqual(P.initial_point(), P(0))
        self.assertAlmostEqual(P.final_point(), P(P.size()))
Beispiel #6
0
    def test_path(self):
        a = Path()
        a.append_curve(
            CubicBezier(Point(-7, -3), Point(2, 8), Point(2, 1), Point(-2, 0)))

        self.assertEqual(a.size(), 1)
        self.assertFalse(a.closed())
        self.path(a)

        a.close(True)
        self.assertTrue(a.closed())
        self.path(a)

        a.close(False)
        a.append_curve(LineSegment(a.final_point(), Point(3, 5)))
        self.assertEqual(a.size(), 2)
        self.path(a)

        a.append_SBasis(SBasis(3, 6) * SBasis(1, 0), SBasis(5, 2))
        self.path(a)

        a.append_curve(
            EllipticalArc(Point(), 1, 2, math.pi / 6, True, True, Point(1, 1)),
            Path.STITCH_DISCONTINUOUS)
        #Stitching adds new segment
        self.assertEqual(a.size(), 5)

        b = Path()
        for c in a:
            b.append_curve(c)

        #TODO: This fails with STITCH_DISCONTINUOUS, but also does so in C++, so
        #it's either correct behaviour or bug in 2geom
        #~ self.path(b)

        b.insert(2, LineSegment(b[2 - 1](1),
                                b[2](0)))  #, Path.STITCH_DISCONTINUOUS)
        self.curves_equal(LineSegment(b[2 - 1](1), b[2](0)), b[2])
        #TODO! fails on root finding
        #self.path(b)

        b.set_initial(a[2](1))
        b.set_final(a[3](0))

        a.insert_slice(3, b, 0, b.size())
        self.assertEqual(a.size(), b.size() * 2 - 1)

        for i in range(b.size()):
            self.curves_equal(a[3 + i], b[i])

        #Looks like bug:


#        A = Path()
#        A.append_curve( CubicBezier( Point(-7, -3), Point(2, 8), Point(2, 1), Point(-2, 0) ) )
#        A.append_curve(EllipticalArc(Point(), 1, 2, math.pi/6, True, True, Point(1, 1)), Path.STITCH_DISCONTINUOUS)
#        print A.roots(0, 1)

#Roots are [1.0, 2.768305708350847, 3.25], Point at second root is
#Point (2.32, -0.48)
#and third root is > 3 - it corresponds to root on closing segment, but A is open,
#and computing A(3.25) results in RangeError - this might be bug or feature.

        self.path(a.portion(0.232, 3.12))
        self.path(a.portion(interval=Interval(0.1, 4.7)))
        self.path(a.portion(0.232, 3.12).reverse())

        b.clear()
        self.assertTrue(b.empty())

        aa = Path()
        for c in a:
            aa.append_curve(c)

        a.erase(0)
        self.assertEqual(a.size(), aa.size() - 1)
        self.assertAlmostEqual(a(0), aa(1))

        a.erase_last()
        self.assertEqual(a.size(), aa.size() - 2)
        self.assertAlmostEqual(a.final_point(), aa[aa.size() - 2](1))

        a.replace(3, QuadraticBezier(a(3), Point(), a(4)))
        self.assertEqual(a.size(), aa.size() - 2)

        cs = [
            LineSegment(Point(-0.5, 0), Point(0.5, 0)).transformed(
                Rotate(-math.pi / 3 * i) * Translate(
                    Point(0,
                          math.sqrt(3) / 2) * Rotate(-math.pi / 3 * i)))
            for i in range(6)
        ]

        hexagon = Path.fromList(cs,
                                stitching=Path.STITCH_DISCONTINUOUS,
                                closed=True)

        if draw:
            utils.draw(hexagon, scale=100)

        #to = 5 because each corner contains one stitching segment
        half_hexagon = Path.fromPath(hexagon, fr=0, to=5)
        if draw:
            utils.draw(half_hexagon, scale=100)

        half_hexagon.replace_slice(
            1, 5, LineSegment(half_hexagon(1), half_hexagon(5)))
        self.assertEqual(half_hexagon.size(), 2)
        self.assertAlmostEqual(half_hexagon(1.5), Point(0.5, 0))

        half_hexagon.stitch_to(half_hexagon(0))
        self.assertAlmostEqual(half_hexagon(2.5), Point())

        a.start(Point(2, 2))
        a.append_SBasis(SBasis(2, 6), SBasis(1, 5) * SBasis(2, 9))
        self.assertAlmostEqual(a(1), Point(6, 5 * 9))

        l = Path.fromList(
            [QuadraticBezier(Point(6, 5 * 9), Point(1, 2), Point(-2, .21))])
        a.append_path(l)
        self.assertAlmostEqual(a.final_point(), l.final_point())

        k = Path.fromList(
            [QuadraticBezier(Point(), Point(2, 1), Point(-2, .21)).reverse()])
        k.append_portion_to(l, 0, 0.3)
        self.assertAlmostEqual(l.final_point(), k(0.3))
Beispiel #7
0
 def test_interval(self):
     I = Interval(1.2, 5)
     J = Interval(0, 0.3)
     self.interval_basic(I, J)
     
     self.assertTrue(I.interior_contains(I.middle()))
     self.assertFalse(I.interior_contains(I.min()))
     self.assertFalse(I.interior_contains_interval(I))
     self.assertTrue(I.interior_contains_interval(Interval(I.min()+1, I.max()-1)))
     
     self.assertTrue(I.interior_intersects(I))
     self.assertFalse(I.interior_intersects(-I))
     p = [1, 2, 3.442, 3]
     K = Interval.from_list(p)
     self.assertAlmostEqual(K.max(), max(p))
     self.assertAlmostEqual((K+Interval(1.0)).min(), min(p)+1)
     L = Interval(10/3.0)
     for i in range(3):
         K+=L
     self.assertAlmostEqual(K.max(), max(p)+10)
     
     #TODO This 2geom behaviour is a bit strange
     self.assertEqual(Interval(3.0)|Interval(5.0), 
                 Interval(3.0, 5.0))
     self.assertAlmostEqual((K-L).max(), (K-10/3.0).max())
     
     self.assertAlmostEqual((K*3.4).max(), 3.4*K.max())
     self.assertAlmostEqual((K/3).extent(), K.extent()/3)
Beispiel #8
0
    def test_sBasis(self):
        S = SBasis()
        T = SBasis(2)
        U = SBasis(1, 7)
        V = SBasis.from_linear( Linear(2, 8) )
        
        self.assertEqual(V[0], Linear(2, 8))
        self.assertEqual(V.back(), Linear(2, 8))
        
        #~ self.assertTrue(S.empty())
        self.assertFalse(T.empty())
        
        T.pop_back()
        self.assertTrue(T.empty())
        
        self.assertEqual(S.size(), 0)
        self.assertEqual(U.size(), 1)
        self.assertEqual((U*V).size(), 2)
        
        T.resize(1, Linear(2, 3))
        self.assertEqual(T[0], Linear(2, 3))
        T.clear()
        self.assertTrue(T.empty())
        #TODO
        #~ T.reserve(5)
        #~ print T.size()
        self.assertEqual(V.at(0), V[0])
        self.assertEqual(V, U+1)
        self.assertNotEqual(V, U)
        self.assertTrue(T.is_zero())
        self.assertTrue(SBasis(1).is_constant())
        def f(A, B):
            return (-A)*(A+B*2.2)*(A*B-B*B/3)
        W = f(U, V)
        self.assertAlmostEqual(W(0), W.at0())
        self.assertAlmostEqual(W(1), W.at1())
        
        for i in range(11):
            t = i/10.0
            self.assertAlmostEqual(W(t), W.value_at(t))
            self.assertAlmostEqual(W(t), f(U(t), V(t)))
            
            vd_UV = (U*V).value_and_derivatives(t, 1)
            vd_U = U.value_and_derivatives(t, 1)
            vd_V = V.value_and_derivatives(t, 1)
            self.assertAlmostEqual( vd_UV[1], vd_U[1]*V(t)+U(t)*vd_V[1] )
            
            self.assertAlmostEqual( U(V)(t), U(V(t)) )
        self.assertEqual(T.degrees_of_freedom(), 0)
        self.assertEqual(U.degrees_of_freedom(), 2)
        
        self.assertEqual(T, T.to_SBasis())
        
        U2 = SBasis(U(0), U(1))
        U2.resize(10)
        self.assertNotEqual(U2, U)
        U2.truncate(U.size())
        self.assertEqual(U2, U)
        #TODO: normalize()
        sL = Linear.sin(Linear(0, 1), 3)
        cL = Linear.cos(Linear(0, 1), 3)
        sqrtU = SBasis.sqrt( U, 3 )
        rL = Linear.reciprocal(Linear(1,2), 3)
        # cy2geom.inverse seems to return nans for degrees > 1
        #~ asin = cy2geom.inverse( cy2geom.sqrt( SBasis(Linear(0, 1)), 3 ), 1)
        for i in range(11):
            t = i/10.0
            self.assertAlmostEqual(sL(t), math.sin(t))
            self.assertAlmostEqual(cL(t), math.cos(t))
            #cy2geom.sqrt is not that precise 
            self.assertAlmostEqual(sqrtU(t), math.sqrt(U(t)), places = 1)
            self.assertAlmostEqual(rL(t), 1/(1+t), places = 1 )
            #~ self.assertAlmostEqual( asin(t), math.asin(t) )
            self.assertAlmostEqual( SBasis.compose(U, V)(t), U(V)(t) )
            self.assertAlmostEqual( SBasis.divide(U, V, 3)(t), U(t)/V(t), places = 1)
            
            self.assertAlmostEqual( SBasis.derivative(SBasis.integral(W))(t), W(t))
            self.assertAlmostEqual( cy2geom.reverse(W)(t), W(1-t) )
            self.assertAlmostEqual( SBasis.multiply(U, V)(t), (U*V)(t))
            #TODO looks like bug in 2geom
            #~ print cy2geom.multiply_add(U, V, W)(t), (U*V+W)(t)
            self.assertAlmostEqual( SBasis.multiply_add(U, W, V)(t), (U*W+V)(t))
            
            self.assertTrue( SBasis.bounds_exact(U).Interval.contains(U(t)) )
            self.assertTrue( SBasis.bounds_fast(U).Interval.contains(U(t)) )
            self.assertTrue( SBasis.bounds_local(U, OptInterval(t-0.05, t+0.05)).Interval.contains(U(t)) )
        
        
        for r in SBasis.roots(W):
            self.assertAlmostEqual(W(r), 0)
        for r in SBasis.roots(W, Interval(0, 0.7)):
            self.assertAlmostEqual(W(r), 0)
            self.assertTrue(Interval(0, 0.7).contains(r))

        levels = [0, 3, 22, -21]
        for i, roots in enumerate( SBasis.multi_roots(W, levels) ):
            level = levels[i]
            for r in roots:
                self.assertAlmostEqual(W(r), level)

        self.assertEqual(SBasis.valuation(W), 0)
        #TODO: why is this still 0?
        #~ print cy2geom.valuation(cy2geom.shift(W, 6))
        self.assertEqual( U[0], SBasis.shift(U, 2)[2] )
        
        for I in SBasis.level_set(W, 2, tol = 1e-7):
            self.assertAlmostEqual( W(I.mid()), 2 )
        for I in SBasis.level_set(W, Interval(0, 1), tol = 1e-7, vtol = 1e-7):
            self.assertTrue( 0 <= W(I.begin()) <= 1 )
            self.assertTrue( 0 <= W(I.mid()) <= 1 )
            self.assertTrue( 0 <= W(I.end()) <= 1 )
Beispiel #9
0
    def curve(self, C): 
        self.assertAlmostEqual(C.initial_point(), C(0))
        self.assertAlmostEqual(C.final_point(), C.point_at(1))
        #Doesn't have to be true
        #~ if C.length() > 0.01:
            #~ self.assertFalse(C.is_degenerate())

        if C.is_degenerate():
            #trivial special case
            return
        
        for i in range(11):
            t = i/10.0
            self.assertAlmostEqual(C(t).x, C.point_at(t).x)
            self.assertAlmostEqual(C(t).y, C.value_at(t, 1))
            self.assertEqual( C(t), C.point_and_derivatives(t, 1)[0] )
            self.assertTrue( C.bounds_exact().contains(C(t)) )
            self.assertTrue( C.bounds_fast().contains(C(t)) )
            #TODO why this works only with degree = 0?
            if      C.bounds_local(OptInterval(t-0.05, t+0.05), 0
                ) and  (
                    C.bounds_local(OptInterval(t-0.05, t+0.05), 0).Rect.area() > 1e-10):
                #ruling out too small rectangles, they have problems with precision
                self.assertTrue( C.bounds_local( OptInterval(t-0.05, t+0.05), 0 ).Rect.contains(C(t)))
        D = C.duplicate()
        
        D.set_initial(Point())
        self.assertAlmostEqual(D.initial_point(), Point())
        
        D.set_final(Point(1, 1))
        self.assertAlmostEqual(D.final_point(), Point(1, 1))
        
        A = Affine( uniform(-10, 10),
                    uniform(-10, 10),
                    uniform(-10, 10),
                    uniform(-10, 10),
                    uniform(-10, 10),
                    uniform(-10, 10))
        E = C.transformed(A)
        for i in range(11):
            t = i/10.0
      #      self.assertAlmostEqual( E(t), C(t)*A )
        G1 = C.portion(0.2, 0.8)
        G2 = C.portion( interval=Interval(2, 8)/10 )
        self.assertAlmostEqual( G1(0), C(0.2) )
        self.assertAlmostEqual( G2(0.5), C( lerp(0.5, 0.2, 0.8) ))
        self.assertAlmostEqual( G1(1), G2(1) )
        
        for i in range(11):
            t = i/10.0
            self.assertAlmostEqual( C.reverse()(t), C(1-t) )
        self.assertAlmostEqual( C.point_and_derivatives(0.3, 1)[1], C.derivative()(0.3) )
        
        self.assertAlmostEqual( C.nearest_time(C(0)), 0 )
        self.assertAlmostEqual( C( C.nearest_time(C(0.5), interval=Interval(0.2, 0.5)) ), C(0.5) )
        self.assertAlmostEqual( C( C.nearest_time(C(0.5), 0.2, 0.5) ), C(0.5) )
        for p in C.all_nearest_times( C(0), 0, 1):
            self.assertEqual(C(p), C(0))
        for p in C.all_nearest_times( C(1), interval=Interval(0, 1)):
            self.assertEqual(C(p), C(1))
        for r in C.roots(0, 0):
            self.assertAlmostEqual(C.value_at(r, 0), 0)
        
        self.assertGreaterEqual(C.length(), abs(C(1) - C(0)))
        self.assertEqual(C.winding(Point()), int(C.winding(Point())) )
        self.assertAlmostEqual( C.unit_tangent_at(0.5), 
                                Point.unit_vector(C.derivative()(0.5)) )
        self.assertTrue(isinstance(C.to_SBasis()[0], SBasis))