From 58e4d59aa83f0bd39d87418d2e3a43021200d4b9 Mon Sep 17 00:00:00 2001 From: Alex Clink Date: Fri, 25 Feb 2022 00:38:53 -0500 Subject: [PATCH] Add rect / bounding_box to cubic bezier --- examples/cubic_bezier.cr | 29 +++++++++++++---------------- src/bezier/cubic.cr | 35 ++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/examples/cubic_bezier.cr b/examples/cubic_bezier.cr index 9e50c1c..d688e31 100644 --- a/examples/cubic_bezier.cr +++ b/examples/cubic_bezier.cr @@ -31,12 +31,12 @@ module PF def update(dt, event) case event when SDL::Event::MouseButton - if event.pressed? && event.button == 1 - @selected_point = @hover_point - end - - if event.released? && event.button == 1 - @selected_point = nil + if event.button == 1 + if event.pressed? + @selected_point = @hover_point + else + @selected_point = nil + end end when SDL::Event::MouseMotion @mouse_pos = Vector[event.x, event.y] // scale @@ -44,8 +44,7 @@ module PF unless point = @selected_point @hover_point = @curve.points.find { |p| @mouse_pos.distance(p.value) < 4 } else - point.value.x = @mouse_pos.x.to_f - point.value.y = @mouse_pos.y.to_f + point.value = @mouse_pos.to_f end end end @@ -57,16 +56,14 @@ module PF draw_line(@curve.p3, @curve.p2, CTL_COLOR) draw_string("Length: " + @curve.length.round(2).to_s, 5, 5, FONT_COLOR) + + draw_rect(*@curve.rect.map(&.to_i), CTL_COLOR) draw_curve(@curve, CURVE_COLOR) - ext_x, ext_y = @curve.extremeties - - ext_x.each do |point| - draw_circle(point.to_i, 3, EXT_X_COLOR) - end - - ext_y.each do |point| - draw_circle(point.to_i, 3, EXT_Y_COLOR) + @curve.extremeties.each do |point| + point.try do |p| + draw_circle(p.to_i, 3, EXT_Y_COLOR) + end end fill_circle(@curve.p0.to_i, 2, POINT_COLOR) diff --git a/src/bezier/cubic.cr b/src/bezier/cubic.cr index 34494a7..58524f0 100644 --- a/src/bezier/cubic.cr +++ b/src/bezier/cubic.cr @@ -24,7 +24,7 @@ module PF disc = b * b - 4 * a * c - return Tuple.new unless disc >= 0 + return {nil, nil} unless disc >= 0 t1 = (-b + Math.sqrt(disc)) / (2 * a) t2 = (-b - Math.sqrt(disc)) / (2 * a) @@ -35,11 +35,11 @@ module PF if accept_1 && accept_2 {t1, t2} elsif accept_1 - {t1} + {t1, nil} elsif accept_2 - {t2} + {nil, t2} else - {0.5} + {0.5, nil} end end @@ -80,14 +80,31 @@ module PF end # Get the points at the extremeties of this curve + # note: Will return 4 values which are either Float64 | nil def extremeties - txs = self.class.extremeties(@p0.x, @p1.x, @p2.x, @p3.x) - tys = self.class.extremeties(@p0.y, @p1.y, @p2.y, @p3.y) + exts = self.class.extremeties(@p0.x, @p1.x, @p2.x, @p3.x) + + self.class.extremeties(@p0.y, @p1.y, @p2.y, @p3.y) + exts.map { |e| e ? at(e) : e } + end - txs = txs.map { |t| at(t) } - tys = tys.map { |t| at(t) } + def rect + tl, br = @p0, @p3 - {txs, tys} + tl.x = @p3.x if @p3.x < tl.x + tl.y = @p3.y if @p3.y < tl.y + br.x = @p0.x if @p0.x > br.x + br.y = @p0.y if @p0.y > br.y + + extremeties.each do |e| + e.try do |e| + tl.x = e.x if e.x < tl.x + tl.y = e.y if e.y < tl.y + br.x = e.x if e.x > br.x + br.y = e.y if e.y > br.y + end + end + + {tl, br} end end end