Module sverchok.utils.surface.coons
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.sv_logging import sv_logger
from sverchok.utils.curve import knotvector as sv_knotvector
from sverchok.utils.curve.core import UnsupportedCurveTypeException
from sverchok.utils.curve.nurbs import SvNurbsCurve
from sverchok.utils.curve.algorithms import reverse_curve, reparametrize_curve, unify_curves_degree
from sverchok.utils.curve.nurbs_algorithms import unify_curves, unify_two_curves
from sverchok.utils.surface.core import SvSurface
from sverchok.utils.surface.nurbs import SvNurbsSurface
from sverchok.utils.surface.algorithms import SvCurveLerpSurface, unify_nurbs_surfaces
class SvCoonsSurface(SvSurface):
__description__ = "Coons Patch"
def __init__(self, curve1, curve2, curve3, curve4):
curve1 = reparametrize_curve(curve1)
curve2 = reparametrize_curve(curve2)
curve3 = reparametrize_curve(curve3)
curve4 = reparametrize_curve(curve4)
self.curve1 = curve1
self.curve2 = curve2
self.curve3 = curve3
self.curve4 = curve4
self.linear1 = SvCurveLerpSurface.build(curve1, reverse_curve(curve3))
self.linear2 = SvCurveLerpSurface.build(curve2, reverse_curve(curve4))
self.c1_t_min, self.c1_t_max = curve1.get_u_bounds()
self.c3_t_min, self.c3_t_max = curve3.get_u_bounds()
self.corner1 = self.curve1.evaluate(self.c1_t_min)
self.corner2 = self.curve1.evaluate(self.c1_t_max)
self.corner3 = self.curve3.evaluate(self.c3_t_max)
self.corner4 = self.curve3.evaluate(self.c3_t_min)
self.normal_delta = 0.001
def get_u_min(self):
return 0
def get_u_max(self):
return 1
def get_v_min(self):
return 0
def get_v_max(self):
return 1
def _calc_b(self, u, v, is_array):
corner1, corner2, corner3, corner4 = self.corner1, self.corner2, self.corner3, self.corner4
if is_array:
u = u[np.newaxis].T
v = v[np.newaxis].T
b = (corner1 * (1 - u) * (1 - v) + corner2 * u * (1 - v) + corner3 * (1 - u) * v + corner4 * u * v)
return b
def evaluate(self, u, v):
return self.linear1.evaluate(1-u, 1-v) + self.linear2.evaluate(1-v, u) - self._calc_b(1-u, 1-v, False)
def evaluate_array(self, us, vs):
return self.linear1.evaluate_array(1-us, 1-vs) + self.linear2.evaluate_array(1-vs, us) - self._calc_b(1-us, 1-vs, True)
GENERIC = 'GENERIC'
NURBS_ONLY = 'NURBS'
NURBS_IF_POSSIBLE = 'NURBS_OPTION'
def coons_surface(curve1, curve2, curve3, curve4, use_nurbs=NURBS_IF_POSSIBLE):
curves = [curve1, curve2, curve3, curve4]
nurbs_curves = [SvNurbsCurve.to_nurbs(c) for c in curves]
if use_nurbs == GENERIC:
return SvCoonsSurface(*curves)
if any(c is None for c in nurbs_curves):
if use_nurbs == NURBS_ONLY:
raise UnsupportedCurveTypeException("Some of curves are not NURBS")
else:
return SvCoonsSurface(*curves)
try:
nurbs_curves = [c.reparametrize(0,1) for c in nurbs_curves]
implementation = nurbs_curves[0].get_nurbs_implementation()
nurbs_curves[0], nurbs_curves[2] = unify_curves_degree([nurbs_curves[0], nurbs_curves[2]])
nurbs_curves[0], nurbs_curves[2] = unify_curves([nurbs_curves[0], nurbs_curves[2]])
nurbs_curves[1], nurbs_curves[3] = unify_curves_degree([nurbs_curves[1], nurbs_curves[3]])
nurbs_curves[1], nurbs_curves[3] = unify_curves([nurbs_curves[1], nurbs_curves[3]])
degree_u = nurbs_curves[0].get_degree()
degree_v = nurbs_curves[1].get_degree()
nurbs_curves[0] = reverse_curve(nurbs_curves[0])
nurbs_curves[3] = reverse_curve(nurbs_curves[3])
ruled1 = nurbs_curves[0].make_ruled_surface(nurbs_curves[2], 0, 1)
ruled2 = nurbs_curves[1].make_ruled_surface(nurbs_curves[3], 0, 1).swap_uv()
linear_kv = sv_knotvector.generate(1, 2)
c1_t_min, c1_t_max = nurbs_curves[0].get_u_bounds()
c3_t_min, c3_t_max = nurbs_curves[2].get_u_bounds()
pt1 = nurbs_curves[0].evaluate(c1_t_min)
pt2 = nurbs_curves[0].evaluate(c1_t_max)
pt3 = nurbs_curves[2].evaluate(c3_t_min)
pt4 = nurbs_curves[2].evaluate(c3_t_max)
w1 = nurbs_curves[0].get_weights()[0]
w2 = nurbs_curves[0].get_weights()[-1]
w3 = nurbs_curves[2].get_weights()[0]
w4 = nurbs_curves[2].get_weights()[-1]
linear_pts = np.array([[pt1,pt3], [pt2,pt4]])
linear_weights = np.array([[w1,w3], [w2,w4]])
#linear_weights = np.array([[1,1], [1,1]])
bilinear = SvNurbsSurface.build(implementation,
1, 1,
linear_kv, linear_kv,
linear_pts, linear_weights)
ruled1, ruled2, bilinear = unify_nurbs_surfaces([ruled1, ruled2, bilinear])
knotvector_u = ruled1.get_knotvector_u()
knotvector_v = ruled1.get_knotvector_v()
control_points = ruled1.get_control_points() + ruled2.get_control_points() - bilinear.get_control_points()
weights = ruled1.get_weights() + ruled2.get_weights() - bilinear.get_weights()
result = SvNurbsSurface.build(implementation,
degree_u, degree_v,
knotvector_u, knotvector_v,
control_points, weights)
return result
except UnsupportedCurveTypeException as e:
if use_nurbs == NURBS_ONLY:
raise
else:
sv_logger.info("Can't create a native Coons surface from curves %s: %s", curves, e)
return SvCoonsSurface(*curves)
Functions
def coons_surface(curve1, curve2, curve3, curve4, use_nurbs='NURBS_OPTION')
-
Expand source code
def coons_surface(curve1, curve2, curve3, curve4, use_nurbs=NURBS_IF_POSSIBLE): curves = [curve1, curve2, curve3, curve4] nurbs_curves = [SvNurbsCurve.to_nurbs(c) for c in curves] if use_nurbs == GENERIC: return SvCoonsSurface(*curves) if any(c is None for c in nurbs_curves): if use_nurbs == NURBS_ONLY: raise UnsupportedCurveTypeException("Some of curves are not NURBS") else: return SvCoonsSurface(*curves) try: nurbs_curves = [c.reparametrize(0,1) for c in nurbs_curves] implementation = nurbs_curves[0].get_nurbs_implementation() nurbs_curves[0], nurbs_curves[2] = unify_curves_degree([nurbs_curves[0], nurbs_curves[2]]) nurbs_curves[0], nurbs_curves[2] = unify_curves([nurbs_curves[0], nurbs_curves[2]]) nurbs_curves[1], nurbs_curves[3] = unify_curves_degree([nurbs_curves[1], nurbs_curves[3]]) nurbs_curves[1], nurbs_curves[3] = unify_curves([nurbs_curves[1], nurbs_curves[3]]) degree_u = nurbs_curves[0].get_degree() degree_v = nurbs_curves[1].get_degree() nurbs_curves[0] = reverse_curve(nurbs_curves[0]) nurbs_curves[3] = reverse_curve(nurbs_curves[3]) ruled1 = nurbs_curves[0].make_ruled_surface(nurbs_curves[2], 0, 1) ruled2 = nurbs_curves[1].make_ruled_surface(nurbs_curves[3], 0, 1).swap_uv() linear_kv = sv_knotvector.generate(1, 2) c1_t_min, c1_t_max = nurbs_curves[0].get_u_bounds() c3_t_min, c3_t_max = nurbs_curves[2].get_u_bounds() pt1 = nurbs_curves[0].evaluate(c1_t_min) pt2 = nurbs_curves[0].evaluate(c1_t_max) pt3 = nurbs_curves[2].evaluate(c3_t_min) pt4 = nurbs_curves[2].evaluate(c3_t_max) w1 = nurbs_curves[0].get_weights()[0] w2 = nurbs_curves[0].get_weights()[-1] w3 = nurbs_curves[2].get_weights()[0] w4 = nurbs_curves[2].get_weights()[-1] linear_pts = np.array([[pt1,pt3], [pt2,pt4]]) linear_weights = np.array([[w1,w3], [w2,w4]]) #linear_weights = np.array([[1,1], [1,1]]) bilinear = SvNurbsSurface.build(implementation, 1, 1, linear_kv, linear_kv, linear_pts, linear_weights) ruled1, ruled2, bilinear = unify_nurbs_surfaces([ruled1, ruled2, bilinear]) knotvector_u = ruled1.get_knotvector_u() knotvector_v = ruled1.get_knotvector_v() control_points = ruled1.get_control_points() + ruled2.get_control_points() - bilinear.get_control_points() weights = ruled1.get_weights() + ruled2.get_weights() - bilinear.get_weights() result = SvNurbsSurface.build(implementation, degree_u, degree_v, knotvector_u, knotvector_v, control_points, weights) return result except UnsupportedCurveTypeException as e: if use_nurbs == NURBS_ONLY: raise else: sv_logger.info("Can't create a native Coons surface from curves %s: %s", curves, e) return SvCoonsSurface(*curves)
Classes
class SvCoonsSurface (curve1, curve2, curve3, curve4)
-
Expand source code
class SvCoonsSurface(SvSurface): __description__ = "Coons Patch" def __init__(self, curve1, curve2, curve3, curve4): curve1 = reparametrize_curve(curve1) curve2 = reparametrize_curve(curve2) curve3 = reparametrize_curve(curve3) curve4 = reparametrize_curve(curve4) self.curve1 = curve1 self.curve2 = curve2 self.curve3 = curve3 self.curve4 = curve4 self.linear1 = SvCurveLerpSurface.build(curve1, reverse_curve(curve3)) self.linear2 = SvCurveLerpSurface.build(curve2, reverse_curve(curve4)) self.c1_t_min, self.c1_t_max = curve1.get_u_bounds() self.c3_t_min, self.c3_t_max = curve3.get_u_bounds() self.corner1 = self.curve1.evaluate(self.c1_t_min) self.corner2 = self.curve1.evaluate(self.c1_t_max) self.corner3 = self.curve3.evaluate(self.c3_t_max) self.corner4 = self.curve3.evaluate(self.c3_t_min) self.normal_delta = 0.001 def get_u_min(self): return 0 def get_u_max(self): return 1 def get_v_min(self): return 0 def get_v_max(self): return 1 def _calc_b(self, u, v, is_array): corner1, corner2, corner3, corner4 = self.corner1, self.corner2, self.corner3, self.corner4 if is_array: u = u[np.newaxis].T v = v[np.newaxis].T b = (corner1 * (1 - u) * (1 - v) + corner2 * u * (1 - v) + corner3 * (1 - u) * v + corner4 * u * v) return b def evaluate(self, u, v): return self.linear1.evaluate(1-u, 1-v) + self.linear2.evaluate(1-v, u) - self._calc_b(1-u, 1-v, False) def evaluate_array(self, us, vs): return self.linear1.evaluate_array(1-us, 1-vs) + self.linear2.evaluate_array(1-vs, us) - self._calc_b(1-us, 1-vs, True)
Ancestors
Methods
def evaluate(self, u, v)
-
Expand source code
def evaluate(self, u, v): return self.linear1.evaluate(1-u, 1-v) + self.linear2.evaluate(1-v, u) - self._calc_b(1-u, 1-v, False)
def evaluate_array(self, us, vs)
-
Expand source code
def evaluate_array(self, us, vs): return self.linear1.evaluate_array(1-us, 1-vs) + self.linear2.evaluate_array(1-vs, us) - self._calc_b(1-us, 1-vs, True)
def get_u_max(self)
-
Expand source code
def get_u_max(self): return 1
def get_u_min(self)
-
Expand source code
def get_u_min(self): return 0
def get_v_max(self)
-
Expand source code
def get_v_max(self): return 1
def get_v_min(self)
-
Expand source code
def get_v_min(self): return 0