Who can teach me to make curve with multiple points?

I’d like to make a components to draw a curve with multiple points which could be more then 20 ?

It could be similar to MS Powerpoint function to draw curve.

1 Like

Well you’d just use a path, and Path::addQuadratic or addCubic to add curves to it. Doesn’t matter how many there are, it should be fast to draw at least a few thousand curves!

I was wondering how quadratic and cubic paths are rendered in JUCE. Are they simply evaluated at some number of points, with drawLine calls to connect the dots? Or is there a something more going on?

The reason I ask is that I’m working on a component that (among other things) needs to draw a cubic Bezier spline. If I’m stuck with drawLine calls, I’m a bit concerned about performance, since I typically need a large number of points (~30) for smooth line rendering.

No, you can’t render a curve with drawLine, it’d be a complete mess. They get turned into a stroked shape and rasterised like any other shape. The code’s all there in the Path and EdgeTable classes if you want to learn more.

I made simple way to draw inperpolated curve. becaus I need to make the curve to go through each knot, I used simple consine curve mechansim. bezier curve is not adoptable for this case becasue it draw spline curve with 3~4 points.

void WaveformComponent::DrawCosines(Graphics &g, Knot *pPoints, int nPoints)
{
double x;
double y;

for(int i = 0; i <= nPoints; i++)
{
    x = pPoints[i].getX();
    for(double u=0.0005;u<=1;u+=0.0005)
    {
		y = CosineInterpolate(pPoints[i].getY(),pPoints[i+1].getY(), u);
        g.setPixel(ROUND(x + (pPoints[i+1].getX() - pPoints[i].getX()) * u),ROUND(y));
    }
}

}

double WaveformComponent::CosineInterpolate(double y1,double y2,double mu)
{
double mu2;
const double PI = 3.14159265358979;
mu2 = (1-cos(muPI))/2;
return(y1
(1-mu2)+y2*mu2);
}

Why don’t you use Path::lineTo to add the points, then stroke the path to draw it? That’d look much prettier than just setting individual pixels.

I have a related problem.

I have a Component which draws the frequency response of a 3 band shelving filter on a dB/log-frequency scale.

for now I’m using a Path with cubic control points, adjusting the control points to approximate the real response and it works pretty well as long as settings are not too extreme.

However what would be the good approach to display the real magnitude response using Juce?

setting pixels individually doesn’t seem like the good approach and redoing the pixel oversampling/antialiasing myself either.

I would use Path with per-pixel linear control points:

Path path; int x = width; path.startNewSubPath(x, getAmp(x)); while (--x>=0) path.lineTo(x, getAmp(x));

ok I see, so this is finally just a variant of setting each pixels individually but the call to LineTo brings in the antialiasing.

is there any cons for this approach? performance?

on a slightly related note… say i have a path made up of curves, is there any function that can be written that could tell me a point along the path? not just the points that are used to define the path, but a point between two actual points. there’s obviously got to be some way of finding this, as we can draw them (so it puts the pixels down at all points along the path) but what about just trying to get them? the main problem would be units, but i guess a 0-1 float as a proportion for the total path length would be okay (or heck, even as a proportion between two points). i guess it involves just using quadratic/cubic formulae for each curve section using the point data, but i haven’t looked into what that involves - how very lazy of me! :slight_smile:

It’d probably be quite easy to get an estimate with the PathFlatteningIterator - that breaks it down into the small line segments that eventually get drawn, so if you iterated it, keeping a total of all the line lengths, you’d know how far you were. It’d probably be a bit error-prone though! Better to do the hard sums and calculate it properly!

1 Like

[quote=“mdsp”]ok I see, so this is finally just a variant of setting each pixels individually but the call to LineTo brings in the antialiasing.

is there any cons for this approach? performance?[/quote]

It might be a bit slower than filling pixels but it should be fast enough for real time use, and if you do have performance issues then you could always skip every other pixel. Just make sure you use a path instead of drawing lines directly in Graphics, otherwise the end caps won’t look as nice.