Add extremities finding for cubic bezier

This commit is contained in:
Alex Clink 2022-02-24 00:02:40 -05:00
parent 8a9adf13c7
commit 09479bdc45
3 changed files with 51 additions and 2 deletions

View file

@ -8,6 +8,8 @@ module PF
CTL_COLOR = Pixel.new(0x505050FF) CTL_COLOR = Pixel.new(0x505050FF)
CURVE_COLOR = Pixel.new(0x0077FFFF) CURVE_COLOR = Pixel.new(0x0077FFFF)
SEL_COLOR = Pixel.new(0xFFFF00FF) SEL_COLOR = Pixel.new(0xFFFF00FF)
EXT_X_COLOR = Pixel.new(0xFF00FFFF)
EXT_Y_COLOR = Pixel.new(0x00FF00FF)
@curve : Bezier::Cubic(Float64) @curve : Bezier::Cubic(Float64)
@ -57,6 +59,16 @@ module PF
draw_string("Length: " + @curve.length.round(2).to_s, 5, 5, FONT_COLOR) draw_string("Length: " + @curve.length.round(2).to_s, 5, 5, FONT_COLOR)
draw_curve(@curve, CURVE_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)
end
fill_circle(@curve.p0.to_i, 2, POINT_COLOR) fill_circle(@curve.p0.to_i, 2, POINT_COLOR)
fill_circle(@curve.p1.to_i, 2, POINT_COLOR) fill_circle(@curve.p1.to_i, 2, POINT_COLOR)
fill_circle(@curve.p2.to_i, 2, POINT_COLOR) fill_circle(@curve.p2.to_i, 2, POINT_COLOR)

View file

@ -17,6 +17,32 @@ module PF
6 * (1 - t) * (p2 - 2 * p1 + p0) + 6 * t * (p3 - 2 * p2 + p1) 6 * (1 - t) * (p2 - 2 * p1 + p0) + 6 * t * (p3 - 2 * p2 + p1)
end end
def self.extremeties(p0 : Number, p1 : Number, p2 : Number, p3 : Number)
a = 3 * p3 - 9 * p2 + 9 * p1 - 3 * p0
b = 6 * p0 - 12 * p1 + 6 * p2
c = 3 * p1 - 3 * p0
disc = b * b - 4 * a * c
return Tuple.new unless disc >= 0
t1 = (-b + Math.sqrt(disc)) / (2 * a)
t2 = (-b - Math.sqrt(disc)) / (2 * a)
accept_1 = t1 >= 0 && t1 <= 1
accept_2 = t2 >= 0 && t2 <= 1
if accept_1 && accept_2
{t1, t2}
elsif accept_1
{t1}
elsif accept_2
{t2}
else
{0.5}
end
end
property p0 : Vector2(T) property p0 : Vector2(T)
property p1 : Vector2(T) property p1 : Vector2(T)
property p2 : Vector2(T) property p2 : Vector2(T)
@ -52,6 +78,17 @@ module PF
T.new(-self.class.derivative(t, @p0.x, @p1.x, @p2.x, @p3.x)), T.new(-self.class.derivative(t, @p0.x, @p1.x, @p2.x, @p3.x)),
].normalized ].normalized
end end
# Get the points at the extremeties of this curve
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)
txs = txs.map { |t| at(t) }
tys = tys.map { |t| at(t) }
{txs, tys}
end
end end
end end
end end

View file

@ -1,6 +1,6 @@
module PF module PF
class Sprite class Sprite
def draw_curve(curve : Bezier::Cubic, samples : Int = 100, pixel : Pixel = Pixel.new) def draw_curve(curve : Bezier::Cubic | Bezier::Quad, samples : Int = 100, pixel : Pixel = Pixel.new)
point = curve.p0 point = curve.p0
0.upto(samples) do |x| 0.upto(samples) do |x|
t = x / samples t = x / samples
@ -10,7 +10,7 @@ module PF
end end
end end
def draw_curve(curve : Bezier::Cubic, pixel : Pixel) def draw_curve(curve : Bezier::Cubic | Bezier::Quad, pixel : Pixel)
draw_curve(curve, pixel: pixel) draw_curve(curve, pixel: pixel)
end end
end end