following a curved path

Monkey Forums/Monkey Programming/following a curved path

dave.h(Posted 2013) [#1]
hi guys

ive figured out how to get an image too follow path with straight lines but im after creating a path that is curved or even spiralled.Am i right in thinking i need to figure out bezier curves for this and if so does anyone know of somme easy to follow tutorials.

what im after ultimately is for a particle emitter where i can make the spawn point of the emitter follow the curved path.Any pointers would be most welcome


Shagwana(Posted 2013) [#2]
Cant you make a curve from a number of straight lines?


dave.h(Posted 2013) [#3]
Yeah but it looks kinda jerky.that was something I tried but doesn't quite look good enuogh


Erik(Posted 2013) [#4]
The 2 functions I use for Beizer curves:
  Class P2
    Field X,Y
  End

  Function BezierArrayQuadratic:P2[](p1:P2,p2:P2,p3:P2,segments)
    Local i
    Local result := New List<P2>()

    For Local i := 0 Until segments
      Local t := Float(i) / segments

      Local a := Pow((1.0 - t), 2.0)
      Local b := 2.0 * t * (1.0 - t)
      Local c := Pow(t, 2.0)

      Local x := a * p1.X + b * p2.X + c * p3.X
      Local y := a * p1.Y + b * p2.Y + c * p3.Y

      result.AddLast(New P2(x,y))
    End
    Return result.ToArray()
  End

  Function BezierArrayCubic:P2[](p1:P2,p2:P2,p3:P2,p4:P2,segments)
    Local i
    Local result := New List<P2>()

    For Local i := 0 Until segments
        Local t := Float(i) / segments

        Local a := Pow((1.0 - t), 3.0)
        Local b := 3.0 * t * Pow((1.0 - t), 2.0)
        Local c := 3.0 * Pow(t, 2.0) * (1.0 - t)
        Local d := Pow(t, 3.0)

        Local x := a * p1.X + b * p2.X + c * p3.X + d * p4.X
        Local y := a * p1.Y + b * p2.Y + c * p3.Y + d * p4.Y

        result.AddLast(New P2(x,y))
    End

    Return result.ToArray()
  End



And then you could use the following to move between the values:

Global stLinear := New stLinearCl()

Class SimpleTween
  Method Do:Float(value:Float) Abstract
  Method Do:Float(fromvalue:Float, tovalue:Float, ratio:Float)
    Return Do(ratio)*(tovalue-fromvalue)+fromvalue
  End
  Method ToString:String() Abstract
End

Class stLinearCl Extends SimpleTween
  Method ToString:String()
    Return "linear"
  End
  Method Do:Float(value:Float) Final
    Return value
  End
End

Class stSinCl Extends SimpleTween
  Field frequency:Float
  Method ToString:String()
    Return "sin"
  End
  Method Do:Float(value:Float) Final
    Return Sin(value*360*frequency)
  End
End




dave.h(Posted 2013) [#5]
Cheers looks complex but I will study this after work tonight


muddy_shoes(Posted 2013) [#6]
For the most part you'll want to use bezier or other spline to define the curved path but to convert it to straight lines for actual usage. Not only is it faster to work with the straight lines but splines don't allow you to easily do things like find a point at a certain distance along the path.

Erik's code above looks like it spits out a straight line approximation of the bezier with a given number of segments. This may work fine for you but if you need to balance numbers of points with accuracy in the approximation then you might want to do something that continues or stops creating segments based on a measurement of the midpoint error.


Gerry Quinn(Posted 2013) [#7]
You can parameterise a Bezier. I did this in the past for my old HyperCurve screensaver. You plot your basic curve as a series of points, then for the portion of the curve nearest one of the points, you take that point and the two adjacent points, and generate four control points for a cubic curve. Then you can use a parameter from 0-1 to generate any point along the curve.

I don't remember the details but the C++ code looks like this, maybe it gives an idea of what I was doing:




skape(Posted 2013) [#8]
The first part of this might be helpful. It explains the ideas / math behind parametrizing bezier curves...


dave.h(Posted 2013) [#9]
thanks for all the feed back guys.lots of good info there.I wrote a test program using erics BezierArrayQuadratic function and got it working really easy.I plan to slightly modified it to save it to an array instead of list and i can use this to figure out where the spawn point should be over the life of the emitter.Well thats my theory anyway,no doubt i will hit a few probs along the way.On holiday next week so should have a working version in my editor by then.cheers