Module sverchok.utils.curve.splines

Expand source code
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE

import numpy as np

from sverchok.utils.geom import LinearSpline, CubicSpline
from sverchok.utils.curve.core import SvCurve
from sverchok.utils.curve.primitives import SvLine
from sverchok.utils.curve.bezier import SvBezierCurve, SvCubicBezierCurve
from sverchok.utils.curve import knotvector as sv_knotvector
from sverchok.utils.curve.nurbs import SvNurbsCurve
from sverchok.utils.curve.algorithms import concatenate_curves, reparametrize_curve
from sverchok.utils.curve.nurbs_algorithms import concatenate_nurbs_curves

class SvSplineCurve(SvCurve):
    __description__ = "Spline"

    def __init__(self, spline):
        self.spline = spline
        self.u_bounds = (0.0, 1.0)

    @classmethod
    def from_points(cls, points, metric=None, is_cyclic=False):
        if points is None or len(points) < 2:
            raise Exception("At least two points are required")
        if len(points) < 3:
            return SvLine.from_two_points(points[0], points[1])
        spline = CubicSpline(points, metric=metric, is_cyclic=is_cyclic)
        return SvSplineCurve(spline)

    def evaluate(self, t):
        v = self.spline.eval_at_point(t)
        return np.array(v)

    def evaluate_array(self, ts):
        vs = self.spline.eval(ts)
        return np.array(vs)

    def tangent(self, t, tangent_delta=None):
        h = self.get_tangent_delta(tangent_delta)
        vs = self.spline.tangent(np.array([t]), h=h)
        return vs[0]

    def tangent_array(self, ts, tangent_delta=None):
        h = self.get_tangent_delta(tangent_delta)
        return self.spline.tangent(ts, h=h)

    def get_u_bounds(self):
        return self.u_bounds

    def get_degree(self):
        return self.spline.get_degree()

    def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
        control_points = self.spline.get_control_points()
        degree = self.spline.get_degree()
        n_points = degree + 1
        knotvector = sv_knotvector.generate(degree, n_points)
        t_segments = self.spline.get_t_segments()
        segments = [SvNurbsCurve.build(implementation,
                        degree, knotvector, points) for points in control_points]
        segments = [reparametrize_curve(segment, t_min, t_max) for segment, (t_min, t_max) in zip(segments, t_segments)]
#         pairs = [f"#{i}: {t_min}-{t_max}: {segment.evaluate(t_min)} -- {segment.evaluate(t_max)}" for i, (segment, (t_min, t_max)) in enumerate(zip(segments, t_segments))]
#         pairs = ", ".join(pairs)
#         print(f"S: {pairs}")
        return concatenate_nurbs_curves(segments)

    def to_bezier_segments(self):
        control_points = self.spline.get_control_points()
        is_cubic = isinstance(self.spline, CubicSpline)
        curve_constructor = lambda cs: SvCubicBezierCurve(*cs) if is_cubic else SvBezierCurve
        segments = [curve_constructor(points) for points in control_points]
        return segments

    def concatenate(self, curve2, tolerance=1e-6, remove_knots=False):
        curve2 = SvNurbsCurve.to_nurbs(curve2)
        if curve2 is None:
            raise UnsupportedCurveTypeException("second curve is not NURBS")
        else:
            return self.to_nurbs().concatenate(curve2, tolerance=tolerance, remove_knots=remove_knots)

    def make_revolution_surface(self, point, direction, v_min, v_max, global_origin):
        return self.to_nurbs().make_revolution_surface(point, direction, v_min, v_max, global_origin)

    def extrude_along_vector(self, vector):
        return self.to_nurbs().extrude_along_vector(vector)

    def make_ruled_surface(self, curve2, vmin, vmax):
        return self.to_nurbs().make_ruled_surface(curve2, vmin, vmax)

    def extrude_to_point(self, point):
        return self.to_nurbs().extrude_to_point(point)
    
    def lerp_to(self, curve2, coefficient):
        return self.to_nurbs().lerp_to(curve2, coefficient)

    def split_at(self, t):
        return self.to_nurbs().split_at(t)

    def cut_segment(self, new_t_min, new_t_max, rescale=False):
        return self.to_nurbs().cut_segment(new_t_min, new_t_max, rescale=rescale)

    def is_polyline(self):
        return self.spline.get_degree() == 1

    def get_polyline_vertices(self):
        if self.spline.get_degree() == 1:
            return self.spline.pts
        else:
            raise Exception("Curve is not a polyline")

Classes

class SvSplineCurve (spline)
Expand source code
class SvSplineCurve(SvCurve):
    __description__ = "Spline"

    def __init__(self, spline):
        self.spline = spline
        self.u_bounds = (0.0, 1.0)

    @classmethod
    def from_points(cls, points, metric=None, is_cyclic=False):
        if points is None or len(points) < 2:
            raise Exception("At least two points are required")
        if len(points) < 3:
            return SvLine.from_two_points(points[0], points[1])
        spline = CubicSpline(points, metric=metric, is_cyclic=is_cyclic)
        return SvSplineCurve(spline)

    def evaluate(self, t):
        v = self.spline.eval_at_point(t)
        return np.array(v)

    def evaluate_array(self, ts):
        vs = self.spline.eval(ts)
        return np.array(vs)

    def tangent(self, t, tangent_delta=None):
        h = self.get_tangent_delta(tangent_delta)
        vs = self.spline.tangent(np.array([t]), h=h)
        return vs[0]

    def tangent_array(self, ts, tangent_delta=None):
        h = self.get_tangent_delta(tangent_delta)
        return self.spline.tangent(ts, h=h)

    def get_u_bounds(self):
        return self.u_bounds

    def get_degree(self):
        return self.spline.get_degree()

    def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
        control_points = self.spline.get_control_points()
        degree = self.spline.get_degree()
        n_points = degree + 1
        knotvector = sv_knotvector.generate(degree, n_points)
        t_segments = self.spline.get_t_segments()
        segments = [SvNurbsCurve.build(implementation,
                        degree, knotvector, points) for points in control_points]
        segments = [reparametrize_curve(segment, t_min, t_max) for segment, (t_min, t_max) in zip(segments, t_segments)]
#         pairs = [f"#{i}: {t_min}-{t_max}: {segment.evaluate(t_min)} -- {segment.evaluate(t_max)}" for i, (segment, (t_min, t_max)) in enumerate(zip(segments, t_segments))]
#         pairs = ", ".join(pairs)
#         print(f"S: {pairs}")
        return concatenate_nurbs_curves(segments)

    def to_bezier_segments(self):
        control_points = self.spline.get_control_points()
        is_cubic = isinstance(self.spline, CubicSpline)
        curve_constructor = lambda cs: SvCubicBezierCurve(*cs) if is_cubic else SvBezierCurve
        segments = [curve_constructor(points) for points in control_points]
        return segments

    def concatenate(self, curve2, tolerance=1e-6, remove_knots=False):
        curve2 = SvNurbsCurve.to_nurbs(curve2)
        if curve2 is None:
            raise UnsupportedCurveTypeException("second curve is not NURBS")
        else:
            return self.to_nurbs().concatenate(curve2, tolerance=tolerance, remove_knots=remove_knots)

    def make_revolution_surface(self, point, direction, v_min, v_max, global_origin):
        return self.to_nurbs().make_revolution_surface(point, direction, v_min, v_max, global_origin)

    def extrude_along_vector(self, vector):
        return self.to_nurbs().extrude_along_vector(vector)

    def make_ruled_surface(self, curve2, vmin, vmax):
        return self.to_nurbs().make_ruled_surface(curve2, vmin, vmax)

    def extrude_to_point(self, point):
        return self.to_nurbs().extrude_to_point(point)
    
    def lerp_to(self, curve2, coefficient):
        return self.to_nurbs().lerp_to(curve2, coefficient)

    def split_at(self, t):
        return self.to_nurbs().split_at(t)

    def cut_segment(self, new_t_min, new_t_max, rescale=False):
        return self.to_nurbs().cut_segment(new_t_min, new_t_max, rescale=rescale)

    def is_polyline(self):
        return self.spline.get_degree() == 1

    def get_polyline_vertices(self):
        if self.spline.get_degree() == 1:
            return self.spline.pts
        else:
            raise Exception("Curve is not a polyline")

Ancestors

Static methods

def from_points(points, metric=None, is_cyclic=False)
Expand source code
@classmethod
def from_points(cls, points, metric=None, is_cyclic=False):
    if points is None or len(points) < 2:
        raise Exception("At least two points are required")
    if len(points) < 3:
        return SvLine.from_two_points(points[0], points[1])
    spline = CubicSpline(points, metric=metric, is_cyclic=is_cyclic)
    return SvSplineCurve(spline)

Methods

def concatenate(self, curve2, tolerance=1e-06, remove_knots=False)
Expand source code
def concatenate(self, curve2, tolerance=1e-6, remove_knots=False):
    curve2 = SvNurbsCurve.to_nurbs(curve2)
    if curve2 is None:
        raise UnsupportedCurveTypeException("second curve is not NURBS")
    else:
        return self.to_nurbs().concatenate(curve2, tolerance=tolerance, remove_knots=remove_knots)
def cut_segment(self, new_t_min, new_t_max, rescale=False)
Expand source code
def cut_segment(self, new_t_min, new_t_max, rescale=False):
    return self.to_nurbs().cut_segment(new_t_min, new_t_max, rescale=rescale)
def extrude_along_vector(self, vector)
Expand source code
def extrude_along_vector(self, vector):
    return self.to_nurbs().extrude_along_vector(vector)
def extrude_to_point(self, point)
Expand source code
def extrude_to_point(self, point):
    return self.to_nurbs().extrude_to_point(point)
def get_polyline_vertices(self)
Expand source code
def get_polyline_vertices(self):
    if self.spline.get_degree() == 1:
        return self.spline.pts
    else:
        raise Exception("Curve is not a polyline")
def is_polyline(self)
Expand source code
def is_polyline(self):
    return self.spline.get_degree() == 1
def lerp_to(self, curve2, coefficient)
Expand source code
def lerp_to(self, curve2, coefficient):
    return self.to_nurbs().lerp_to(curve2, coefficient)
def make_revolution_surface(self, point, direction, v_min, v_max, global_origin)
Expand source code
def make_revolution_surface(self, point, direction, v_min, v_max, global_origin):
    return self.to_nurbs().make_revolution_surface(point, direction, v_min, v_max, global_origin)
def make_ruled_surface(self, curve2, vmin, vmax)
Expand source code
def make_ruled_surface(self, curve2, vmin, vmax):
    return self.to_nurbs().make_ruled_surface(curve2, vmin, vmax)
def split_at(self, t)
Expand source code
def split_at(self, t):
    return self.to_nurbs().split_at(t)
def to_bezier_segments(self)
Expand source code
def to_bezier_segments(self):
    control_points = self.spline.get_control_points()
    is_cubic = isinstance(self.spline, CubicSpline)
    curve_constructor = lambda cs: SvCubicBezierCurve(*cs) if is_cubic else SvBezierCurve
    segments = [curve_constructor(points) for points in control_points]
    return segments
def to_nurbs(self, implementation='NATIVE')
Expand source code
    def to_nurbs(self, implementation=SvNurbsCurve.NATIVE):
        control_points = self.spline.get_control_points()
        degree = self.spline.get_degree()
        n_points = degree + 1
        knotvector = sv_knotvector.generate(degree, n_points)
        t_segments = self.spline.get_t_segments()
        segments = [SvNurbsCurve.build(implementation,
                        degree, knotvector, points) for points in control_points]
        segments = [reparametrize_curve(segment, t_min, t_max) for segment, (t_min, t_max) in zip(segments, t_segments)]
#         pairs = [f"#{i}: {t_min}-{t_max}: {segment.evaluate(t_min)} -- {segment.evaluate(t_max)}" for i, (segment, (t_min, t_max)) in enumerate(zip(segments, t_segments))]
#         pairs = ", ".join(pairs)
#         print(f"S: {pairs}")
        return concatenate_nurbs_curves(segments)

Inherited members