Skip to content

Commit

Permalink
"Move NURBS curve point" node: add Absolute mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
portnov committed Oct 27, 2024
1 parent 2b817c6 commit 80d1045
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 10 deletions.
13 changes: 9 additions & 4 deletions docs/nodes/curve/move_nurbs_curve_point.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@ This node has the following inputs:

The default value is 1.0.

* **Vector**. The vector for which the curve point at **T** parameter is to be
moved. This input is available only when **Method** is set to **Move one
control point**, **Move control points**, or **Insert knot**. The default
value is ``(1.0, 0.0, 0.0)``.
* **Vector** / **Point**. This input is available only when **Method** is set
to **Move one control point**, **Move control points**, or **Insert knot**.
If **Mode** parameter is set to **Relative**, this input specifies the vector
for which the curve point at **T** parameter is to be moved. In **Absolute**
mode, this input specifies the point where curve point is to be moved to. The
default value is ``(1.0, 0.0, 0.0)``.

Parameters
----------
Expand Down Expand Up @@ -93,6 +95,9 @@ This node has the following parameters:
direction of curve tangent at the point being moved. In many cases, this
gives only a slight difference; but sometimes this will make the result
smoother. Unchecked by default.
* **Mode**. The available options are **Relative** and **Absolute**. In the
**Relative** mode, you specify the movement vector; in the **Absolute** mode,
you specify the target point. The default mode is **Relative**.

Outputs
-------
Expand Down
22 changes: 19 additions & 3 deletions nodes/curve/move_nurbs_curve_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,16 @@ class SvNurbsCurveMovePointNode(SverchCustomTreeNode, bpy.types.Node):
('INSERT_KNOT', "Insert knot", "Insert additional knot and move several control points", 4)
]

modes = [
('REL', "Relative", "Specify vector by which the point is to be moved", 0),
('ABS', "Absolute", "Specify target place where to place the point", 2)
]

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']
self.inputs['Vector'].label = 'Vector' if self.vector_mode == 'REL' else 'Point'
updateNode(self, context)

method : EnumProperty(
Expand All @@ -52,6 +58,12 @@ def update_sockets(self, context):
default = 'ONE_CPT',
update = update_sockets)

vector_mode : EnumProperty(
name = "Mode",
items = modes,
default = 'REL',
update = update_sockets)

t_value : FloatProperty(
name = "T",
description = "Curve parameter value",
Expand All @@ -78,6 +90,8 @@ def update_sockets(self, context):

def draw_buttons(self, context, layout):
layout.prop(self, 'method')
if self.method in ['ONE_CPT', 'MOVE_CPTS', 'INSERT_KNOT']:
layout.prop(self, 'vector_mode')
if self.method == 'MOVE_CPTS':
layout.prop(self, 'preserve_tangent')

Expand Down Expand Up @@ -111,6 +125,8 @@ def process(self):
distance_s = ensure_nesting_level(distance_s, 2)
vector_s = ensure_nesting_level(vector_s, 3)

relative = self.vector_mode == 'REL'

curves_out = []
for params in zip_long_repeat(curve_s, t_value_s, index_s, distance_s, vector_s):
new_curves = []
Expand All @@ -121,7 +137,7 @@ def process(self):

vector = np.array(vector)
if self.method == 'ONE_CPT':
new_curve = move_curve_point_by_moving_control_point(curve, t_value, index, vector)
new_curve = move_curve_point_by_moving_control_point(curve, t_value, index, vector, relative=relative)
elif self.method == 'ONE_WEIGHT':
new_curve = move_curve_point_by_adjusting_one_weight(curve, t_value, index, distance)
elif self.method == 'TWO_WEIGHTS':
Expand All @@ -131,9 +147,9 @@ def process(self):
tangent = TANGENT_PRESERVE
else:
tangent = None
new_curve = move_curve_point_by_moving_control_points(curve, t_value, vector, tangent=tangent)
new_curve = move_curve_point_by_moving_control_points(curve, t_value, vector, tangent=tangent, relative=relative)
elif self.method == 'INSERT_KNOT':
new_curve = move_curve_point_by_inserting_knot(curve, t_value, vector)
new_curve = move_curve_point_by_inserting_knot(curve, t_value, vector, relative=relative)
else:
raise Exception("Unsupported method")

Expand Down
14 changes: 11 additions & 3 deletions utils/curve/nurbs_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ def offset_nurbs_curve(curve, offset_vector,
offset_curve = remove_excessive_knots(offset_curve, tolerance = target_tolerance)
return offset_curve

def move_curve_point_by_moving_control_point(curve, u_bar, k, vector):
def move_curve_point_by_moving_control_point(curve, u_bar, k, vector, relative=True):
"""
Adjust the given curve so that at parameter u_bar it goes through
the point C[u_bar] + vector instead of C[u_bar].
Expand All @@ -626,6 +626,9 @@ def move_curve_point_by_moving_control_point(curve, u_bar, k, vector):
cpts = curve.get_control_points().copy()
weights = curve.get_weights()
vector = np.array(vector)
if not relative:
src_pt = curve.evaluate(u_bar)
vector = vector - src_pt
distance = np.linalg.norm(vector)
vector = vector / distance
functions = SvNurbsBasisFunctions(curve.get_knotvector())
Expand Down Expand Up @@ -757,7 +760,7 @@ def move_curve_point_by_adjusting_two_weights(curve, u_bar, k, distance=None, sc
WEIGHTS_EUCLIDIAN = 'EUCLIDIAN'
TANGENT_PRESERVE = 'PRESERVE'

def move_curve_point_by_moving_control_points(curve, u_bar, vector, weights_mode = WEIGHTS_NONE, tangent = None):
def move_curve_point_by_moving_control_points(curve, u_bar, vector, weights_mode = WEIGHTS_NONE, tangent = None, relative=True):
"""
Adjust the given curve so that at parameter u_bar it goues through
the point C[u_bar] + vector instead of C[u_bar].
Expand Down Expand Up @@ -813,6 +816,9 @@ def move_curve_point_by_moving_control_points(curve, u_bar, vector, weights_mode
ndim = 3
cpts = curve.get_control_points().copy()
curve_weights = curve.get_weights()
if not relative:
src_pt = curve.evaluate(u_bar)
vector = vector - src_pt
if weights_mode == WEIGHTS_EUCLIDIAN:
pt0 = curve.evaluate(u_bar)
pt1 = pt0 + vector
Expand Down Expand Up @@ -853,7 +859,7 @@ def move_curve_point_by_moving_control_points(curve, u_bar, vector, weights_mode
cpts = cpts + d_cpts
return curve.copy(control_points = cpts)

def move_curve_point_by_inserting_knot(curve, u_bar, vector):
def move_curve_point_by_inserting_knot(curve, u_bar, vector, relative=True):
"""
Adjust the given curve so that at parameter u_bar it goues through
the point C[u_bar] + vector instead of C[u_bar].
Expand All @@ -867,6 +873,8 @@ def move_curve_point_by_inserting_knot(curve, u_bar, vector):
you want the point to be moved
"""
pt0 = curve.evaluate(u_bar)
if not relative:
vector = vector - pt0
p = curve.get_degree()
curve2 = curve.insert_knot(u_bar, p-1, if_possible=True)
cpts = curve2.get_control_points().copy()
Expand Down

0 comments on commit 80d1045

Please sign in to comment.