Reading points from a Path object

I am creating an interactive spline UI control. I am extending the Drawable component and the objective is that the user can add points to the curve and move then around to shape the curve.

I will be using the path.cubicTo method so the points are joined by cubic curves. Once this is done, I want to parse the curve and build a set of data points with (x,y) coordinates. I have looked at the getPointAlongPath method, but dont think this is what I am looking for. I want to pass the path a series of x coordinates and get the y coordinates in return.

Is there an existing way to do this?

I have looked at Is there a class to draw and edit splines? post. It looks like quite an old post with the links not working currently.

There is Path::Iterator and PathFlatteningIterator, both should do what you need.

Thanks oli1 I for your quick response.

I am not sure it addresses what I am looking for (or I am getting confused with the documentation). I will give an example.

Lets say I use a path to create a straight line as below:

mypath.startNewSubPath(0.0,0.0);
myPath.lineTo(10.0,10.0);

This would create a straight line from co-ordinates (0,0) to (10,10). I now want to find out what is y when x = 5.

The example is a simplistic case. What I am really interested in, is solving this for for cubic splines. Since Juce is already doing the calculations to plot the curve/line, I am trying to leverage that. The alternate is to creating my own cubic-spline equation solver.

I don’t think JUCE offers a function to find a point on a straight line, but that’s quite trivial to do yourself.

The pathFlatteningIterator turns the spline into many small straight line segments. You can then use these line segments to calculate the x/y coordinates of any point on the spline.

Perhaps you would rather manage the splines yourself, without relying on juce::Path. I found this video very useful for doing something similar:

1 Like

But I think it does: check the https://docs.juce.com/master/classLine.html, and its functions getPointAlongLine() or getPointAlongLineProportionally()

The juce::Path class is a 2 dimensional path, so it is not suitable to check what Y over X is. It is defined in the form f(t) rather than f(x).

If you need to use the juce::Path class, then you need to iterate the juce::PathFlatteningIterator and see if the line segment crosses your X coordinate. But there can be any number of valid results, since the path can go in circles orwhatever form.

I think what you really want is covered in Signalsmiths excellent blog post:

You can scroll down for a C++ implementation which works perfect for me

1 Like

To be exact, those methods let you find a point given a distance along a line, but I was thinking of finding out what y is given x, which is what the OP was after. As Daniel pointed out, that can be done by checking if/where the line segment crosses a vertical line on the x coordinate (using intersects()).

While we are at it, maybe the documentation of the Path::Iterator could be improved so it specifies, what exactly is x1, y1 or x2, y2 or x3, y3. The textual explanation is a bit hard to read, so that I usually had to resort to the source code to be sure.

Even better would be if those were juce::Point instances, but that might be too much of a change.
But if you are up for it, something like:

Point<float> position;
Point<float> leftControl;
Point<float> rightControl;

would make code much more readable.

@aamf - Thanks. I had a look at the video and it is indeed helpful. I will try to spend some time on the weekend to work out my own spline solver.

@daniel - I was shying away from doing this as I will then have to plot the curve on screen myself and I was trying to see if I could use the Path object to do the hard work for me. But it looks like I have no other option.

re: finding the point using vertical lines, conceptually it feels like too much computation. But, will explore based on how complex the code becomes.

1 Like

The drawing code is really trivial. Just loop over X and call lineTo.
There are a few things in terms of optimisation, either:

  • keep the path as member but call clear() at the beginning or:
  • call ensureAllocatedSpace() on the path to make sure the array doesn’t need to reallocate on every pixel.

Thanks all. I got a little bogged down with the “mathematics” of drawing the spline. What took a while was understanding the C++ examples out there. All of them use GLM, Eigen or some other library to perform vector arithmetic and the library was too heavy for my simple purposes (I mean it has a lot of other stuff I did not really want).

But I finally managed to get a lightweight opensource Spline Header File that I could use for my purpose. I still dont understand the mathematics behind it, but this will do for now.