Esempio n. 1
0
def random_point_comparision_to_nurbs_python(spline: BSpline, count: int = 10):
    curve = spline.to_nurbs_python_curve()
    for _ in range(count):
        t = random.random()
        p1 = spline.point(t)
        p2 = curve.evaluate_single(t)
        assert p1.isclose(p2)
Esempio n. 2
0
def test_bspline_insert_knot():
    bspline = BSpline([(0, 0), (10, 20), (30, 10), (40, 10), (50, 0), (60, 20),
                       (70, 50), (80, 70)])
    t = bspline.max_t / 2
    assert len(bspline.control_points) == 8
    bspline.insert_knot(t)
    assert len(bspline.control_points) == 9
Esempio n. 3
0
def test_normalize_knots_if_needed():
    s = BSpline(
        control_points=DEFPOINTS,
        knots=[2, 2, 2, 2, 3, 6, 6, 6, 6],
        order=4,
    )
    k = s.knots()
    assert k[0] == 0.0
Esempio n. 4
0
 def __init__(self, spline):
     control_points = [Vector(point) for point in spline.control_points]
     knots = [knot for knot in spline.knots]
     weights = [weight for weight in spline.weights] if spline.weights else None
     order = spline.dxf.degree + 1
     BSpline.__init__(self, control_points, order, knots, weights)
     points = [point for point in self.approximate()]
     Element.__init__(self, spline, points)
Esempio n. 5
0
def test_bspine_points():
    curve = BSpline(DEFPOINTS, order=3)
    points = list(curve.approximate(40))

    for rpoint, epoint in zip(points, iter_points(DBSPLINE, 0)):
        epx, epy, epz = epoint
        rpx, rpy, rpz = rpoint
        assert isclose(epx, rpx)
        assert isclose(epy, rpy)
        assert isclose(epz, rpz)
Esempio n. 6
0
def random_derivatives_comparision_to_nurbs_python(spline: BSpline,
                                                   count: int = 10):
    curve = spline.to_nurbs_python_curve()
    for _ in range(count):
        t = random.random()
        p1, d1_1, d2_1 = spline.derivative(t, n=2)
        p2, d1_2, d2_2 = curve.derivatives(t, order=2)
        assert p1.isclose(p2)
        assert d1_1.isclose(d1_2)
        assert d2_1.isclose(d2_2)
Esempio n. 7
0
def test_rbspline():
    curve = BSpline(DEFPOINTS, order=3, weights=DEFWEIGHTS)
    expected = RBSPLINE
    points = list(curve.approximate(40))

    for rpoint, epoint in zip(points, expected):
        epx, epy, epz = epoint
        rpx, rpy, rpz = rpoint
        assert isclose(epx, rpx)
        assert isclose(epy, rpy)
        assert isclose(epz, rpz)
Esempio n. 8
0
    def render_open_bspline(self, layout: 'BaseLayout', degree: int = 3, dxfattribs: dict = None) -> None:
        """
        Render an open uniform BSpline as 3D :class:`~ezdxf.entities.Polyline`. Definition points are control points.

        Args:
            layout: :class:`~ezdxf.layouts.BaseLayout` object
            degree: degree of B-spline (order = `degree` + 1)
            dxfattribs: DXF attributes for :class:`~ezdxf.entities.Polyline`

        """
        spline = BSpline(self.points, order=degree + 1)
        layout.add_polyline3d(list(spline.approximate(self.segments)), dxfattribs=dxfattribs)
Esempio n. 9
0
    def render_open_bspline(self, layout: 'GenericLayoutType', degree: int = 3, dxfattribs: dict = None) -> None:
        """
        Render an open uniform BSpline as 3d polyline. Definition points are control points.

        Args:
            layout: ezdxf layout
            degree: B-spline degree (order = degree + 1)
            dxfattribs: DXF attributes for POLYLINE

        """
        spline = BSpline(self.points, order=degree + 1)
        layout.add_polyline3d(list(spline.approximate(self.segments)), dxfattribs=dxfattribs)
Esempio n. 10
0
def test_if_nurbs_python_is_reliable():
    # Testing for some known values, just for the case
    # that NURBS-Python is incorrect.
    expected = [(0.0, 0.0, 0.0),
                (11.840000000000003, 13.760000000000002, 16.64),
                (22.72, 14.079999999999998, 22.719999999999995),
                (31.759999999999994, 11.2, 24.399999999999995),
                (39.92, 7.999999999999999, 26.0), (50.0, 0.0, 30.0)]
    params = [0, .2, .4, .6, .8, 1.0]
    curve = BSpline(DEFPOINTS).to_nurbs_python_curve()
    points = curve.evaluate_list(params)
    for expect, point in zip(expected, points):
        assert Vector(expect).isclose(point)
Esempio n. 11
0
    def apply_construction_tool(self, s: BSpline) -> None:
        """
        Set SPLINE data from construction tool :class:`ezdxf.math.BSpline`.

        .. versionadded:: 0.13

        """
        self.dxf.degree = s.degree
        self.control_points = s.control_points
        self.fit_points = []  # remove fit points
        self.knots = s.knots()
        self.weights = s.weights()
        self.set_flag_state(Spline.RATIONAL, state=bool(len(self.weights)))
Esempio n. 12
0
    def render_open_rbspline(self, layout: 'GenericLayoutType', weights: Iterable[float], degree: int = 3,
                             dxfattribs: dict = None) -> None:
        """
        Render a rational open uniform BSpline as 3d polyline.

        Args:
            layout: ezdxf layout
            weights: list of weights, requires a weight value for each defpoint.
            degree: B-spline degree (order = degree + 1)
            dxfattribs: DXF attributes for POLYLINE

        """
        spline = BSpline(self.points, order=degree + 1, weights=weights)
        layout.add_polyline3d(list(spline.approximate(self.segments)), dxfattribs=dxfattribs)
Esempio n. 13
0
    def render_open_rbspline(self, layout: 'BaseLayout', weights: Iterable[float], degree: int = 3,
                             dxfattribs: dict = None) -> None:
        """
        Render a rational open uniform BSpline as 3D :class:`~ezdxf.entities.Polyline`. Definition points are control
        points.

        Args:
            layout: :class:`~ezdxf.layouts.BaseLayout` object
            weights: list of weights, requires a weight value (float) for each definition point.
            degree: degree of B-spline (order = `degree` + 1)
            dxfattribs: DXF attributes for :class:`~ezdxf.entities.Polyline`

        """
        spline = BSpline(self.points, order=degree + 1, weights=weights)
        layout.add_polyline3d(list(spline.approximate(self.segments)), dxfattribs=dxfattribs)
Esempio n. 14
0
def test_cubic_bezier_approximation():
    bspline = BSpline.from_fit_points([(0, 0), (10, 20), (30, 10), (40, 10),
                                       (50, 0), (60, 20), (70, 50), (80, 70)])
    bezier_segments = list(bspline.cubic_bezier_approximation(level=3))
    assert len(bezier_segments) == 28
    bezier_segments = list(bspline.cubic_bezier_approximation(segments=40))
    assert len(bezier_segments) == 40
Esempio n. 15
0
    def bspline(self,
                length: float,
                segments: int = 10,
                degree: int = 3,
                method: str = 'uniform') -> BSpline:
        """
        Approximate euler spiral as B-spline.

        Args:
            length: length of euler spiral
            segments: count of fit points for B-spline calculation
            degree: degree of BSpline
            method: calculation method for parameter vector t

        Returns:
            :class:`BSpline`

        """
        fit_points = list(self.approximate(length, segments=segments))
        spline = global_bspline_interpolation(fit_points,
                                              degree,
                                              method=method)
        return BSpline(
            spline.control_points,
            spline.order,
            # Scale knot values to length:
            [v * length for v in spline.knots()],
        )
Esempio n. 16
0
    def approximate(self,
                    segments: int = 40,
                    ucs: 'UCS' = None) -> List['Vertex']:
        """
        Approximate B-spline by a polyline with `segments` line segments. If `ucs` is not ``None``, ucs defines an
        :class:`~ezdxf.math.UCS`, to transformed the curve into :ref:`OCS`. The control points are placed xy-plane of
        the UCS, don't use z-axis coordinates, if so make sure all control points are in a plane parallel to the OCS
        base plane (UCS xy-plane), else the result is unpredictable and depends on the CAD application used to open the
        DXF file, it maybe crash.

        Args:
            segments: count of line segments for approximation, vertex count is `segments` + 1
            ucs: :class:`~ezdxf.math.UCS` definition, control points in ucs coordinates.

        Returns:
            list of vertices in :class:`~ezdxf.math.OCS` as :class:`~ezdxf.math.Vec3` objects

        """
        if self.closed:
            spline = BSplineClosed(self.control_points, order=self.degree + 1)
        else:
            spline = BSpline(self.control_points, order=self.degree + 1)
        vertices = spline.approximate(segments)
        if ucs is not None:
            vertices = (ucs.to_ocs(vertex) for vertex in vertices)
        return list(vertices)
Esempio n. 17
0
    def construction_tool(self) -> BSpline:
        """ Returns construction tool :class:`ezdxf.math.BSpline`.

        .. versionadded:: 0.13

        """
        if self.control_point_count():
            weights = self.weights if len(self.weights) else None
            knots = self.knots if len(self.knots) else None
            return BSpline(control_points=self.control_points,
                           order=self.dxf.degree + 1, knots=knots,
                           weights=weights)
        elif self.fit_point_count():
            return BSpline.from_fit_points(self.fit_points,
                                           degree=self.dxf.degree)
        else:
            raise ValueError(
                'Construction tool requires control- or fit points.')
Esempio n. 18
0
 def approximate(self,
                 segments: int = 40,
                 ucs: 'UCS' = None) -> List['Vertex']:
     if self.closed:
         spline = BSplineClosed(self.control_points, order=self.degree + 1)
     else:
         spline = BSpline(self.control_points, order=self.degree + 1)
     vertices = spline.approximate(segments)
     if ucs is not None:
         vertices = (ucs.to_ocs(vertex) for vertex in vertices)
     return list(vertices)
Esempio n. 19
0
def test_bezier_decomposition():
    bspline = BSpline.from_fit_points([(0, 0), (10, 20), (30, 10), (40, 10),
                                       (50, 0), (60, 20), (70, 50), (80, 70)])
    bezier_segments = list(bspline.bezier_decomposition())
    assert len(bezier_segments) == 5
    # results visually checked to be correct
    assert bezier_segments[0] == [(0.0, 0.0, 0.0),
                                  (2.02070813064438, 39.58989657555839, 0.0),
                                  (14.645958536022286, 10.410103424441612,
                                   0.0), (30.0, 10.0, 0.0)]
    assert bezier_segments[-1] == [(60.0, 20.0, 0.0),
                                   (66.33216513897267, 43.20202388489432, 0.0),
                                   (69.54617236126121, 50.37880459351478, 0.0),
                                   (80.0, 70.0, 0.0)]
Esempio n. 20
0
    def apply_construction_tool(self, s) -> 'Spline':
        """ Set SPLINE data from construction tool :class:`ezdxf.math.BSpline`
        or from a :class:`geomdl.BSpline.Curve` object.

        .. versionadded:: 0.13

        """
        try:
            self.control_points = s.control_points
        except AttributeError:  # maybe a geomdl.BSpline.Curve class
            s = BSpline.from_nurbs_python_curve(s)
            self.control_points = s.control_points

        self.dxf.degree = s.degree
        self.fit_points = []  # remove fit points
        self.knots = s.knots()
        self.weights = s.weights()
        self.set_flag_state(Spline.RATIONAL, state=bool(len(self.weights)))
        return self  # floating interface
Esempio n. 21
0
    def from_arc(cls, entity: 'DXFGraphic') -> 'Spline':
        """ Create a new SPLINE entity from CIRCLE, ARC or ELLIPSE entity.

        The new SPLINE entity has no owner, no handle, is not stored in
        the entity database nor assigned to any layout!

        .. versionadded:: 0.13

        """
        dxftype = entity.dxftype()
        if dxftype == 'ELLIPSE':
            ellipse = cast('Ellipse', entity).construction_tool()
        elif dxftype == 'CIRCLE':
            ellipse = ConstructionEllipse.from_arc(
                center=entity.dxf.get('center', NULLVEC),
                radius=abs(entity.dxf.get('radius', 1.0)),
                extrusion=entity.dxf.get('extrusion', Z_AXIS),
            )
        elif dxftype == 'ARC':
            ellipse = ConstructionEllipse.from_arc(
                center=entity.dxf.get('center', NULLVEC),
                radius=abs(entity.dxf.get('radius', 1.0)),
                extrusion=entity.dxf.get('extrusion', Z_AXIS),
                start_angle=entity.dxf.get('start_angle', 0),
                end_angle=entity.dxf.get('end_angle', 360)
            )
        else:
            raise TypeError('CIRCLE, ARC or ELLIPSE entity required.')

        spline = Spline.new(dxfattribs=entity.graphic_properties(),
                            doc=entity.doc)
        s = BSpline.from_ellipse(ellipse)
        spline.dxf.degree = s.degree
        spline.dxf.flags = Spline.RATIONAL
        spline.control_points = s.control_points
        spline.knots = s.knots()
        spline.weights = s.weights()
        return spline
Esempio n. 22
0
    def bspline(
        self,
        length: float,
        segments: int = 10,
        degree: int = 3,
        method: str = "uniform",
    ) -> BSpline:
        """Approximate euler spiral as B-spline.

        Args:
            length: length of euler spiral
            segments: count of fit points for B-spline calculation
            degree: degree of BSpline
            method: calculation method for parameter vector t

        Returns:
            :class:`BSpline`

        """
        length = float(length)
        fit_points = list(self.approximate(length, segments=segments))
        derivatives = [
            # Scaling derivatives by chord length (< real length) is suggested
            # by Piegl & Tiller.
            self.tangent(t).normalize(length)
            for t in _params(length, segments)
        ]
        spline = global_bspline_interpolation(
            fit_points, degree, method=method, tangents=derivatives
        )
        return BSpline(
            spline.control_points,
            spline.order,
            # Scale knot values to length:
            [v * length for v in spline.knots()],
        )
Esempio n. 23
0
def test_flattening():
    fitpoints = [(0, 0), (1, 3), (2, 0), (3, 3)]
    bspline = BSpline.from_fit_points(fitpoints)
    assert list(bspline.flattening(0.01, segments=4)) == EXPECTED_FLATTENING
Esempio n. 24
0
def test_transform_interface():
    from ezdxf.math import Matrix44
    spline = BSpline(control_points=[(1, 0, 0), (3, 3, 0), (6, 0, 1)], order=3)
    spline.transform(Matrix44.translate(1, 2, 3))
    assert spline.control_points[0] == (2, 2, 3)
Esempio n. 25
0
def test_bspine_derivatives_random():
    spline = BSpline(DEFPOINTS, order=3)
    random_derivatives_comparision_to_nurbs_python(spline)
Esempio n. 26
0
def test_is_clamped(weired_spline1):
    spline = BSpline(DEFPOINTS, order=3)
    assert spline.is_clamped is True
    assert weired_spline1.is_clamped is False
Esempio n. 27
0
def test_bspine_points_random():
    spline = BSpline(DEFPOINTS, order=3)
    random_point_comparision_to_nurbs_python(spline)
Esempio n. 28
0
def weired_spline1():
    # test spline from: 'CADKitSamples\Tamiya TT-01.dxf'
    control_points = [
        (-52.08772752271847, 158.6939842216689, 0.0),
        (-52.08681215879965, 158.5299954819766, 0.0),
        (-52.10118023714384, 158.453369560292, 0.0),
        (-52.15481567142786, 158.3191250853181, 0.0),
        (-52.19398877522381, 158.2621809388646, 0.0),
        (-52.28596439525645, 158.1780834350967, 0.0),
        (-52.33953844794299, 158.1503467960972, 0.0),
        (-52.44810872122953, 158.1300340044323, 0.0),
        (-52.50421992306838, 158.1373171840982, 0.0),
        (-52.6075289246734, 158.1865954546344, 0.0),
        (-52.65514787710273, 158.2285032895921, 0.0),
        (-52.73668761545541, 158.3403743627349, 0.0),
        (-52.77007322118961, 158.4091709021843, 0.0),
        (-52.82282063670695, 158.5633574927312, 0.0),
        (-52.84192253131899, 158.6479284406054, 0.0),
        (-52.86740213628708, 158.8193660227095, 0.0),
        (-52.87386770841857, 158.9069288997418, 0.0),
        (-52.87483030423064, 159.0684635170357, 0.0),
        (-52.86932199691667, 159.1438624785262, 0.0),
        (-52.84560704446005, 159.2697570380293, 0.0),
        (-52.82725914916205, 159.3212520891559, 0.0),
        (-52.75022655463125, 159.4318434990425, 0.0),
        (-52.6670694478151, 159.4452110783386, 0.0),
        (-52.51141458339235, 159.3709884860868, 0.0),
        (-52.45531159130934, 159.3310594465107, 0.0),
        (-52.34571913237574, 159.2278392570542, 0.0),
        (-52.29163139562603, 159.1638425241462, 0.0),
        (-52.19834244727945, 159.0217561474263, 0.0),
        (-52.15835994602539, 158.9423430023927, 0.0),
        (-52.10315233959036, 158.778742732499, 0.0),
        (-52.08772752271847, 158.6939842216689, 0.0),
        (-52.08681215879965, 158.5299954819766, 0.0),
    ]
    knots = [
        -0.0624999999999976,
        -0.0624999999999976,
        0.0,
        0.0,
        0.0624999999999998,
        0.0624999999999998,
        0.1249999999999997,
        0.1249999999999997,
        0.1874999999999996,
        0.1874999999999996,
        0.2499999999999994,
        0.2499999999999994,
        0.3124999999999992,
        0.3124999999999992,
        0.3749999999999991,
        0.3749999999999991,
        0.4374999999999989,
        0.4374999999999989,
        0.4999999999999988,
        0.4999999999999988,
        0.5624999999999987,
        0.5624999999999987,
        0.6249999999999984,
        0.6249999999999984,
        0.7500000000000099,
        0.7500000000000099,
        0.8125000000000074,
        0.8125000000000074,
        0.875000000000005,
        0.875000000000005,
        0.9375000000000024,
        0.9375000000000024,
        1.0,
        1.0,
        1.0625,
        1.0625,
    ]
    return BSpline(control_points, order=4, knots=knots)