Beispiel #1
0
def bilinear_surface(vtxs, overhang=0.0):
    """
    Returns B-spline surface of a bilinear surface given by 4 corner points:
    uv coords:
    We retun also list of UV coordinates of the given points.
    :param vtxs: List of tuples (X,Y,Z)
    :return: ( Surface, vtxs_uv )
    """
    assert len(vtxs) == 4, "n vtx: {}".format(len(vtxs))
    vtxs = np.array(vtxs)
    if overhang > 0.0:
        dv = np.roll(vtxs, -1, axis=0) - vtxs
        dv *= overhang
        vtxs += np.roll(dv, 1, axis=0) - dv

    def mid(*idx):
        return np.mean(vtxs[list(idx)], axis=0)

    # v - direction v0 -> v2
    # u - direction v0 -> v1
    poles = [[vtxs[0], mid(0, 3), vtxs[3]],
             [mid(0, 1), mid(0, 1, 2, 3),
              mid(2, 3)], [vtxs[1], mid(1, 2), vtxs[2]]]
    knots = 3 * [0.0 - overhang] + 3 * [1.0 + overhang]
    basis = bs.SplineBasis(2, knots)
    surface = bs.Surface((basis, basis), poles)
    #vtxs_uv = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
    return surface
Beispiel #2
0
    def test_eval(self):
        #self.plot_basis(bs.SplineBasis.make_equidistant(0, 4))

        knots = np.array([
            0, 0, 0, 0.1880192, 0.24545785, 0.51219762, 0.82239001, 1., 1., 1.
        ])
        basis = bs.SplineBasis(2, knots)
        #self.plot_basis(basis)

        eq_basis = bs.SplineBasis.make_equidistant(0, 2)
        assert eq_basis.eval(0, 0.0) == 1.0
        assert eq_basis.eval(1, 0.0) == 0.0
        assert eq_basis.eval(0, 0.5) == 0.0
        assert eq_basis.eval(1, 0.5) == 1.0
        assert eq_basis.eval(1, 1.0) == 1.0

        eq_basis = bs.SplineBasis.make_equidistant(1, 4)
        assert eq_basis.eval(0, 0.0) == 1.0
        assert eq_basis.eval(1, 0.0) == 0.0
        assert eq_basis.eval(2, 0.0) == 0.0
        assert eq_basis.eval(3, 0.0) == 0.0
        assert eq_basis.eval(4, 0.0) == 0.0

        assert eq_basis.eval(0, 0.125) == 0.5
        assert eq_basis.eval(1, 0.125) == 0.5
        assert eq_basis.eval(2, 1.0) == 0.0

        # check summation to one:
        for deg in range(0, 10):
            basis = bs.SplineBasis.make_equidistant(deg, 2)
            for x in np.linspace(basis.domain[0], basis.domain[1], 10):
                s = sum([basis.eval(i, x) for i in range(basis.size)])
                assert np.isclose(s, 1.0)
Beispiel #3
0
def curve_from_grid(points, **kwargs):
    """
    Make a Curve (of degree 3) as an approximation of a sequence of points.
    :param points - N x D array, D is dimension
    :param nt Prescribed number of poles of the resulting spline.
    :return: Curve object.

    TODO:
    - Measure efficiency. Estimate how good we can be. Do it our self if we can do at leas 10 times better.
    - Find out which method is used. Hoschek (4.4.1) refers to several methods how to determine parametrization of
    the curve, i.e. Find parameters t_i to the given approximation points P_i.
    - Further on it is not clear what is the mening of the 's' parameter and how one cna influence tolerance and smoothness.
    - Some sort of adaptivity is used.


    """
    deg = kwargs.get('degree', 3)
    tol = kwargs.get('tol', 0.01)
    weights = np.ones(points.shape[0])
    weights[0] = weights[-1] = 1000.0
    tck = scipy.interpolate.splprep(points.T, k=deg, s=tol, w=weights)[0]
    knots, poles, degree = tck
    curve_poles = np.array(poles).T
    curve_poles[0] = points[0]
    curve_poles[-1] = points[-1]
    basis = bs.SplineBasis(degree, knots)
    curve = bs.Curve(basis, curve_poles)
    return curve
Beispiel #4
0
    def test_find_knot_interval(self):
        """
        test methods:
        - make_equidistant
        - find_knot_interval
        """
        eq_basis = bs.SplineBasis.make_equidistant(2, 100)
        assert eq_basis.find_knot_interval(0.0) == 0
        assert eq_basis.find_knot_interval(0.001) == 0
        assert eq_basis.find_knot_interval(0.01) == 1
        assert eq_basis.find_knot_interval(0.011) == 1
        assert eq_basis.find_knot_interval(0.5001) == 50
        assert eq_basis.find_knot_interval(1.0 - 0.011) == 98
        assert eq_basis.find_knot_interval(1.0 - 0.01) == 99
        assert eq_basis.find_knot_interval(1.0 - 0.001) == 99
        assert eq_basis.find_knot_interval(1.0) == 99

        knots = np.array([
            0, 0, 0, 0.1880192, 0.24545785, 0.51219762, 0.82239001, 1., 1., 1.
        ])
        basis = bs.SplineBasis(2, knots)
        for interval in range(2, 7):
            xx = np.linspace(knots[interval], knots[interval + 1], 10)
            for j, x in enumerate(xx[:-1]):
                i_found = basis.find_knot_interval(x)
                assert i_found == interval - 2, "i_found: {} i: {} j: {} x: {} ".format(
                    i_found, interval - 2, j, x)
Beispiel #5
0
def line(vtxs, overhang=0.0):
    '''
    Return B-spline approximation of a line from two points
    :param vtxs: [ X0, X1 ], Xn are point coordinates in arbitrary dimension D
    :return: Curve2D
    '''
    assert len(vtxs) == 2
    vtxs = np.array(vtxs)
    if overhang > 0.0:
        dv = overhang * (vtxs[1] - vtxs[0])
        vtxs[0] -= dv
        vtxs[1] += dv
    mid = np.mean(vtxs, axis=0)
    poles = [vtxs[0], mid, vtxs[1]]
    knots = 3 * [0.0 - overhang] + 3 * [1.0 + overhang]
    basis = bs.SplineBasis(2, knots)
    return bs.Curve(basis, poles)