Коммит f153ab27 создал по автору Ilya Portnov's avatar Ilya Portnov
Просмотр файлов

"Move NURBS curve point" node.

владелец faad970c
......@@ -70,6 +70,8 @@
SvDeconstructCurveNode
SvNurbsCurveNodesNode
---
SvNurbsCurveMovePointNode
---
SvCurveInsertKnotNode
SvCurveRemoveKnotNode
SvRefineNurbsCurveNode
......
# 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
import bpy
from bpy.props import FloatProperty, EnumProperty, BoolProperty, IntProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode, zip_long_repeat, ensure_nesting_level, get_data_nesting_level, repeat_last_for_length
from sverchok.utils.curve import SvCurve
from sverchok.utils.curve.nurbs import SvNurbsCurve
from sverchok.utils.curve.nurbs_algorithms import (
move_curve_point_by_moving_control_point,
move_curve_point_by_adjusting_one_weight,
move_curve_point_by_adjusting_two_weights,
move_curve_point_by_moving_control_points,
move_curve_point_by_inserting_knot)
class SvNurbsCurveMovePointNode(bpy.types.Node, SverchCustomTreeNode):
"""
Triggers: Move NURBS curve point
Tooltip: Adjust NURBS curve to move it's point to another location
"""
bl_idname = 'SvNurbsCurveMovePointNode'
bl_label = 'Move NURBS Curve Point'
bl_icon = 'OUTLINER_OB_EMPTY'
sv_icon = 'SV_CURVE_INSERT_KNOT'
methods = [
('ONE_CPT', "Move one control point", "Move single control point", 0),
('ONE_WEIGHT', "Adjust one weight", "Change single weight", 1),
('TWO_WEIGHTS', "Adjust two weights", "Change two weights", 2),
('MOVE_CPTS', "Move control points", "Move several control points", 3),
('INSERT_KNOT', "Insert knot", "Insert additional knot and move several control points", 4)
]
def update_sockets(self, context):
self.inputs['Index'].hide_safe = self.method not in ['ONE_CPT', 'ONE_WEIGHT', 'TWO_WEIGHTS']
self.inputs['Distance'].hide_safe = self.method not in ['ONE_WEIGHT', 'TWO_WEIGHTS']
self.inputs['Vector'].hide_safe = self.method not in ['ONE_CPT', 'MOVE_CPTS', 'INSERT_KNOT']
updateNode(self, context)
method : EnumProperty(
name = "Method",
description = "How should we modify the curve control points or weights",
items = methods,
default = 'ONE_CPT',
update = update_sockets)
t_value : FloatProperty(
name = "T",
description = "Curve parameter value",
default = 0.5,
update = updateNode)
idx : IntProperty(
name = "Index",
description = "Control point or weight index to be adjusted",
default = 1,
min = 0,
update = updateNode)
distance : FloatProperty(
name = "Distance",
description = "How far to move the point; negative value mean move in the opposite direction",
default = 1.0,
update = updateNode)
def draw_buttons(self, context, layout):
layout.prop(self, 'method')
def sv_init(self, context):
self.inputs.new('SvCurveSocket', "Curve")
self.inputs.new('SvStringsSocket', "T").prop_name = 't_value'
self.inputs.new('SvStringsSocket', "Index").prop_name = 'idx'
self.inputs.new('SvStringsSocket', "Distance").prop_name = 'distance'
p = self.inputs.new('SvVerticesSocket', "Vector")
p.use_prop = True
p.default_property = (1.0, 0.0, 0.0)
self.outputs.new('SvCurveSocket', "Curve")
self.update_sockets(context)
def process(self):
if not any(socket.is_linked for socket in self.outputs):
return
curve_s = self.inputs['Curve'].sv_get()
t_value_s = self.inputs['T'].sv_get()
index_s = self.inputs['Index'].sv_get()
distance_s = self.inputs['Distance'].sv_get()
vector_s = self.inputs['Vector'].sv_get()
input_level = get_data_nesting_level(curve_s, data_types=(SvCurve,))
flat_output = input_level < 2
curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve,))
t_value_s = ensure_nesting_level(t_value_s, 2)
index_s = ensure_nesting_level(index_s, 2)
distance_s = ensure_nesting_level(distance_s, 2)
vector_s = ensure_nesting_level(vector_s, 3)
curves_out = []
for params in zip_long_repeat(curve_s, t_value_s, index_s, distance_s, vector_s):
new_curves = []
for curve, t_value, index, distance, vector in zip_long_repeat(*params):
curve = SvNurbsCurve.to_nurbs(curve)
if curve is None:
raise Exception("One of curves is not NURBS")
vector = np.array(vector)
if self.method == 'ONE_CPT':
curve = move_curve_point_by_moving_control_point(curve, t_value, index, vector)
elif self.method == 'ONE_WEIGHT':
curve = move_curve_point_by_adjusting_one_weight(curve, t_value, index, distance)
elif self.method == 'TWO_WEIGHTS':
curve = move_curve_point_by_adjusting_two_weights(curve, t_value, index, distance=distance)
elif self.method == 'MOVE_CPTS':
curve = move_curve_point_by_moving_control_points(curve, t_value, vector)
elif self.method == 'INSERT_KNOT':
curve = move_curve_point_by_inserting_knot(curve, t_value, vector)
else:
raise Exception("Unsupported method")
new_curves.append(curve)
if flat_output:
curves_out.extend(new_curves)
else:
curves_out.append(new_curves)
self.outputs['Curve'].sv_set(curves_out)
def register():
bpy.utils.register_class(SvNurbsCurveMovePointNode)
def unregister():
bpy.utils.unregister_class(SNurbsCurveMovePointNodevCurveInsertKnotNode)
......@@ -693,6 +693,8 @@ def move_curve_point_by_moving_control_point(curve, u_bar, k, vector):
vector = vector / distance
functions = SvNurbsBasisFunctions(curve.get_knotvector())
x = functions.fraction(k,p, weights)(np.array([u_bar]))[0]
if abs(x) < 1e-6:
raise Exception(f"Specified control point #{k} is too far from curve parameter U = {u_bar}")
alpha = distance / x
cpts[k] = cpts[k] + alpha * vector
return curve.copy(control_points = cpts)
......@@ -798,6 +800,10 @@ def move_curve_point_by_adjusting_two_weights(curve, u_bar, k, distance=None, sc
abk = np.linalg.norm(D - pk1) / control_leg_len
abk1 = np.linalg.norm(C - pk) / control_leg_len
eps = 1e-6
if abs(ak) < eps or abs(abk) < eps or abs(ak1) < eps or abs(abk1) < eps:
raise Exception(f"Specified control point #{k} is too far from curve parameter U = {u_bar}")
numerator = 1.0 - ak - ak1
numerator_brave = 1.0 - abk - abk1
......@@ -813,7 +819,7 @@ def move_curve_point_by_adjusting_two_weights(curve, u_bar, k, distance=None, sc
WEIGHTS_NONE = 'NONE'
WEIGHTS_EUCLIDIAN = 'EUCLIDIAN'
def move_curve_point_by_moving_control_points(curve, u_bar, vector, weight_mode = WEIGHTS_NONE):
def move_curve_point_by_moving_control_points(curve, u_bar, vector, weights_mode = WEIGHTS_NONE):
"""
Adjust the given curve so that at parameter u_bar it goues through
the point C[u_bar] + vector instead of C[u_bar].
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать