Exemplo n.º 1
0
    def rebuild(self, p, n):
        """Creates an approximation to this curve by resampling it using a
        uniform knot vector of order *p* with *n* control points.

        :param int p: Polynomial discretization order
        :param int n: Number of control points
        :return: A new approximate curve
        :rtype: Curve
        """
        # establish uniform open knot vector
        knot = [0] * p + list(range(1, n - p + 1)) + [n - p + 1] * p
        basis = BSplineBasis(p, knot)
        # set parametric range of the new basis to be the same as the old one
        basis.normalize()
        t0 = self.bases[0].start()
        t1 = self.bases[0].end()
        basis *= t1 - t0
        basis += t0
        # fetch evaluation points and solve interpolation problem
        t = basis.greville()
        N = basis.evaluate(t)
        controlpoints = np.linalg.solve(N, self.evaluate(t))

        # return new resampled curve
        return Curve(basis, controlpoints)
Exemplo n.º 2
0
    def test_edge_curves(self):
        # create an arrow-like 2D geometry with the pointy end at (-1,1) towards up and left
        # mixes rational and non-rational curves with different parametrization spaces
        c1 = cf.circle_segment(pi / 2)
        c2 = Curve(BSplineBasis(2, [0, 0, 1, 2, 2]),
                   [[0, 1], [-1, 1], [-1, 0]])
        c3 = cf.circle_segment(pi / 2)
        c3.rotate(pi)
        c4 = Curve(BSplineBasis(2), [[0, -1], [1, 0]])

        surf = sf.edge_curves(c1, c2, c3, c4)

        # srf spits out parametric space (0,1)^2, so we sync these up to input curves
        c3.reverse()
        c4.reverse()
        c1.reparam()
        c2.reparam()
        c3.reparam()
        c4.reparam()

        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 0)[0],
                                   c1(u)[0])  # x-coord, bottom crv
            self.assertAlmostEqual(surf(u, 0)[1],
                                   c1(u)[1])  # y-coord, bottom crv
        for u in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(u, 1)[0], c3(u)[0])  # x-coord, top crv
            self.assertAlmostEqual(surf(u, 1)[1], c3(u)[1])  # y-coord, top crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(0, v)[0],
                                   c4(v)[0])  # x-coord, left crv
            self.assertAlmostEqual(surf(0, v)[1],
                                   c4(v)[1])  # y-coord, left crv
        for v in np.linspace(0, 1, 7):
            self.assertAlmostEqual(surf(1, v)[0],
                                   c2(v)[0])  # x-coord, right crv
            self.assertAlmostEqual(surf(1, v)[1],
                                   c2(v)[1])  # y-coord, right crv

        # add a case where opposing sites have mis-matching rationality
        crvs = Surface().edges()  # returned in order umin, umax, vmin, vmax
        crvs[0].force_rational()
        crvs[1].reverse()
        crvs[2].reverse()
        # input curves should be clockwise oriented closed loop
        srf = sf.edge_curves(crvs[0], crvs[3], crvs[1], crvs[2])
        crvs[1].reverse()
        u = np.linspace(0, 1, 7)
        self.assertTrue(np.allclose(srf(u, 0).reshape((7, 2)), crvs[0](u)))
        self.assertTrue(np.allclose(srf(u, 1).reshape((7, 2)), crvs[1](u)))

        # test self-organizing curve ordering when they are not sequential
        srf = sf.edge_curves(crvs[0], crvs[2].reverse(), crvs[3], crvs[1])
        u = np.linspace(0, 1, 7)
        self.assertTrue(np.allclose(srf(u, 0).reshape((7, 2)), crvs[0](u)))
        self.assertTrue(np.allclose(srf(u, 1).reshape((7, 2)), crvs[1](u)))

        # test error handling
        with self.assertRaises(ValueError):
            srf = sf.edge_curves(crvs + (Curve(), ))  # 5 input curves
Exemplo n.º 3
0
 def test_greville(self):
     b = BSplineBasis(4, [0, 0, 0, 0, 1, 2, 3, 3, 3, 3])
     self.assertAlmostEqual(b.greville(0), 0.0)
     self.assertAlmostEqual(b.greville(1), 1.0 / 3.0)
     self.assertAlmostEqual(b.greville(2), 1.0)
     self.assertAlmostEqual(b.greville(),
                            [0.0, 1.0 / 3.0, 1.0, 2.0, 8.0 / 3.0, 3.0])
Exemplo n.º 4
0
    def test_make_periodic(self):
        my_cps = np.array([[0, -1], [1, 0], [0, 1], [-1, 0], [0, -1]],
                          dtype=float)

        crv = Curve(BSplineBasis(2, [0, 0, 1, 2, 3, 4, 4]),
                    my_cps,
                    rational=False)
        crv = crv.make_periodic(0)
        cps = [[0, -1], [1, 0], [0, 1], [-1, 0]]
        self.assertAlmostEqual(np.linalg.norm(crv.controlpoints - cps), 0.0)

        crv = Curve(BSplineBasis(2, [0, 0, 1, 2, 3, 4, 4]),
                    my_cps,
                    rational=False)
        crv = crv.make_periodic(0)
        cps = [[0, -1], [1, 0], [0, 1], [-1, 0]]
        self.assertAlmostEqual(np.linalg.norm(crv.controlpoints - cps), 0.0)

        crv = Curve(BSplineBasis(3, [0, 0, 0, 1, 2, 3, 3, 3]),
                    my_cps,
                    rational=False)
        crv = crv.make_periodic(0)
        cps = [[0, -1], [1, 0], [0, 1], [-1, 0]]
        self.assertAlmostEqual(np.linalg.norm(crv.controlpoints - cps), 0.0)

        crv = Curve(BSplineBasis(3, [0, 0, 0, 1, 2, 3, 3, 3]),
                    my_cps,
                    rational=False)
        crv = crv.make_periodic(1)
        cps = [[-1, 0], [1, 0], [0, 1]]
        self.assertAlmostEqual(np.linalg.norm(crv.controlpoints - cps), 0.0)
Exemplo n.º 5
0
    def test_force_rational(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1,
                                                            2], [1, 0, 2],
                         [1, 1, 2], [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0],
                         [4, 1, 0], [3, 2, 0], [0, 0, 3], [-1, 1,
                                                           3], [0, 2, 3],
                         [1, -1, 5], [1, 0, 5], [1, 1, 5], [2, 1, 4],
                         [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, .66, .32)
        control_point1 = vol[0]
        vol.force_rational()
        evaluation_point2 = vol(0.23, .66, .32)
        control_point2 = vol[0]
        # ensure that volume has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])
        # ensure that we include rational weights of 1
        self.assertEqual(len(control_point1), 3)
        self.assertEqual(len(control_point2), 4)
        self.assertEqual(control_point2[3], 1)
        self.assertEqual(vol.rational, True)
Exemplo n.º 6
0
    def test_insert_knot(self):
        # more or less random 2D surface with p=[3,2] and n=[4,3]
        controlpoints = [[0, 0], [-1, 1], [0, 2], [1, -1], [1, 0], [1, 1],
                         [2, 1], [2, 2], [2, 3], [3, 0], [4, 1], [3, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        surf = Surface(basis1, basis2, controlpoints)

        # pick some evaluation point (could be anything)
        evaluation_point1 = surf(0.23, 0.37)

        surf.insert_knot(.22, 0)
        surf.insert_knot(.5, 0)
        surf.insert_knot(.7, 0)
        surf.insert_knot(.1, 1)
        surf.insert_knot(1.0 / 3, 1)
        knot1, knot2 = surf.knots(with_multiplicities=True)
        self.assertEqual(len(knot1), 11)  # 8 to start with, 3 new ones
        self.assertEqual(len(knot2), 8)  # 6 to start with, 2 new ones

        evaluation_point2 = surf(0.23, 0.37)

        # evaluation before and after InsertKnot should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])

        # test a rational 2D surface
        controlpoints = [[0, 0, 1], [-1, 1, .96], [0, 2, 1], [1, -1, 1],
                         [1, 0, .8], [1, 1, 1], [2, 1, .89], [2, 2, .9],
                         [2, 3, 1], [3, 0, 1], [4, 1, 1], [3, 2, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        surf = Surface(basis1, basis2, controlpoints, True)

        evaluation_point1 = surf(0.23, 0.37)

        surf.insert_knot(.22, 0)
        surf.insert_knot(.5, 0)
        surf.insert_knot(.7, 0)
        surf.insert_knot(.1, 1)
        surf.insert_knot(1.0 / 3, 1)
        knot1, knot2 = surf.knots(with_multiplicities=True)
        self.assertEqual(len(knot1), 10)  # 7 to start with, 3 new ones
        self.assertEqual(len(knot2), 8)  # 6 to start with, 2 new ones

        evaluation_point2 = surf(0.23, 0.37)

        # evaluation before and after InsertKnot should remain unchanged
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])

        # test errors and exceptions
        with self.assertRaises(TypeError):
            surf.insert_knot(1, 2, 3)  # too many arguments
        with self.assertRaises(ValueError):
            surf.insert_knot("tree-fiddy", .5)  # wrong argument type
        with self.assertRaises(ValueError):
            surf.insert_knot(0, -0.2)  # Outside-domain error
        with self.assertRaises(ValueError):
            surf.insert_knot(1, 1.4)  # Outside-domain error
Exemplo n.º 7
0
    def test_make_identical(self):
        basis1 = BSplineBasis(4, [-1, -1, 0, 0, 1, 2, 9, 9, 10, 10, 11, 12],
                              periodic=1)
        basis2 = BSplineBasis(2, [0, 0, .25, 1, 1])
        cp = [[0, 0, 0, 1], [1, 0, 0, 1.1], [2, 0, 0, 1], [0, 1, 0, .7],
              [1, 1, 0, .8], [2, 1, 0, 1], [0, 2, 0, 1], [1, 2, 0, 1.2],
              [2, 2, 0, 1]]
        surf1 = Surface(BSplineBasis(3), BSplineBasis(3), cp,
                        True)  # rational 3D
        surf2 = Surface(basis1, basis2)  # periodic 2D
        surf1.insert_knot([0.25, .5, .75], direction='v')

        Surface.make_splines_identical(surf1, surf2)

        for s in (surf1, surf2):
            self.assertEqual(s.periodic(0), False)
            self.assertEqual(s.periodic(1), False)
            self.assertEqual(s.dimension, 3)
            self.assertEqual(s.rational, True)
            self.assertEqual(s.order(), (4, 3))

            self.assertAlmostEqual(len(s.knots(0, True)), 12)
            self.assertAlmostEqual(len(s.knots(1, True)), 10)

            self.assertEqual(s.bases[1].continuity(.25), 0)
            self.assertEqual(s.bases[1].continuity(.75), 1)
            self.assertEqual(s.bases[0].continuity(.2), 2)
            self.assertEqual(s.bases[0].continuity(.9), 1)
Exemplo n.º 8
0
    def test_const_par_crv(self):
        # more or less random 2D surface with p=[2,2] and n=[4,3]
        controlpoints = [[0, 0], [-1, 1], [0, 2], [1, -1], [1, 0], [1, 1],
                         [2, 1], [2, 2], [2, 3], [3, 0], [4, 1], [3, 2]]
        basis1 = BSplineBasis(3, [0, 0, 0, .4, 1, 1, 1])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        surf = Surface(basis1, basis2, controlpoints)
        surf.refine(1)

        # try general knot in u-direction
        crv = surf.const_par_curve(0.3, 'u')
        v = np.linspace(0, 1, 13)
        self.assertTrue(np.allclose(surf(0.3, v), crv(v)))

        # try existing knot in u-direction
        crv = surf.const_par_curve(0.4, 'u')
        v = np.linspace(0, 1, 13)
        self.assertTrue(np.allclose(surf(0.4, v), crv(v)))

        # try general knot in v-direction
        crv = surf.const_par_curve(0.3, 'v')
        u = np.linspace(0, 1, 13)
        self.assertTrue(np.allclose(surf(u, 0.3).reshape(13, 2), crv(u)))

        # try start-point
        crv = surf.const_par_curve(0.0, 'v')
        u = np.linspace(0, 1, 13)
        self.assertTrue(np.allclose(surf(u, 0.0).reshape(13, 2), crv(u)))

        # try end-point
        crv = surf.const_par_curve(1.0, 'v')
        u = np.linspace(0, 1, 13)
        self.assertTrue(np.allclose(surf(u, 1.0).reshape(13, 2), crv(u)))
Exemplo n.º 9
0
    def read_surface(self, nsrf):
        knotsu = [0]
        for i in nsrf.KnotsU:
            knotsu.append(i)
        knotsu.append(knotsu[len(knotsu) - 1])
        knotsu[0] = knotsu[1]

        knotsv = [0]
        for i in nsrf.KnotsV:
            knotsv.append(i)
        knotsv.append(knotsv[len(knotsv) - 1])
        knotsv[0] = knotsv[1]

        basisu = BSplineBasis(nsrf.OrderU, knotsu, -1)
        basisv = BSplineBasis(nsrf.OrderV, knotsv, -1)
        cpts = []

        cpts = np.ndarray(
            (nsrf.Points.CountU * nsrf.Points.CountV, 3 + nsrf.IsRational))
        for v in range(0, nsrf.Points.CountV):
            for u in range(0, nsrf.Points.CountU):
                cpts[u + v * nsrf.Points.CountU, 0] = nsrf.Points[u, v].X
                cpts[u + v * nsrf.Points.CountU, 1] = nsrf.Points[u, v].Y
                cpts[u + v * nsrf.Points.CountU, 2] = nsrf.Points[u, v].Z
                if nsrf.IsRational:
                    cpts[u + v * nsrf.Points.CountU, 3] = nsrf.Points[u, v].W

        return Surface(basisu, basisv, cpts, nsrf.IsRational)
Exemplo n.º 10
0
    def test_edge_curves_elasticity(self):
        # create an arrow-like 2D geometry with the pointy end at (-1,1) towards up and left
        # rebuild to avoid rational representations
        c1 = CurveFactory.circle_segment(pi / 2).rebuild(3,11)
        c2 = Curve(BSplineBasis(2, [0, 0, 1, 2, 2]), [[0, 1], [-1, 1], [-1, 0]])
        c3 = CurveFactory.circle_segment(pi / 2).rebuild(3,11)
        c3.rotate(pi)
        c4 = Curve(BSplineBasis(2), [[0, -1], [1, 0]]).rebuild(3,10)
        c4 = c4.rebuild(4,11)

        surf = SurfaceFactory.edge_curves([c1, c2, c3, c4], type='elasticity')

        # check right dimensions of output
        self.assertEqual(surf.shape[0], 11) # 11 controlpoints in the circle segment
        self.assertEqual(surf.shape[1], 13) # 11 controlpoints in c4, +2 for C0-knot in c1
        self.assertEqual(surf.order(0), 3)
        self.assertEqual(surf.order(1), 4)

        # check that c1 edge conforms to surface edge
        u = np.linspace(0,1,7)
        c1.reparam()
        pts_surf = surf(u,0.0)
        pts_c1   = c1(u)
        for (xs,xc) in zip(pts_surf[:,0,:], pts_c1):
            self.assertTrue(np.allclose(xs, xc))

        # check that c2 edge conforms to surface edge
        v = np.linspace(0,1,7)
        c2.reparam()
        pts_surf = surf(1.0,v)
        pts_c2   = c2(v)
        for (xs,xc) in zip(pts_surf[:,0,:], pts_c2):
            self.assertTrue(np.allclose(xs, xc))
Exemplo n.º 11
0
def disc(r=1,
         center=(0, 0, 0),
         normal=(0, 0, 1),
         type='radial',
         xaxis=(1, 0, 0)):
    """  Create a circular disc. The *type* parameter distinguishes between
    different parametrizations.

    :param float r: Radius
    :param array-like center: local origin
    :param array-like normal: local normal
    :param string type: The type of parametrization ('radial' or 'square')
    :param array-like xaxis: direction of sem, i.e. parametric start point v=0
    :return: The disc
    :rtype: Surface
    """
    if type == 'radial':
        c1 = CurveFactory.circle(r, center=center, normal=normal, xaxis=xaxis)
        c2 = flip_and_move_plane_geometry(c1 * 0, center, normal)
        result = edge_curves(c2, c1)
        result.swap()
        result.reparam((0, r), (0, 2 * pi))
        return result
    elif type == 'square':
        w = 1 / sqrt(2)
        cp = [[-r * w, -r * w, 1], [0, -r, w], [r * w, -r * w, 1], [-r, 0, w],
              [0, 0, 1], [r, 0, w], [-r * w, r * w, 1], [0, r, w],
              [r * w, r * w, 1]]
        basis1 = BSplineBasis(3)
        basis2 = BSplineBasis(3)
        result = Surface(basis1, basis2, cp, True)
        return flip_and_move_plane_geometry(result, center, normal)
    else:
        raise ValueError('invalid type argument')
Exemplo n.º 12
0
    def test_evaluate(self):
        # creating the identity mapping by different size for all directions
        vol = Volume(BSplineBasis(7), BSplineBasis(6), BSplineBasis(5))

        # call evaluation at a 2x3x4 grid of points
        u_val = np.linspace(0, 1, 2)
        v_val = np.linspace(0, 1, 3)
        w_val = np.linspace(0, 1, 4)
        value = vol(u_val, v_val, w_val)
        self.assertEqual(value.shape[0], 2)  # 2 u-evaluation points
        self.assertEqual(value.shape[1], 3)  # 3 v-evaluation points
        self.assertEqual(value.shape[2], 4)  # 4 w-evaluation points
        self.assertEqual(value.shape[3], 3)  # 3 dimensions (x,y,z)
        self.assertEqual(vol.order(), (7, 6, 5))
        for i, u in enumerate(u_val):
            for j, v in enumerate(v_val):
                for k, w in enumerate(w_val):
                    self.assertAlmostEqual(value[i, j, k, 0], u)  # identity map x=u
                    self.assertAlmostEqual(value[i, j, k, 1], v)  # identity map y=v
                    self.assertAlmostEqual(value[i, j, k, 2], w)  # identity map z=w

        # test errors and exceptions
        with self.assertRaises(ValueError):
            val = vol(-10, .5, .5)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(+10, .3, .3)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, -10, .123)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, +10, .123)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, .2, +10)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = vol(.5, .2, -10)  # evalaute outside parametric domain
Exemplo n.º 13
0
    def test_surface_loft(self):
        crv1 = Curve(BSplineBasis(3, range(11), 1), [[1,-1], [1,0], [1,1], [-1,1], [-1,0], [-1,-1]])
        crv2 = cf.circle(2) + (0,0,1)
        crv3 = Curve(BSplineBasis(4, range(11), 2), [[1,-1,2], [1,1,2], [-1,1,2], [-1,-1,2]])
        crv4 = cf.circle(2) + (0,0,3)
        surf = sf.loft(crv1, crv2, crv3, crv4)

        crv1.set_dimension(3) # for convenience when evaluating
        t = np.linspace( 0, 1, 13)

        u = np.linspace(crv1.start(0), crv1.end(0), 13)
        pt  = crv1(u)
        pt2 = surf(t,0).reshape(13,3)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)

        u = np.linspace(crv2.start(0), crv2.end(0), 13)
        pt  = crv2(u)
        pt2 = surf(t,1).reshape(13,3)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)

        u = np.linspace(crv3.start(0), crv3.end(0), 13)
        pt  = crv3(u)
        pt2 = surf(t,2).reshape(13,3)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)

        u = np.linspace(crv4.start(0), crv4.end(0), 13)
        pt  = crv4(u)
        pt2 = surf(t,3).reshape(13,3)
        self.assertAlmostEqual(np.linalg.norm(pt-pt2), 0.0)
Exemplo n.º 14
0
    def test_normal(self):
        surf = sf.sphere(1)
        surf.swap()
        u = np.linspace(surf.start(0) + 1e-3, surf.end(0) - 1e-3, 9)
        v = np.linspace(surf.start(1) + 1e-3, surf.end(1) - 1e-3, 9)

        xpts = surf(u, v, tensor=False)
        npts = surf.normal(u, v, tensor=False)

        self.assertEqual(npts.shape, (9, 3))

        # check that the normal is pointing out of the unit ball on a 9x9 evaluation grid
        for (x, n) in zip(xpts, npts):
            self.assertAlmostEqual(n[0], x[0])
            self.assertAlmostEqual(n[1], x[1])
            self.assertAlmostEqual(n[2], x[2])

        xpts = surf(u, v)
        npts = surf.normal(u, v)

        self.assertEqual(npts.shape, (9, 9, 3))

        # check that the normal is pointing out of the unit ball on a 9x9 evaluation grid
        for (i, j) in zip(xpts, npts):
            for (x, n) in zip(i, j):
                self.assertAlmostEqual(n[0], x[0])
                self.assertAlmostEqual(n[1], x[1])
                self.assertAlmostEqual(n[2], x[2])

        # check single value input
        n = surf.normal(0, 0)
        self.assertEqual(len(n), 3)

        # test 2D surface
        s = Surface()
        n = s.normal(.5, .5)
        self.assertEqual(len(n), 3)
        self.assertAlmostEqual(n[0], 0.0)
        self.assertAlmostEqual(n[1], 0.0)
        self.assertAlmostEqual(n[2], 1.0)
        n = s.normal([.25, .5], [.1, .2, .3, .4, .5, .6, .7, .8, .9])
        self.assertEqual(n.shape[0], 2)
        self.assertEqual(n.shape[1], 9)
        self.assertEqual(n.shape[2], 3)
        self.assertAlmostEqual(n[1, 4, 0], 0.0)
        self.assertAlmostEqual(n[1, 4, 1], 0.0)
        self.assertAlmostEqual(n[1, 4, 2], 1.0)

        n = s.normal([.25, .5, .75], [.3, .5, .9], tensor=False)
        self.assertEqual(n.shape, (3, 3))
        for i in range(3):
            for j in range(2):
                self.assertAlmostEqual(n[i, j], 0.0)
            self.assertAlmostEqual(n[i, 2], 1.0)

        # test errors
        s = Surface(BSplineBasis(3), BSplineBasis(3), [[0]] * 9)  # 1D-surface
        with self.assertRaises(RuntimeError):
            s.normal(.5, .5)
Exemplo n.º 15
0
    def test_derivative(self):
        # knot vector [t_1, t_2, ... t_{n+p+1}]
        # polynomial degree p (order-1)
        # n basis functions N_i(t), for i=1...n
        # the power basis {1,t,t^2,t^3,...} can be expressed as:
        # 1     = sum         N_i(t)
        # t     = sum ts_i  * N_i(t)
        # t^2   = sum t2s_i * N_i(t)
        # ts_i  = sum_{j=i+1}^{i+p}   t_j / p
        # t2s_i = sum_{j=i+1}^{i+p-1} sum_{k=j+1}^{i+p} t_j*t_k / (p 2)
        # (p 2) = binomial coefficient

        # creating the mapping:
        #   x(u,v) = u^2*v + u(1-v)
        #   y(u,v) = v
        controlpoints = [[0, 0], [1.0 / 4, 0], [3.0 / 4, 0], [.75, 0], [0, 1],
                         [0, 1], [.5, 1], [1, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .5, 1, 1, 1])
        basis2 = BSplineBasis(2, [0, 0, 1, 1])
        surf = Surface(basis1, basis2, controlpoints)

        # call evaluation at a 5x4 grid of points
        val = surf.derivative([0, .2, .5, .6, 1], [0, .2, .4, 1], d=(1, 0))
        self.assertEqual(len(val.shape),
                         3)  # result should be wrapped in 3-index tensor
        self.assertEqual(val.shape[0], 5)  # 5 evaluation points in u-direction
        self.assertEqual(val.shape[1], 4)  # 4 evaluation points in v-direction
        self.assertEqual(val.shape[2], 2)  # 2 coordinates (x,y)

        self.assertAlmostEqual(surf.derivative(.2, .2, d=(1, 0))[0],
                               .88)  # dx/du=2uv+(1-v)
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(1, 0))[1],
                               0)  # dy/du=0
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(0, 1))[0],
                               -.16)  # dx/dv=u^2-u
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(0, 1))[1],
                               1)  # dy/dv=1
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(1, 1))[0],
                               -.60)  # d2x/dudv=2u-1
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(2, 0))[0],
                               0.40)  # d2x/dudu=2v
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(3, 0))[0],
                               0.00)  # d3x/du3=0
        self.assertAlmostEqual(surf.derivative(.2, .2, d=(0, 2))[0],
                               0.00)  # d2y/dv2=0

        # test errors and exceptions
        with self.assertRaises(ValueError):
            val = surf.derivative(-10,
                                  .5)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = surf.derivative(+10,
                                  .3)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = surf.derivative(.5,
                                  -10)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = surf.derivative(.5,
                                  +10)  # evalaute outside parametric domain
Exemplo n.º 16
0
 def test_reparam(self):
     b = BSplineBasis(5, [-1, 0, 1, 1, 1, 3, 9, 10, 11, 11, 11, 13, 19], periodic=1)
     b.reparam(11, 21)
     expect = [9, 10, 11, 11, 11, 13, 19, 20, 21, 21, 21, 23, 29]
     self.assertAlmostEqual(np.linalg.norm(b.knots - expect), 0)
     b.reparam()
     expect = [-.2, -.1, 0, 0, 0, .2, .8, .9, 1.0, 1.0, 1.0, 1.2, 1.8]
     self.assertAlmostEqual(np.linalg.norm(b.knots - expect), 0)
Exemplo n.º 17
0
 def get_c0_mesh(self):
     # Create the C0-mesh
     nx, ny, nz = self.n
     X = self.raw.get_c0_avg()
     b1 = BSplineBasis(2, [0] + [i/nx for i in range(nx+1)] + [1])
     b2 = BSplineBasis(2, [0] + [i/ny for i in range(ny+1)] + [1])
     b3 = BSplineBasis(2, [0] + [i/nz for i in range(nz+1)] + [1])
     c0_vol = volume_factory.interpolate(X, [b1, b2, b3])
     return c0_vol
Exemplo n.º 18
0
 def get_cm1_mesh(self):
     # Create the C^{-1} mesh
     nx, ny, nz = self.n
     Xm1 = self.raw.get_discontinuous_all()
     b1 = BSplineBasis(2, sorted(list(range(self.n[0]+1))*2))
     b2 = BSplineBasis(2, sorted(list(range(self.n[1]+1))*2))
     b3 = BSplineBasis(2, sorted(list(range(self.n[2]+1))*2))
     discont_vol = Volume(b1, b2, b3, Xm1)
     return discont_vol
Exemplo n.º 19
0
 def get_mixed_cont_mesh(self):
     # Create mixed discontinuity mesh: C^0, C^0, C^{-1}
     nx, ny, nz = self.n
     Xz = self.raw.get_discontinuous_z()
     b1 = BSplineBasis(2, sorted(list(range(self.n[0]+1))+[0,self.n[0]]))
     b2 = BSplineBasis(2, sorted(list(range(self.n[1]+1))+[0,self.n[1]]))
     b3 = BSplineBasis(2, sorted(list(range(self.n[2]+1))*2))
     true_vol = Volume(b1, b2, b3, Xz, raw=True)
     return true_vol
Exemplo n.º 20
0
def loft(*curves):
    if len(curves) == 1:
        curves = curves[0]

    # clone input, so we don't change those references
    # make sure everything has the same dimension since we need to compute length
    curves = [c.clone().set_dimension(3) for c in curves]
    if len(curves)==2:
        return edge_curves(curves)
    elif len(curves)==3:
        # can't do cubic spline interpolation, so we'll do quadratic
        basis2 = BSplineBasis(3)
        dist  = basis2.greville()
    else:
        x = [c.center() for c in curves]

        # create knot vector from the euclidian length between the curves
        dist = [0]
        for (x1,x0) in zip(x[1:],x[:-1]):
            dist.append(dist[-1] + np.linalg.norm(x1-x0))

        # using "free" boundary condition by setting N'''(u) continuous at second to last and second knot
        knot = [dist[0]]*4 + dist[2:-2] + [dist[-1]]*4
        basis2 = BSplineBasis(4, knot)

    n = len(curves)
    for i in range(n):
        for j in range(i+1,n):
            Curve.make_splines_identical(curves[i], curves[j])
    
    basis1 = curves[0].bases[0]
    m      = basis1.num_functions()
    u      = basis1.greville() # parametric interpolation points
    v      = dist              # parametric interpolation points
    
    # compute matrices
    Nu     = basis1(u)
    Nv     = basis2(v)
    Nu_inv = np.linalg.inv(Nu)
    Nv_inv = np.linalg.inv(Nv)

    # compute interpolation points in physical space
    x      = np.zeros((m,n, curves[0][0].size))
    for i in range(n):
        x[:,i,:] = Nu * curves[i].controlpoints

    # solve interpolation problem
    cp = np.tensordot(Nv_inv, x,  axes=(1,1))
    cp = np.tensordot(Nu_inv, cp, axes=(1,1))

    # re-order controlpoints so they match up with Surface constructor
    cp = cp.transpose((1, 0, 2))
    cp = cp.reshape(n*m, cp.shape[2])

    return Surface(basis1, basis2, cp, curves[0].rational)
Exemplo n.º 21
0
def loft(*curves):
    if len(curves) == 1:
        curves = curves[0]

    # clone input, so we don't change those references
    # make sure everything has the same dimension since we need to compute length
    curves = [c.clone().set_dimension(3) for c in curves]
    if len(curves)==2:
        return edge_curves(curves)
    elif len(curves)==3:
        # can't do cubic spline interpolation, so we'll do quadratic
        basis2 = BSplineBasis(3)
        dist  = basis2.greville()
    else:
        x = [c.center() for c in curves]

        # create knot vector from the euclidian length between the curves
        dist = [0]
        for (x1,x0) in zip(x[1:],x[:-1]):
            dist.append(dist[-1] + np.linalg.norm(x1-x0))

        # using "free" boundary condition by setting N'''(u) continuous at second to last and second knot
        knot = [dist[0]]*4 + dist[2:-2] + [dist[-1]]*4
        basis2 = BSplineBasis(4, knot)

    n = len(curves)
    for i in range(n):
        for j in range(i+1,n):
            Curve.make_splines_identical(curves[i], curves[j])

    basis1 = curves[0].bases[0]
    m      = basis1.num_functions()
    u      = basis1.greville() # parametric interpolation points
    v      = dist              # parametric interpolation points

    # compute matrices
    Nu     = basis1(u)
    Nv     = basis2(v)
    Nu_inv = np.linalg.inv(Nu)
    Nv_inv = np.linalg.inv(Nv)

    # compute interpolation points in physical space
    x      = np.zeros((m,n, curves[0][0].size))
    for i in range(n):
        x[:,i,:] = Nu * curves[i].controlpoints

    # solve interpolation problem
    cp = np.tensordot(Nv_inv, x,  axes=(1,1))
    cp = np.tensordot(Nu_inv, cp, axes=(1,1))

    # re-order controlpoints so they match up with Surface constructor
    cp = cp.transpose((1, 0, 2))
    cp = cp.reshape(n*m, cp.shape[2])

    return Surface(basis1, basis2, cp, curves[0].rational)
Exemplo n.º 22
0
def circle_segment(theta,
                   r=1,
                   center=(0, 0, 0),
                   normal=(0, 0, 1),
                   xaxis=(1, 0, 0)):
    """  Create a circle segment starting parallel to the rotated x-axis.

    :param float theta: Angle in radians
    :param float r: Radius
    :param array-like center: circle segment center
    :param array-like normal: normal vector to the plane that contains circle
    :param array-like xaxis: direction of the parametric start point t=0
    :return: A quadratic rational curve
    :rtype: Curve
    :raises ValueError: If radius is not positive
    :raises ValueError: If theta is not in the range *[-2pi, 2pi]*
    """
    # error test input
    if abs(theta) > 2 * pi:
        raise ValueError('theta needs to be in range [-2pi,2pi]')
    if r <= 0:
        raise ValueError('radius needs to be positive')
    if theta == 2 * pi:
        return circle(r, center, normal)

    # build knot vector
    knot_spans = int(ceil(abs(theta) / (2 * pi / 3)))
    knot = [0]
    for i in range(knot_spans + 1):
        knot += [i] * 2
    knot += [knot_spans]  # knot vector [0,0,0,1,1,2,2,..,n,n,n]
    knot = np.array(knot) / float(
        knot[-1]) * theta  # set parametric space to [0,theta]

    n = (knot_spans - 1) * 2 + 3  # number of control points needed
    cp = []
    t = 0  # current angle
    dt = float(theta) / knot_spans / 2  # angle step

    # build control points
    for i in range(n):
        w = 1 - (i % 2) * (1 - cos(dt)
                           )  # weights = 1 and cos(dt) every other i
        x = r * cos(t)
        y = r * sin(t)
        cp += [[x, y, w]]
        t += dt

    if theta < 0:
        cp.reverse()
        result = Curve(BSplineBasis(3, np.flip(knot, 0)), cp, True)
    else:
        result = Curve(BSplineBasis(3, knot), cp, True)
    result.rotate(rotate_local_x_axis(xaxis, normal))
    return flip_and_move_plane_geometry(result, center, normal)
Exemplo n.º 23
0
def image_height(filename, N=[30, 30], p=[4, 4]):
    """Generate a B-spline surface approximation given by the heightmap in a
    grayscale image.

    :param str filename: Name of image file to read
    :param (int,int) N: Number of controlpoints in u-direction
    :param (int,int) p: Polynomial order (degree+1)
    :return: Normalized (all values between 0 and 1) heightmap approximation
    :rtype: :class:`splipy.Surface`
    """

    import cv2

    im = cv2.imread(filename)

    width = len(im)
    height = len(im[0])

    # initialize image holder
    imGrey = np.zeros((len(im), len(im[0])), np.uint8)

    # convert to greyscale image
    if cv2.__version__[0] == '2':
        warnings.warn(
            FutureWarning(
                'openCV v.2 will eventually be discontinued. Please update your version: \"pip install opencv-python --upgrade\"'
            ))
        cv2.cvtColor(im, cv2.cv.CV_RGB2GRAY, imGrey)
    else:
        cv2.cvtColor(im, cv2.COLOR_RGB2GRAY, imGrey)

    pts = []
    # guess uniform evaluation points and knot vectors
    u = range(width)
    v = range(height)
    knot1 = [0] * 3 + range(N[0] - p[0] + 2) + [N[0] - p[0] + 1] * 3
    knot2 = [0] * 3 + range(N[0] - p[0] + 2) + [N[0] - p[0] + 1] * 3

    # normalize all values to be in range [0, 1]
    u = [float(i) / u[-1] for i in u]
    v = [float(i) / v[-1] for i in v]
    knot1 = [float(i) / knot1[-1] for i in knot1]
    knot2 = [float(i) / knot2[-1] for i in knot2]

    for j in range(height):
        for i in range(width):
            pts.append(
                [v[j], u[i],
                 float(imGrey[width - i - 1][j]) / 255.0 * 1.0])

    basis1 = BSplineBasis(4, knot1)
    basis2 = BSplineBasis(4, knot2)

    return surface_factory.least_square_fit(pts, [basis1, basis2], [u, v])
Exemplo n.º 24
0
    def test_evaluate(self):
        # knot vector [t_1, t_2, ... t_{n+p+1}]
        # polynomial degree p (order-1)
        # n basis functions N_i(t), for i=1...n
        # the power basis {1,t,t^2,t^3,...} can be expressed as:
        # 1     = sum         N_i(t)
        # t     = sum ts_i  * N_i(t)
        # t^2   = sum t2s_i * N_i(t)
        # ts_i  = sum_{j=i+1}^{i+p}   t_j / p
        # t2s_i = sum_{j=i+1}^{i+p-1} sum_{k=j+1}^{i+p} t_j*t_k / (p 2)
        # (p 2) = binomial coefficient

        # creating the mapping:
        #   x(u,v) = u^2*v + u(1-v)
        #   y(u,v) = v
        controlpoints = [[0, 0], [1.0 / 4, 0], [3.0 / 4, 0], [.75, 0], [0, 1],
                         [0, 1], [.5, 1], [1, 1]]
        basis1 = BSplineBasis(3, [0, 0, 0, .5, 1, 1, 1])
        basis2 = BSplineBasis(2, [0, 0, 1, 1])
        surf = Surface(basis1, basis2, controlpoints)

        # call evaluation at a 5x4 grid of points
        val = surf([0, .2, .5, .6, 1], [0, .2, .4, 1])
        self.assertEqual(len(val.shape),
                         3)  # result should be wrapped in 3-index tensor
        self.assertEqual(val.shape[0], 5)  # 5 evaluation points in u-direction
        self.assertEqual(val.shape[1], 4)  # 4 evaluation points in v-direction
        self.assertEqual(val.shape[2], 2)  # 2 coordinates (x,y)

        # check evaluation at (0,0)
        self.assertAlmostEqual(val[0][0][0], 0.0)
        self.assertAlmostEqual(val[0][0][1], 0.0)
        # check evaluation at (.2,0)
        self.assertAlmostEqual(val[1][0][0], 0.2)
        self.assertAlmostEqual(val[1][0][1], 0.0)
        # check evaluation at (.2,.2)
        self.assertAlmostEqual(val[1][1][0], 0.168)
        self.assertAlmostEqual(val[1][1][1], 0.2)
        # check evaluation at (.5,.4)
        self.assertAlmostEqual(val[2][2][0], 0.4)
        self.assertAlmostEqual(val[2][2][1], 0.4)
        # check evaluation at (.6,1)
        self.assertAlmostEqual(val[3][3][0], 0.36)
        self.assertAlmostEqual(val[3][3][1], 1)

        # test errors and exceptions
        with self.assertRaises(ValueError):
            val = surf(-10, .5)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = surf(+10, .3)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = surf(.5, -10)  # evalaute outside parametric domain
        with self.assertRaises(ValueError):
            val = surf(.5, +10)  # evalaute outside parametric domain
Exemplo n.º 25
0
 def test_bug44(self):
     # https://github.com/sintefmath/Splipy/issues/44
     b = BSplineBasis(4, [ 0.        , 0.        , 0.        , 0.        , 0.01092385, 0.02200375,
                           0.03316167, 0.04435861, 0.05526295, 0.0663331 , 0.07748615, 0.08868065,
                           0.09989588, 0.11080936, 0.12188408, 0.13303942, 0.14423507, 0.15545087,
                           0.16636463, 0.1774395 , 0.1885949 , 0.19979059, 0.2       , 0.2       ,
                           0.2       , 0.2     ])
     grvl = b.greville()
     # last greville point is 0.20000000000000004, and technically outside domain [0,.2]
     self.assertAlmostEqual(grvl[-1], 0.2)
     # should snap to 0.2 and evaluate to 1 for the last function
     self.assertAlmostEqual(b(grvl[-1])[-1,-1], 1.0)
Exemplo n.º 26
0
 def test_bug44(self):
     # https://github.com/sintefmath/Splipy/issues/44
     b = BSplineBasis(4, [ 0.        , 0.        , 0.        , 0.        , 0.01092385, 0.02200375,
                           0.03316167, 0.04435861, 0.05526295, 0.0663331 , 0.07748615, 0.08868065,
                           0.09989588, 0.11080936, 0.12188408, 0.13303942, 0.14423507, 0.15545087,
                           0.16636463, 0.1774395 , 0.1885949 , 0.19979059, 0.2       , 0.2       ,
                           0.2       , 0.2     ])
     grvl = b.greville()
     # last greville point is 0.20000000000000004, and technically outside domain [0,.2]
     self.assertAlmostEqual(grvl[-1], 0.2)
     # should snap to 0.2 and evaluate to 1 for the last function
     self.assertAlmostEqual(b(grvl[-1])[-1,-1], 1.0)
Exemplo n.º 27
0
def circle(r=1, center=(0,0,0), normal=(0,0,1), type='p2C0', xaxis=(1,0,0)):
    """  Create a circle.

    :param float r: Radius
    :param array-like center: local origin
    :param array-like normal: local normal
    :param string type: The type of parametrization ('p2C0' or 'p4C1')
    :param array-like xaxis: direction of sem, i.e. parametric start point t=0
    :return: A periodic, quadratic rational curve
    :rtype: Curve
    :raises ValueError: If radius is not positive
    """
    if r <= 0:
        raise ValueError('radius needs to be positive')

    if type == 'p2C0' or type == 'C0p2':
        w = 1.0 / sqrt(2)
        controlpoints = [[1, 0, 1],
                         [w, w, w],
                         [0, 1, 1],
                         [-w, w, w],
                         [-1, 0, 1],
                         [-w, -w, w],
                         [0, -1, 1],
                         [w, -w, w]]
        knot = np.array([-1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]) / 4.0 * 2 * pi

        result = Curve(BSplineBasis(3, knot, 0), controlpoints, True)
    elif type.lower() == 'p4c1' or type.lower() == 'c1p4':
        w = 2*sqrt(2)/3
        a = 1.0/2/sqrt(2)
        b = 1.0/6 * (4*sqrt(2)-1)
        controlpoints = [[ 1,-a, 1],
                         [ 1, a, 1],
                         [ b, b, w],
                         [ a, 1, 1],
                         [-a, 1, 1],
                         [-b, b, w],
                         [-1, a, 1],
                         [-1,-a, 1],
                         [-b,-b, w],
                         [-a,-1, 1],
                         [ a,-1, 1],
                         [ b,-b, w]]
        knot = np.array([ -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5]) / 4.0 * 2 * pi
        result = Curve(BSplineBasis(5, knot, 1), controlpoints, True)
    else:
        raise ValueError('Unkown type: %s' %(type))

    result *= r
    result.rotate(rotate_local_x_axis(xaxis, normal))
    return flip_and_move_plane_geometry(result, center, normal)
Exemplo n.º 28
0
    def test_periodic_boundary_evaluation(self):
        # Issue #66: "From left evaluations crash on periodic basis"
        b = BSplineBasis(3, [0,0,0,1,2,3,4,4,4])
        x = b.evaluate(t=0, from_right=False)
        self.assertAlmostEqual(x[0,0], 0.0)

        x = b.evaluate(t=0, from_right=True)
        self.assertAlmostEqual(x[0,0], 1.0)

        b = BSplineBasis(3, [-1,0,0,1,2,3,4,4,5], periodic=0)
        x = b.evaluate(t=0, d=1, from_right=False)
        self.assertAlmostEqual(x[0, 0],  2.0)
        self.assertAlmostEqual(x[0,-1], -2.0)
Exemplo n.º 29
0
    def test_constructor(self):
        # test 3D constructor
        cp = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]]
        surf = Surface(controlpoints=cp)
        val = surf(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf[0]), 3)

        # test 2D constructor
        cp = [[0, 0], [1, 0], [0, 1], [1, 1]]
        surf2 = Surface(controlpoints=cp)
        val = surf2(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf2[0]), 2)

        # test rational 2D constructor
        cp = [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
        surf3 = Surface(controlpoints=cp, rational=True)
        val = surf3(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf3[0]), 3)

        # test rational 3D constructor
        cp = [[0, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1], [1, 1, 0, 1]]
        surf4 = Surface(controlpoints=cp, rational=True)
        val = surf4(0.5, 0.5)
        self.assertEqual(val[0], 0.5)
        self.assertEqual(len(surf4[0]), 4)

        # test constructor with single basis
        b = BSplineBasis(4)
        surf = Surface(b, b)
        surf.insert_knot(.3, 'u')  # change one, but not the other
        self.assertEqual(len(surf.knots('u')), 3)
        self.assertEqual(len(surf.knots('v')), 2)

        # TODO: Include a default constructor specifying nothing, or just polynomial degrees, or just knot vectors.
        #       This should create identity mappings

        # test errors and exceptions
        controlpoints = [[0, 0, 1], [1, 0, 1], [0, 1, 1], [1, 1, 1]]
        with self.assertRaises(ValueError):
            basis1 = BSplineBasis(2, [1, 1, 0, 0])
            basis2 = BSplineBasis(2, [0, 0, 1, 1])
            surf = Surface(basis1, basis2,
                           controlpoints)  # illegal knot vector
        with self.assertRaises(ValueError):
            basis1 = BSplineBasis(2, [0, 0, .5, 1, 1])
            basis2 = BSplineBasis(2, [0, 0, 1, 1])
            surf = Surface(basis1, basis2,
                           controlpoints)  # too few controlpoints
Exemplo n.º 30
0
 def test_snap(self):
     b = BSplineBasis(3, [0,0,0, .123, np.pi, 3.5, 4,4,4])
     t = [0,.123+1e-12, 3, 3.1, 3.14, 3.1415, 3.1415926, 3.500000000000002, 4+1e-12, 4+1e-2]
     b.snap(t)
     self.assertEqual(   t[0], b[0]) # 0
     self.assertEqual(   t[1], b[3]) # 0.123
     self.assertNotEqual(t[2], b[4]) # 3
     self.assertNotEqual(t[3], b[4]) # 3.1
     self.assertNotEqual(t[4], b[4]) # 3.14
     self.assertNotEqual(t[5], b[4]) # 3.1415
     self.assertNotEqual(t[6], b[4]) # 3.1415926
     self.assertEqual(   t[7], b[5]) # 3.5
     self.assertEqual(   t[8], b[6]) # 4.0
     self.assertNotEqual(t[9], b[6]) # 4.01
Exemplo n.º 31
0
 def test_snap(self):
     b = BSplineBasis(3, [0,0,0, .123, np.pi, 3.5, 4,4,4])
     t = [0,.123+1e-12, 3, 3.1, 3.14, 3.1415, 3.1415926, 3.500000000000002, 4+1e-12, 4+1e-2]
     b.snap(t)
     self.assertEqual(   t[0], b[0]) # 0
     self.assertEqual(   t[1], b[3]) # 0.123
     self.assertNotEqual(t[2], b[4]) # 3
     self.assertNotEqual(t[3], b[4]) # 3.1
     self.assertNotEqual(t[4], b[4]) # 3.14
     self.assertNotEqual(t[5], b[4]) # 3.1415
     self.assertNotEqual(t[6], b[4]) # 3.1415926
     self.assertEqual(   t[7], b[5]) # 3.5
     self.assertEqual(   t[8], b[6]) # 4.0
     self.assertNotEqual(t[9], b[6]) # 4.01
Exemplo n.º 32
0
 def test_start_end(self):
     b = BSplineBasis(4, [-2, -1, 0, 0, 1, 2, 3, 3, 4, 5], periodic=1)
     self.assertAlmostEqual(b.start(), 0)
     self.assertAlmostEqual(b.end(),   3)
     b = BSplineBasis(3, [0, 1, 1, 2, 3, 4, 4, 6])
     self.assertAlmostEqual(b.start(), 1)
     self.assertAlmostEqual(b.end(),   4)
Exemplo n.º 33
0
    def test_swap(self):
        # more or less random 3D volume with p=[3,2,1] and n=[4,3,2]
        controlpoints = [[0, 0, 1], [-1, 1, 1], [0, 2, 1], [1, -1,
                                                            2], [1, 0, 2],
                         [1, 1, 2], [2, 1, 2], [2, 2, 2], [2, 3, 2], [3, 0, 0],
                         [4, 1, 0], [3, 2, 0], [0, 0, 3], [-1, 1,
                                                           3], [0, 2, 3],
                         [1, -1, 5], [1, 0, 5], [1, 1, 5], [2, 1, 4],
                         [2, 2, 4], [2, 3, 4], [3, 0, 2], [4, 1, 2], [3, 2, 2]]
        basis1 = BSplineBasis(4, [0, 0, 0, 0, 2, 2, 2, 2])
        basis2 = BSplineBasis(3, [0, 0, 0, 1, 1, 1])
        basis3 = BSplineBasis(2, [0, 0, 1, 1])
        vol = Volume(basis1, basis2, basis3, controlpoints)

        evaluation_point1 = vol(0.23, .56, .12)
        control_point1 = vol[
            1]  # this is control point i=(1,0,0), when n=(4,3,2)
        self.assertEqual(vol.order(), (4, 3, 2))
        vol.swap(0, 1)
        evaluation_point2 = vol(0.56, .23, .12)
        control_point2 = vol[
            3]  # this is control point i=(0,1,0), when n=(3,4,2)
        self.assertEqual(vol.order(), (3, 4, 2))

        # ensure that volume has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point2[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point2[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point2[2])

        # check that the control points have re-ordered themselves
        self.assertEqual(control_point1[0], control_point2[0])
        self.assertEqual(control_point1[1], control_point2[1])
        self.assertEqual(control_point1[2], control_point2[2])

        vol.swap(1, 2)
        evaluation_point3 = vol(.56, .12, .23)
        control_point3 = vol[
            6]  # this is control point i=(0,0,1), when n=(3,2,4)
        self.assertEqual(vol.order(), (3, 2, 4))

        # ensure that volume has not chcanged, by comparing evaluation of it
        self.assertAlmostEqual(evaluation_point1[0], evaluation_point3[0])
        self.assertAlmostEqual(evaluation_point1[1], evaluation_point3[1])
        self.assertAlmostEqual(evaluation_point1[2], evaluation_point3[2])

        # check that the control points have re-ordered themselves
        self.assertEqual(control_point1[0], control_point3[0])
        self.assertEqual(control_point1[1], control_point3[1])
        self.assertEqual(control_point1[2], control_point3[2])
Exemplo n.º 34
0
    def test_evaluate_nontensor(self):
        vol = Volume(BSplineBasis(7), BSplineBasis(7), BSplineBasis(5))

        u_val = [0, 0.1, 0.9, 0.3]
        v_val = [0.2, 0.3, 0.9, 0.4]
        w_val = [0.3, 0.5, 0.5, 0.0]
        value = vol(u_val, v_val, w_val, tensor=False)

        self.assertEqual(value.shape[0], 4)
        self.assertEqual(value.shape[1], 3)

        for i, (u, v, w) in enumerate(zip(u_val, v_val, w_val)):
            self.assertAlmostEqual(value[i, 0], u)  # identity map x=u
            self.assertAlmostEqual(value[i, 1], v)  # identity map y=v
            self.assertAlmostEqual(value[i, 2], w)  # identity map z=w
Exemplo n.º 35
0
def image_height(filename, N=[30, 30], p=[4, 4]):
    """Generate a B-spline surface approximation given by the heightmap in a
    grayscale image.

    :param str filename: Name of image file to read
    :param (int,int) N: Number of controlpoints in u-direction
    :param (int,int) p: Polynomial order (degree+1)
    :return: Normalized (all values between 0 and 1) heightmap approximation
    :rtype: :class:`splipy.Surface`
    """

    import cv2

    im = cv2.imread(filename)

    width = len(im[0])
    height = len(im)

    # initialize image holder
    imGrey = np.zeros((height, width), np.uint8)

    # convert to greyscale image
    cv2.cvtColor(im, cv2.COLOR_RGB2GRAY, imGrey)

    # guess uniform evaluation points and knot vectors
    u = list(range(width))
    v = list(range(height))
    knot1 = [0] * (p[0] - 1) + list(
        range(N[0] - p[0] + 2)) + [N[0] - p[0] + 1] * (p[0] - 1)
    knot2 = [0] * (p[1] - 1) + list(
        range(N[1] - p[1] + 2)) + [N[1] - p[1] + 1] * (p[1] - 1)

    # normalize all values to be in range [0, 1]
    u = [float(i) / u[-1] for i in u]
    v = [float(i) / v[-1] for i in v]
    knot1 = [float(i) / knot1[-1] for i in knot1]
    knot2 = [float(i) / knot2[-1] for i in knot2]

    # flip and reverse image so coordinate (0,0) is at lower-left corner
    imGrey = imGrey.T / 255.0
    imGrey = np.flip(imGrey, axis=1)
    x, y = np.meshgrid(u, v, indexing='ij')
    pts = np.stack([x, y, imGrey], axis=2)

    basis1 = BSplineBasis(p[0], knot1)
    basis2 = BSplineBasis(p[1], knot2)

    return surface_factory.least_square_fit(pts, [basis1, basis2], [u, v])
Exemplo n.º 36
0
 def test_curve_interpolation(self):
     basis = BSplineBasis(4, [0, 0, 0, 0, .3, .9, 1, 1, 1, 1])
     t = np.array(basis.greville())
     # create the mapping (x,y,z)=(t^2, 1-t, t^3+2*t)
     x_pts = np.zeros((len(t), 3))
     x_pts[:, 0] = t * t
     x_pts[:, 1] = 1 - t
     x_pts[:, 2] = t * t * t + 2 * t
     crv = cf.interpolate(x_pts, basis)
     self.assertEqual(crv.order(0), 4)
     self.assertAlmostEqual(crv(.4)[0], .4**2)  # x=t^2
     self.assertAlmostEqual(crv(.4)[1], 1 - .4)  # y=1-t
     self.assertAlmostEqual(crv(.4)[2], .4**3 + 2 * .4)  # z=t^3+2t
     self.assertAlmostEqual(crv(.5)[0], .5**2)  # x=t^2
     self.assertAlmostEqual(crv(.5)[1], 1 - .5)  # y=1-t
     self.assertAlmostEqual(crv(.5)[2], .5**3 + 2 * .5)  # z=t^3+2t
Exemplo n.º 37
0
 def test_curve_interpolation(self):
     basis = BSplineBasis(4, [0, 0, 0, 0, .3, .9, 1, 1, 1, 1])
     t = np.array(basis.greville())
     # create the mapping (x,y,z)=(t^2, 1-t, t^3+2*t)
     x_pts = np.zeros((len(t), 3))
     x_pts[:, 0] = t * t
     x_pts[:, 1] = 1 - t
     x_pts[:, 2] = t * t * t + 2 * t
     crv = CurveFactory.interpolate(x_pts, basis)
     self.assertEqual(crv.order(0), 4)
     self.assertAlmostEqual(crv(.4)[0], .4**2)  # x=t^2
     self.assertAlmostEqual(crv(.4)[1], 1 - .4)  # y=1-t
     self.assertAlmostEqual(crv(.4)[2], .4**3 + 2 * .4)  # z=t^3+2t
     self.assertAlmostEqual(crv(.5)[0], .5**2)  # x=t^2
     self.assertAlmostEqual(crv(.5)[1], 1 - .5)  # y=1-t
     self.assertAlmostEqual(crv(.5)[2], .5**3 + 2 * .5)  # z=t^3+2t
Exemplo n.º 38
0
    def test_make_periodic(self):
        b = BSplineBasis(4, [1,1,1,1,2,3,4,5,5,5,5])

        c = b.make_periodic(0)
        self.assertEqual(c.periodic, 0)
        self.assertEqual(c.order, 4)
        self.assertAlmostEqual(c.knots[0], 0)
        self.assertAlmostEqual(c.knots[1], 1)
        self.assertAlmostEqual(c.knots[2], 1)
        self.assertAlmostEqual(c.knots[3], 1)
        self.assertAlmostEqual(c.knots[4], 2)
        self.assertAlmostEqual(c.knots[5], 3)
        self.assertAlmostEqual(c.knots[6], 4)
        self.assertAlmostEqual(c.knots[7], 5)
        self.assertAlmostEqual(c.knots[8], 5)
        self.assertAlmostEqual(c.knots[9], 5)
        self.assertAlmostEqual(c.knots[10], 6)

        c = b.make_periodic(1)
        self.assertEqual(c.periodic, 1)
        self.assertEqual(c.order, 4)
        self.assertAlmostEqual(c.knots[0], -1)
        self.assertAlmostEqual(c.knots[1], 0)
        self.assertAlmostEqual(c.knots[2], 1)
        self.assertAlmostEqual(c.knots[3], 1)
        self.assertAlmostEqual(c.knots[4], 2)
        self.assertAlmostEqual(c.knots[5], 3)
        self.assertAlmostEqual(c.knots[6], 4)
        self.assertAlmostEqual(c.knots[7], 5)
        self.assertAlmostEqual(c.knots[8], 5)
        self.assertAlmostEqual(c.knots[9], 6)
        self.assertAlmostEqual(c.knots[10], 7)

        c = b.make_periodic(2)
        self.assertEqual(c.periodic, 2)
        self.assertEqual(c.order, 4)
        self.assertAlmostEqual(c.knots[0], -2)
        self.assertAlmostEqual(c.knots[1], -1)
        self.assertAlmostEqual(c.knots[2], 0)
        self.assertAlmostEqual(c.knots[3], 1)
        self.assertAlmostEqual(c.knots[4], 2)
        self.assertAlmostEqual(c.knots[5], 3)
        self.assertAlmostEqual(c.knots[6], 4)
        self.assertAlmostEqual(c.knots[7], 5)
        self.assertAlmostEqual(c.knots[8], 6)
        self.assertAlmostEqual(c.knots[9], 7)
        self.assertAlmostEqual(c.knots[10], 8)
Exemplo n.º 39
0
    def test_lower_order(self):
        b = BSplineBasis(4, [0,0,0,0,.2, .3, .3, .6, .9, 1,1,1,1])
        t = b.greville()
        Y, X, Z = np.meshgrid(t,t,t)
        cp = np.zeros((len(t), len(t), len(t), 3))
        cp[...,0] = X*(1-Y)
        cp[...,1] = X*X
        cp[...,2] = Z**2 + 2

        vol  = VolumeFactory.interpolate(cp, [b,b,b])
        vol2 = vol.lower_order(1) # still in space, vol2 is *also* exact
        u = np.linspace(0,1, 5)
        v = np.linspace(0,1, 6)
        w = np.linspace(0,1, 7)
        self.assertTrue(np.allclose( vol(u,v,w), vol2(u,v,w) ))
        self.assertTupleEqual(vol.order(), (4,4,4))
        self.assertTupleEqual(vol2.order(), (3,3,3))
Exemplo n.º 40
0
    def test_lower_order(self):
        basis = BSplineBasis(4, [0,0,0,0,.2, .3, .3, .6, .9, 1,1,1,1])
        interp_pts = basis.greville()
        x = [[t*(1-t), t**2] for t in interp_pts]
        
        crv = CurveFactory.interpolate(x, basis) # function in space, exact representation kept

        crv2 = crv.lower_order(1) # still in space, crv2 is *also* exact

        t = np.linspace(0,1, 13)
        self.assertTrue(np.allclose( crv(t), crv2(t)) )
        self.assertEqual(crv.order(0),  4)
        self.assertEqual(crv2.order(0), 3)
        self.assertEqual(crv.continuity(0.3),  1)
        self.assertEqual(crv.continuity(0.6),  2)
        self.assertEqual(crv2.continuity(0.3), 1)
        self.assertEqual(crv2.continuity(0.6), 1)
Exemplo n.º 41
0
    def test_raise_order(self):
        # test normal knot vector
        b  = BSplineBasis(4, [0, 0, 0, 0, 1, 2, 3, 3, 3, 3])
        b2 = b.raise_order(2)
        expect =  [0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3]
        self.assertAlmostEqual(np.linalg.norm(b2.knots - expect), 0)
        self.assertEqual(b2.order, 6)

        # test periodic knot vector
        b = BSplineBasis(5, [-1, 0, 1, 1, 1, 3, 9, 10, 11, 11, 11, 13, 19], periodic=1)
        b2 = b.raise_order(1)
        expect =  [0, 0, 1, 1, 1, 1, 3, 3, 9, 9, 10, 10, 11, 11, 11, 11, 13, 13]
        self.assertAlmostEqual(np.linalg.norm(b2.knots - expect), 0)
        self.assertEqual(b2.order,    6)
        self.assertEqual(b2.periodic, 1)

        with self.assertRaises(ValueError):
            BSplineBasis().raise_order(-1)
Exemplo n.º 42
0
 def test_roll(self):
     b = BSplineBasis(4, [-2, -1, -1, 0, 2, 4, 6.5, 7, 8, 8, 9, 11, 13, 15.5], periodic=2)
     b.roll(3)
     self.assertEqual(len(b.knots), 14)
     self.assertAlmostEqual(b.knots[0], 0)
     self.assertAlmostEqual(b.knots[1], 2)
     self.assertAlmostEqual(b.knots[2], 4)
     self.assertAlmostEqual(b.knots[3], 6.5)
     self.assertAlmostEqual(b.knots[4], 7)
     self.assertAlmostEqual(b.knots[5], 8)
     self.assertAlmostEqual(b.knots[6], 8)
     self.assertAlmostEqual(b.knots[7], 9)
     self.assertAlmostEqual(b.knots[8], 11)
     self.assertAlmostEqual(b.knots[9], 13)
     self.assertAlmostEqual(b.knots[10], 15.5)
     self.assertAlmostEqual(b.knots[11], 16)
     self.assertAlmostEqual(b.knots[12], 17)
     self.assertAlmostEqual(b.knots[13], 17)
Exemplo n.º 43
0
def camber(M, P, order=5):
    """ Create the NACA centerline used for wing profiles. This is given as
    an exact quadratic piecewise polynomial y(x),
    see http://airfoiltools.com/airfoil/naca4digit. The method will produce
    one of two representations: For order<5 it will create x(t)=t and
    for order>4 it will create x(t) as qudratic in t and stretched towards the
    endpointspoints creating a more optimized parametrization.
    :param M: Max camber height (y) given as percentage 0% to 9% of length
    :type  M: Int 0<M<10
    :param P: Max camber position (x) given as percentage 0% to 90% of length
    :type  P: Int 0<P<10
    :return : Exact centerline representation
    :rtype  : Curve
    """
    # parametrized by x=t or x="t^2" if order>4
    M = M / 100.0
    P = P / 10.0
    basis = BSplineBasis(order)
    # basis.insert_knot([P]*(order-2)) # insert a C1-knot
    for i in range(order - 2):
        basis.insert_knot(P)

    t = basis.greville()
    n = len(t)
    x = np.zeros((n, 2))
    for i in range(n):
        if t[i] <= P:
            if order > 4:
                x[i, 0] = t[i]**2 / P
            else:
                x[i, 0] = t[i]
            x[i, 1] = M / P / P * (2 * P * x[i, 0] - x[i, 0] * x[i, 0])
        else:
            if order > 4:
                x[i, 0] = (t[i]**2 - 2 * t[i] + P) / (P - 1)
            else:
                x[i, 0] = t[i]
            x[i, 1] = M / (1 - P) / (1 - P) * (1 - 2 * P + 2 * P * x[i, 0] - x[i, 0] * x[i, 0])
    N = basis.evaluate(t)
    controlpoints = np.linalg.solve(N, x)
    return Curve(basis, controlpoints)
Exemplo n.º 44
0
 def test_start_end(self):
     b = BSplineBasis(4, [-2, -1, 0, 0, 1, 2, 3, 3, 4, 5], periodic=1)
     self.assertAlmostEqual(b.start(), 0)
     self.assertAlmostEqual(b.end(),   3)
     b = BSplineBasis(3, [0, 1, 1, 2, 3, 4, 4, 6])
     self.assertAlmostEqual(b.start(), 1)
     self.assertAlmostEqual(b.end(),   4)
Exemplo n.º 45
0
    def test_roll(self):
        b = BSplineBasis(3, [-1, 0, 0, 2, 3, 4, 4, 6], periodic=0)
        b.roll(3)
        expect = [0, 2, 3, 4, 4, 6, 7, 8]
        self.assertAlmostEqual(np.linalg.norm(b.knots - expect), 0)
        b.roll(2)
        expect = [2, 3, 4, 4, 6, 7, 8, 8]
        self.assertAlmostEqual(np.linalg.norm(b.knots - expect), 0)

        with self.assertRaises(IndexError):
            b.roll(19)
Exemplo n.º 46
0
 def test_get_continuity(self):
     b = BSplineBasis(4, [0, 0, 0, 0, .3, 1, 1, 1.134, 1.134, 1.134, 2, 2, 2, 2])
     self.assertEqual(b.continuity(.3), 2)
     self.assertEqual(b.continuity(1), 1)
     self.assertEqual(b.continuity(1.134), 0)
     self.assertEqual(b.continuity(0), -1)
     self.assertEqual(b.continuity(2), -1)
     self.assertEqual(b.continuity(.4), np.inf)
Exemplo n.º 47
0
 def test_reverse(self):
     b = BSplineBasis(3, [0,0,0,1,3,3,6,10,15,21,21,21])
     b.reverse()
     expect = [0,0,0,6,11,15,18,18,20,21,21,21]
     self.assertAlmostEqual(np.linalg.norm(b.knots - expect), 0)
Exemplo n.º 48
0
def loft(*surfaces):
    if len(surfaces) == 1:
        surfaces = surfaces[0]

    # clone input, so we don't change those references
    # make sure everything has the same dimension since we need to compute length
    surfaces = [s.clone().set_dimension(3) for s in surfaces]
    if len(surfaces)==2:
        return SurfaceFactory.edge_curves(surfaces)
    elif len(surfaces)==3:
        # can't do cubic spline interpolation, so we'll do quadratic
        basis3 = BSplineBasis(3)
        dist  = basis3.greville()
    else:
        x = [s.center() for s in surfaces]

        # create knot vector from the euclidian length between the surfaces
        dist = [0]
        for (x1,x0) in zip(x[1:],x[:-1]):
            dist.append(dist[-1] + np.linalg.norm(x1-x0))

        # using "free" boundary condition by setting N'''(u) continuous at second to last and second knot
        knot = [dist[0]]*4 + dist[2:-2] + [dist[-1]]*4
        basis3 = BSplineBasis(4, knot)

    n = len(surfaces)
    for i in range(n):
        for j in range(i+1,n):
            Surface.make_splines_identical(surfaces[i], surfaces[j])

    basis1 = surfaces[0].bases[0]
    basis2 = surfaces[0].bases[1]
    m1     = basis1.num_functions()
    m2     = basis2.num_functions()
    dim    = len(surfaces[0][0])
    u      = basis1.greville() # parametric interpolation points
    v      = basis2.greville()
    w      = dist

    # compute matrices
    Nu     = basis1(u)
    Nv     = basis2(v)
    Nw     = basis3(w)
    Nu_inv = np.linalg.inv(Nu)
    Nv_inv = np.linalg.inv(Nv)
    Nw_inv = np.linalg.inv(Nw)

    # compute interpolation points in physical space
    x      = np.zeros((m1,m2,n, dim))
    for i in range(n):
        tmp        = np.tensordot(Nv, surfaces[i].controlpoints, axes=(1,1))
        x[:,:,i,:] = np.tensordot(Nu, tmp                      , axes=(1,1))

    # solve interpolation problem
    cp = np.tensordot(Nw_inv, x,  axes=(1,2))
    cp = np.tensordot(Nv_inv, cp, axes=(1,2))
    cp = np.tensordot(Nu_inv, cp, axes=(1,2))

    # re-order controlpoints so they match up with Surface constructor
    cp = np.reshape(cp.transpose((2, 1, 0, 3)), (m1*m2*n, dim))

    return Volume(basis1, basis2, basis3, cp, surfaces[0].rational)
Exemplo n.º 49
0
 def test_greville(self):
     b = BSplineBasis(4, [0, 0, 0, 0, 1, 2, 3, 3, 3, 3])
     self.assertAlmostEqual(b.greville(0), 0.0)
     self.assertAlmostEqual(b.greville(1), 1.0 / 3.0)
     self.assertAlmostEqual(b.greville(2), 1.0)
     self.assertAlmostEqual(b.greville(), [0.0, 1.0/3.0, 1.0, 2.0, 8.0/3.0, 3.0])
Exemplo n.º 50
0
def cubic_curve(x, boundary=Boundary.FREE, t=None, tangents=None):
    """cubic_curve(x, [boundary=Boundary.FREE], [t=None], [tangents=None])

    Perform cubic spline interpolation on a provided basis.

    The valid boundary conditions are enumerated in :class:`Boundary`. The
    meaning of the `tangents` parameter depends on the specified boundary
    condition:

    - `TANGENT`: two points,
    - `TANGENTNATURAL`: one point,
    - `HERMITE`: *n* points

    :param matrix-like x: Matrix *X[i,j]* of interpolation points *x_i* with
        components *j*
    :param int boundary: Any value from :class:`Boundary`.
    :param array-like t: parametric values at interpolation points, defaults
        to Euclidean distance between evaluation points
    :param matrix-like tangents: Tangent information according to the boundary
        conditions.
    :return: Interpolated curve
    :rtype: Curve
    """

    # special case periodic curves to both allow repeated start/end or not
    if boundary == Boundary.PERIODIC and (
       np.allclose(x[0,:], x[-1,:],
                   rtol = state.controlpoint_relative_tolerance,
                   atol = state.controlpoint_absolute_tolerance)):
        # count the seam (start/end point) as only one point, otherwise the
        # interpolation matrix will have two identical rows corresponding to
        # this point
        x = x[:-1,:]
        if t is not None:
            t = t[:-1]

    n = len(x)
    if t is None:
        t = [0.0]
        for (x0,x1) in zip(x[:-1,:], x[1:,:]):
            # eucledian distance between two consecutive points 
            dist = np.linalg.norm(np.array(x1)-np.array(x0))
            t.append(t[-1]+dist)

    # modify knot vector for chosen boundary conditions
    knot = [t[0]]*3 + list(t) + [t[-1]]*3
    if boundary == Boundary.FREE:
        del knot[-5]
        del knot[4]
    elif boundary == Boundary.HERMITE:
        knot = sorted(knot + t[1:-1])

    # create the interpolation basis and interpolation matrix on this
    if boundary == Boundary.PERIODIC:
        knot[0]  = t[-3] - t[-1]
        knot[1]  = t[-2] - t[-1]
        knot[-2] = t[-1] + t[1]
        knot[-1] = t[-1] + t[2]
        basis = BSplineBasis(4, knot, 1)
        # since we can't interpolate at the end and start simultaneously, we
        # have to resample the interpolation points. We use the greville points
        t = basis.greville()
    else:
        basis = BSplineBasis(4, knot)
    N = basis(t)  # left-hand-side matrix

    # add derivative boundary conditions if applicable
    if boundary in [Boundary.TANGENT, Boundary.HERMITE, Boundary.TANGENTNATURAL]:
        if boundary == Boundary.TANGENT:
            dn = basis([t[0], t[-1]], d=1)
            N  = np.resize(N, (N.shape[0]+2, N.shape[1]))
            x  = np.resize(x, (x.shape[0]+2, x.shape[1]))
        elif boundary == Boundary.TANGENTNATURAL:
            dn = basis(t[0], d=1)
            N  = np.resize(N, (N.shape[0]+1, N.shape[1]))
            x  = np.resize(x, (x.shape[0]+1, x.shape[1]))
        elif boundary == Boundary.HERMITE:
            dn = getBasis(t, d=1)
            N  = np.resize(N, (N.shape[0]+n, N.shape[1]))
            x  = np.resize(x, (x.shape[0]+n, x.shape[1]))
        x[n:,:] = tangents
        N[n:,:] = dn

    # add double derivative boundary conditions if applicable
    if boundary in [Boundary.NATURAL, Boundary.TANGENTNATURAL]:
        if boundary == Boundary.NATURAL:
            ddn  = basis([t[0], t[-1]], d=2)
            new  = 2
        elif boundary == Boundary.TANGENTNATURAL:
            ddn  = basis(t[-1], d=2)
            new  = 1
        N  = np.resize(N, (N.shape[0]+new, N.shape[1]))
        x  = np.resize(x, (x.shape[0]+new, x.shape[1]))
        N[-new:,:] = ddn
        x[-new:,:] = 0

    # solve system to get controlpoints
    cp = np.linalg.solve(N,x)

    # wrap it all into a curve and return
    return Curve(basis, cp)
Exemplo n.º 51
0
 def test_num_functions(self):
     b = BSplineBasis(4, [0, 0, 0, 0, 1, 2, 3, 3, 3, 3])
     self.assertEqual(b.num_functions(), 6)
     b = BSplineBasis(4, [-2, -1, 0, 0, 1, 2, 3, 3, 4, 5], periodic=1)
     self.assertEqual(b.num_functions(), 4)
Exemplo n.º 52
0
    def test_integrate(self):
        # create the linear functions x(t) = [1-t, t] on t=[0,1]
        b = BSplineBasis()
        self.assertAlmostEqual(b.integrate(0,1)[0], 0.5)
        self.assertAlmostEqual(b.integrate(0,1)[1], 0.5)
        self.assertAlmostEqual(b.integrate(.25,.5)[0], 5.0/32)
        self.assertAlmostEqual(b.integrate(.25,.5)[1], 3.0/32)

        # create the quadratic functions x(t) = [(1-t)^2, 2t(1-t), t^2] on t=[0,1]
        b = BSplineBasis(3)
        self.assertAlmostEqual(b.integrate(0,1)[0], 1.0/3)
        self.assertAlmostEqual(b.integrate(0,1)[1], 1.0/3)
        self.assertAlmostEqual(b.integrate(0,1)[2], 1.0/3)
        self.assertAlmostEqual(b.integrate(.25,.5)[0], 19.0/192)
        self.assertAlmostEqual(b.integrate(.25,.5)[1], 11.0/96)
        self.assertAlmostEqual(b.integrate(.25,.5)[2], 7.0/192)

        # create periodic quadratic functions on [0,3]. This is 3 functions, which are all
        # translated versions of the one below:
        #        | 1/2 t^2          t=[0,1]
        # N[3] = { -t^2 + 3t - 3/2  t=[1,2]
        #        | 1/2 (3-t)^2      t=[2,3]
        b = BSplineBasis(3, [-2,-1,0,1,2,3,4,5], periodic=1)
        self.assertEqual(len(b.integrate(0,3)), 3) # returns 3 functions
        self.assertAlmostEqual(b.integrate(0,3)[0], 1)
        self.assertAlmostEqual(b.integrate(0,3)[1], 1)
        self.assertAlmostEqual(b.integrate(0,3)[2], 1)
        self.assertAlmostEqual(b.integrate(0,1)[0], 1.0/6)
        self.assertAlmostEqual(b.integrate(0,1)[1], 2.0/3)
        self.assertAlmostEqual(b.integrate(0,1)[2], 1.0/6)
        self.assertAlmostEqual(b.integrate(0,2)[0], 2.0/6)
        self.assertAlmostEqual(b.integrate(0,2)[1], 5.0/6)
        self.assertAlmostEqual(b.integrate(0,2)[2], 5.0/6)
Exemplo n.º 53
0
    def test_matches(self):
        b1 = BSplineBasis(3, [0,0,0,1,2,3,4,4,4])
        b2 = BSplineBasis(3, [1,1,1,2,3,4,5,5,5])
        b3 = BSplineBasis(4, [1,1,1,2,3,4,5,5,5])
        b4 = BSplineBasis(4, [2,2,2,4,6,8,10,10,10])
        b5 = BSplineBasis(3, [-1,0,0,1,2,3,4,4,5], periodic=0)
        b6 = BSplineBasis(3, [-1,0,0,1,2,3,4,4,5])
        b7 = BSplineBasis(3, [0,0,0,2,3,3,3])
        b8 = BSplineBasis(3, [5,5,5,7,11,11,11])

        self.assertEqual(b1.matches(b2), True)
        self.assertEqual(b1.matches(b2, reverse=True), True)
        self.assertEqual(b2.matches(b1), True)
        self.assertEqual(b1.matches(b3), False)
        self.assertEqual(b2.matches(b3), False)
        self.assertEqual(b1.matches(b4), False)
        self.assertEqual(b4.matches(b4), True)
        self.assertEqual(b5.matches(b6), False)
        self.assertEqual(b7.matches(b8, reverse=True), True)
        self.assertEqual(b8.matches(b7, reverse=True), True)