Skip to content

Instantly share code, notes, and snippets.

@portnov
Created October 19, 2025 15:59
Show Gist options
  • Select an option

  • Save portnov/63284532fe0d7e8d22344781a987c897 to your computer and use it in GitHub Desktop.

Select an option

Save portnov/63284532fe0d7e8d22344781a987c897 to your computer and use it in GitHub Desktop.
"""
in curve_in C
out curve_out C
"""
from math import sqrt, exp
import numpy as np
from sverchok.data_structure import zip_long_repeat, ensure_nesting_level, repeat_last_for_length
from sverchok.utils.curve.core import SvCurve, UnsupportedCurveTypeException
from sverchok.utils.curve.nurbs import SvNurbsCurve
from sverchok.utils.curve.bezier import SvCubicBezierCurve
from sverchok.utils.curve.nurbs_algorithms import concatenate_nurbs_curves
from sverchok.dependencies import scipy
from scipy.optimize import fsolve
def process_segment(segment, c1, c2):
#print(f"Fit to {c1}, {c2}")
A, B, C, D = segment.get_control_points()
v1 = B - A
v13 = np.linalg.norm(v1)**3
v2 = D - C
v23 = np.linalg.norm(v2)**3
def equations(p):
X, Y = p
x, y = exp(X), exp(Y)
#x, y = p
C_star = D - y*v2
B_star = A + x*v1
eq1 = 2 * np.linalg.norm(np.cross(v1, C_star - A)) / (x*x * v13) - 3*c1
eq2 = 2 * np.linalg.norm(np.cross(v2, B_star - D)) / (y*y * v23) - 3*c2
return (eq1, eq2)
initial_guess = [0, 0]
ps = fsolve(equations, initial_guess)
#print(solution)
#ps, info, ier, mesg = solution
X, Y = ps
x, y = exp(X), exp(Y)
#x,y = ps
#print(f"Sol: {x}, {y}")
B_star = A + x*v1
C_star = D - y*v2
result = SvCubicBezierCurve(A, B_star, C_star, D)
#k1 = result.curvature(0)
#k2 = result.curvature(1)
#print("Res", k1, k2)
return result
def process(curve):
p = curve.get_degree()
if p != 3:
raise UnsupportedCurveTypeException("Only degree 3 curves are supported for now")
segments = curve.to_bezier_segments()
start_curvatures = []
end_curvatures = []
for segment in segments:
c1 = segment.curvature(0)
c2 = segment.curvature(1)
#print("Src", c1, c2)
start_curvatures.append(c1)
end_curvatures.append(c2)
target_curvatures = [start_curvatures[0]]
for c1, c2 in zip(end_curvatures[:-1], start_curvatures[1:]):
c = sqrt(c1*c2)
target_curvatures.append(c)
target_curvatures.append(end_curvatures[-1])
#print("Target", target_curvatures)
result = []
for segment, c1, c2 in zip(segments, target_curvatures[:-1], target_curvatures[1:]):
segment = process_segment(segment, c1, c2)
result.append(segment)
return concatenate_nurbs_curves(result)
curve_in = ensure_nesting_level(curve_in, 1, data_types=(SvCurve,))
curve_out = []
for curve in curve_in:
curve = SvNurbsCurve.to_nurbs(curve)
if curve is None:
raise UnsupportedCurveTypeException("One of curve is not NURBS")
curve = process(curve)
curve_out.append(curve)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment