add Lane-Riesenfeld subdivision for lab2
This commit is contained in:
@@ -20,6 +20,7 @@ def ibspline(inputA, inputB=None):
|
|||||||
global save_message_xloc
|
global save_message_xloc
|
||||||
global num_sample
|
global num_sample
|
||||||
global curve_degree, knot_vector, add_cp_mode # added for Bspline
|
global curve_degree, knot_vector, add_cp_mode # added for Bspline
|
||||||
|
global ax_lr_button, lr_button # added for Lane-Riesenfeld
|
||||||
|
|
||||||
# de Boor's algorithm to evaluate a point on a B-spline.
|
# de Boor's algorithm to evaluate a point on a B-spline.
|
||||||
# Returns (x, y) coordinate at parameter t
|
# Returns (x, y) coordinate at parameter t
|
||||||
@@ -119,6 +120,7 @@ def ibspline(inputA, inputB=None):
|
|||||||
plt.plot(vX, vY, 'ob', picker=True, pickradius=5)
|
plt.plot(vX, vY, 'ob', picker=True, pickradius=5)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# Redraw the entire plot
|
# Redraw the entire plot
|
||||||
def redrawPlot(vX, vY):
|
def redrawPlot(vX, vY):
|
||||||
global text_message, ax
|
global text_message, ax
|
||||||
@@ -187,6 +189,58 @@ def ibspline(inputA, inputB=None):
|
|||||||
|
|
||||||
# CallbackS
|
# CallbackS
|
||||||
|
|
||||||
|
# Lane-Riesenfeld subdivision callback
|
||||||
|
def lrSubdivideCallback(event):
|
||||||
|
global vX, vY, curve_degree, knot_vector
|
||||||
|
|
||||||
|
if len(vX) == 0: return
|
||||||
|
|
||||||
|
# Check if knot vector is uniform
|
||||||
|
is_uniform = True
|
||||||
|
if len(knot_vector) > 1:
|
||||||
|
diff = knot_vector[1] - knot_vector[0]
|
||||||
|
for i in range(1, len(knot_vector) - 1):
|
||||||
|
if abs((knot_vector[i+1] - knot_vector[i]) - diff) > 1e-5:
|
||||||
|
is_uniform = False
|
||||||
|
break
|
||||||
|
|
||||||
|
if not is_uniform:
|
||||||
|
outputPlotMessage("Error: LR-Subdivide requires uniform knot distances.")
|
||||||
|
plt.draw()
|
||||||
|
return
|
||||||
|
|
||||||
|
n = curve_degree
|
||||||
|
m = len(vX)
|
||||||
|
points = list(zip(vX, vY))
|
||||||
|
|
||||||
|
# Step 1: Double the points (P0, P0, P1, P1, ...)
|
||||||
|
doubled_points = []
|
||||||
|
for p in points:
|
||||||
|
doubled_points.append(p)
|
||||||
|
doubled_points.append(p)
|
||||||
|
|
||||||
|
# Step 2: Apply moving average n times
|
||||||
|
for _ in range(n):
|
||||||
|
smoothed_points = []
|
||||||
|
# Average adjacent points
|
||||||
|
for i in range(len(doubled_points) - 1):
|
||||||
|
px = (doubled_points[i][0] + doubled_points[i+1][0]) / 2.0
|
||||||
|
py = (doubled_points[i][1] + doubled_points[i+1][1]) / 2.0
|
||||||
|
smoothed_points.append((px, py))
|
||||||
|
doubled_points = smoothed_points
|
||||||
|
|
||||||
|
# Update vX and vY
|
||||||
|
vX = [p[0] for p in doubled_points]
|
||||||
|
vY = [p[1] for p in doubled_points]
|
||||||
|
|
||||||
|
# update knot : maintain uniformity but increase density
|
||||||
|
new_m = len(vX)
|
||||||
|
knot_vector = list(range(1, new_m + curve_degree + 1))
|
||||||
|
|
||||||
|
outputPlotMessage(f"LR-Subdivide applied. (m={len(vX)})")
|
||||||
|
redrawPlot(vX, vY)
|
||||||
|
return
|
||||||
|
|
||||||
# callback of add cp
|
# callback of add cp
|
||||||
def addCPButtonCallback(event):
|
def addCPButtonCallback(event):
|
||||||
global add_cp_mode
|
global add_cp_mode
|
||||||
@@ -265,6 +319,7 @@ def ibspline(inputA, inputB=None):
|
|||||||
def createButtons(left_pos, button_width, button_height):
|
def createButtons(left_pos, button_width, button_height):
|
||||||
global ax_add_button, add_button
|
global ax_add_button, add_button
|
||||||
global ax_save_button, save_button
|
global ax_save_button, save_button
|
||||||
|
global ax_lr_button, lr_button
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
inactive_color = 'lightgray'
|
inactive_color = 'lightgray'
|
||||||
@@ -276,6 +331,13 @@ def ibspline(inputA, inputB=None):
|
|||||||
add_button.color = inactive_color
|
add_button.color = inactive_color
|
||||||
add_button.hovercolor = inactive_color
|
add_button.hovercolor = inactive_color
|
||||||
|
|
||||||
|
# LR-Subdivide
|
||||||
|
ax_lr_button = plt.axes([left_pos, 0.7, button_width, button_height])
|
||||||
|
lr_button = Button(ax_lr_button, "LR-Sub")
|
||||||
|
lr_button.on_clicked(lrSubdivideCallback)
|
||||||
|
lr_button.color = inactive_color
|
||||||
|
lr_button.hovercolor = inactive_color
|
||||||
|
|
||||||
# Save
|
# Save
|
||||||
ax_save_button = plt.axes([left_pos, 0.6, button_width, button_height])
|
ax_save_button = plt.axes([left_pos, 0.6, button_width, button_height])
|
||||||
save_button = Button(ax_save_button, "Save")
|
save_button = Button(ax_save_button, "Save")
|
||||||
@@ -288,10 +350,12 @@ def ibspline(inputA, inputB=None):
|
|||||||
|
|
||||||
# not enable all buttons as smooth needs subdivision first
|
# not enable all buttons as smooth needs subdivision first
|
||||||
def enableButtons():
|
def enableButtons():
|
||||||
global add_button, save_button
|
global add_button, save_button, lr_button
|
||||||
|
|
||||||
add_button.color = 'white'
|
add_button.color = 'white'
|
||||||
add_button.hovercolor = 'green'
|
add_button.hovercolor = 'green'
|
||||||
|
lr_button.color = 'white'
|
||||||
|
lr_button.hovercolor = 'green'
|
||||||
save_button.color = 'white'
|
save_button.color = 'white'
|
||||||
save_button.hovercolor = 'green'
|
save_button.hovercolor = 'green'
|
||||||
plt.draw()
|
plt.draw()
|
||||||
|
|||||||
Reference in New Issue
Block a user