Drawing charts

Hello,
could anyone help me? How to make graph of math formula? I mean something like drawing synthesiser envelope shape? I have also sliders that control independently attack, decay, sustain and release. And I would like the envelope graph (chart) will be updating with my sliders changing.
I tried to looking for something like that, but all tutorials and people on forums tell only about juce::paint and graphics, which actually allow me to draw already defined shapes like lines, rectangles, triangles and things like that.
I wonder, maybe I should just create my own class and inherit from graphics, and then create my own function that would draw from math formula?
I am not sure what to do. Sorry if itâ€™s stupid question but I am quite new in JUCE and in C++, and even in programming at all, and itâ€™s difficult for me

Of course I know I can draw simply envelope graph with simple lines. But my envelope is built from logarithmic lines, and I even have slider that changes those curves and I want to see those changes. That is why I need something to draw math formula.

Inherit from Component and implement the paint-method to draw your formula. You may need to resort to drawing your curve with individual drawLine calls on the Graphics object provided to the paint-method unless thereâ€™s some method in Graphics that replicates the shape of your math formula.

Hello,
As I remember, even when I drawn something really simple with that method and made it resizeable according to windows resize there was always some lagging.
So I think component paint method is good for some static graphics.
But maybe I am wrong, please correct me if I am.

I am also looking farther in the future, and I wonder how to let that graph of envelope to be click-drag able, so I could set ADSR parameters by dragging graph lines end points, or even to manipulate curves by dragging the whole lines.
And then to make a sense, sustain point should be able to draging in 2D (left/right to set decay, and up/down to set sustain level)

Oh manâ€¦ Maybe I am little impatient. But there is a lot of things to discover in JUCE, and discovering goes very slow and hard for me as begginer.

Yeah, youâ€™re misinterpreting whatever it was that you saw there.

For 2D graphics, paint() is pretty much optimal. Of course, it can go really slowly if you do something dumb in there. But itâ€™s pretty much the same performance youâ€™ll see from any other toolkit/platform, because they all do basically the same thing. For example on OSX or iOS, drawing stuff in paint() just calls straight through to CoreGraphics, just like a native OSX app does.

OK, so I need to make more experiences.

So maybe other question. Is it good idea to draw chart by drawing several small circles (for example 2 pixels diameter), and give them coordinates relative to my f(x) math formula?

No again
Best is to create a Path and use startNewSubPath() and lineTo(). This gives you a good start.

Good luck

If you want several small circles, then yes, drawing several small circles is probably a good ideaâ€¦

1 Like

Oh man, but Daniel above your post wrote itâ€™s not good (can you see his post?)
He told to use startNewSubPath() and lineTo().
But Iâ€™ve just read on startNewSubPath() and lineTo() and as I understand it draws line from point to point, so it would be straight line, not curve. Maybe Daniel thought about drawing several very short straight lines to provide curve. But then itâ€™s much less optimal (at least for my brain) than drawing just several circles - where each one has just two coordinates (for line you need two coordinates for both ends, so you need 4 coordinates).
So I have realy mess in mind.

Ok sorry, I donâ€™t know where you are with your skills. I meant to get you going. Any paint call will boil down to a lot of lines rasterised to pixels by the OS.
I mean to be fair, even better than to paint circles, which all have round shapes that need antialiasing and so forthâ€¦

You will get good results, if each line segment is about a pixel.

Another method is to use cubicTo(), if you know how to compute the parameters from your formula. But donâ€™t be disappointed if you care to look at the internals, the PathFlateningIterator will slice down your path and create a lot line segmentsâ€¦

But you say it right, start experimenting and find your way of doing it.

Good luck

OK, thanks I will try to experimenting.
Best Regards

Hello Boys and Girls.
I am so happy, Iâ€™ve just drawn my envelope shape. I finally used Daniel advice:
Path and use startNewSubPath() and lineTo()
Great thanks for your help. But now I want more, more moreâ€¦
How to update my envelope graph?
I have knob that allow me (by AudioProcessorValueTreeState) to change parameter of my logarithmic formula, so I can change shape of curves of Attack, Decay etc.
And it works for audio. As a beginner I am really excited. But unfortunately it doesnâ€™t work for graph. Graph is static with parameters which are initialised on the beginning.
I paint it in the JUCE::AudioProcessorEditor, which is main parent class for all other classes, and it is invoked only one time on the beginning. I canâ€™t execute AudioProcessorEditor more than one, or I donâ€™t know how.

So I tried inherit JUCE::Component class in my JUCE::AudioProcessor, where I have my AudioProcessorValueTreeState, audio is updating all the time, and where all things happen. So there I overrided Component::paint(Graphics& p), and resized() where I added bounds for my envelope, and than addAndMakeVissible in constructor, but it doesnâ€™t paint anything. xCode doesnâ€™t show me any errors, but it just doesnâ€™t paint.
Could anyone give me any advice how to make it work?
Great thanks in advance and best regards.

Add a listener to whatever is changing the settings and add the appropriate callback for this (for example, inherit from `Slider::Listener`, do `mySlider.addListener (this)` and add `void sliderValueChanged (Slider* slider)` to your editor if using a slider to change the curve settings) and call repaint inside of here. This will trigger the paint function to be called again every time you move the slider you have attached the listener to

edit: a bit of clarification

Ok, great thanks, but what exactly do you mean by â€¦repaintâ€¦
Do you mean to call addAndMakeCisible, or resized(), or paint(Graphics& p)?
I am asking because paint require something as a â€śGraphics& pâ€ť. I donâ€™t know what to put there. I see paint function is nowhere called in my code, it happesn somewhere deep in JUCE framework. So I am not sure how to recall that function.

That is painfully wrong, donâ€™t do that.

OK OK OK, I was just experimenting. I am still beginner.

Thanks for your warning, but I would be more grateful if you tell why itâ€™s wrong, beside that it doesnâ€™t work.

There is a function in there component class called `repaint()`which will mark the entire component as needing to be drawn again. This is useful when you want to update the look of a component (like you do here). Just write `repaint()` inside the slider changed callback

Hey man I fill I am closer to the solution, thanks. I made it, and it works, but the problem are:

1. there are great lagging, knob and graph work not fluid, just jumping and lagging
2. When I rotate the knob itâ€™s repainting but it multiplies the curves, you know what I mean? all changes are visible on the screen, changes doesnâ€™t clear the screen, so when I rotate knob I have a lot of curves. It should clear the screen each time I rotate knob, and show only one curve, updated one to appropriate value of my knob.

Maybe you could help if I show you my code for sliderValueChanged:

void WojtekSynthAudioProcessorEditor::sliderValueChanged (Slider slider)
{
if(slider == &attackShape)
{
for (int i=0; i<=1000; i++)
{
envGraphWindow.myPath.lineTo(envGraphWindow.startPointX+(i/10),
envGraphWindow.startPointY - (100
``````    }