Creating curves with MGraphics

Anthony Palomba's icon

I am trying to create a bezier spline curve that goes through four points.But it looks like MGraphics only supports curves of three points.
curve_to(x1, y1, x2, y2, x3, y3);
How can I create a curve using MGraphics that will support more points?

Rob Ramirez's icon

an example patch might help, but have you tried jit.path, or jit.gl.path?

Joshua Kit Clayton's icon

I believe you just use a sequence of curve_to calls. You can also check out the cairographics.org examples/docs, since mgraphics' API maps closely to Cairo.

Anthony Palomba's icon

I am working on a javascript porting library that allows you to easily port processing sketches to jitter. I am currently using MGraphics as my drawing interface.

In processing you can create a curve in the following manner:

beginShape();
curveVertex(84,  91);
curveVertex(84,  91);
curveVertex(68,  19);
curveVertex(21,  17);
curveVertex(32, 100);
curveVertex(32, 100);
endShape();

Which should look something like this...

I am using the following code...

function draw()
{
mgfx.move_to(84,  91);
mgfx.curve_to(84,  91, 68,  19, 21,  17);
mgfx.curve_to(32, 100, 32, 100, 32, 100);
mgfx.set_source_rgba(1, 0, 0, 1);
mgfx.stroke();
}

Rather clumsy, but I know of no other way. What I get is...

I have attached an example patch. Any ideas?

Thanks,

Anthony

test.maxpat
Max Patch
test.txt
txt
Rob Ramirez's icon

it looks like processing uses catmull-rom splines for drawing curves, which draws the curve through each vertex.
this is also how jit.path draws curves.

Max Patch
Copy patch and select New From Clipboard in Max.

here is an example of using jit.path to draw curves with jit.mgraphics:

Anthony Palomba's icon

For some reason the images i posted do not show.
Also, I made mistake in my javascript. Here is the update source...
autowatch = 1;
var width = 500;
var height = 300;

// create a [jit.gl.render] object for drawing into our window:
var glrender = new JitterObject("jit.gl.render","render-ctx");
// use a 2-dimensional projection:
glrender.ortho = 2;
glrender.blend_enable = 1;
glrender.blend = "alphablend";
glrender.depth_enable = 0;
glrender.erase_color = [0,0,0,1]; // set background to black with full erase opacity (no trails):

var mgfx = new MGraphics(width,height);

// init drawing context
mgfx.init();
mgfx.relative_coords = 0;
mgfx.autofill = 0;

var outmatrix = new JitterMatrix(4, "char", width, height);

function bang()
{
drawProcessingScene();
}

function draw()
{
mgfx.move_to(84,  91);
mgfx.curve_to(84,  91, 68,  19, 21,  17);
mgfx.curve_to(32, 100, 32, 100, 32, 100);
mgfx.set_source_rgba(1, 0, 0, 1);
mgfx.stroke();
}

function drawProcessingScene()
{
var theImage = null;

draw();

mgfx.identity_matrix();
theImage = new Image(mgfx.pop_group());
mgfx.image_surface_draw(theImage);

theImage.tonamedmatrix(outmatrix.name);
outlet(0, "jit_matrix", outmatrix.name);

gc();

}

Anthony Palomba's icon

Hey Rob,

Thanks for the great example. But I am doing things in Javascript. Would I be able to create an instance of jit.path and then send its output to jit.mgraphics?

Rob Ramirez's icon

unfortunately jit.path doesn't function inside javascript.
i will make a feature request for this.
in the meantime, perhaps you can pass path messages to an external jit.path, and send the outputted matrix back into your javascript for iterating.

Joshua Kit Clayton's icon

FWIW, on quick google, here's a processing.js example of converting a catmull rom curve to a cubic bezier approximation. That's the route I'd probably take to build a processing curve() workalike. You can begin a curve/path and then when ending it convert all the points to bezier form and then issue the corresponding mgraphics curve_to() calls.

bokemono's icon

Since this thread is more than a year old, I'm sure Anthony has already found the answer to his original question, but since I'm working on bezier curves and trying to port from processing and other sources. I thought I'd update.

As I've discovered in the documentation, mgraphics' curve_to call does utilizes 4 points. I believe both Processing and mgraphics utilize cubic bezier formulas. The start point is the current point.Then curve_to call takes 2 control points and an end point. Here's the edited draw function:

function draw()
{
mgfx.move_to(84, 91);
mgfx.curve_to(68, 19, 21, 17, 32, 100);
mgfx.set_source_rgba(1, 0, 0, 1);
mgfx.stroke();
}

I'm now going to search for the porting library from Processing-Jitter!

Tosh

processing_bezier.js
js
bokemono's icon

uh oh! I just looked up the processing curve, and I'm wrong. though they utilize the same start and control points, the curve from mgraphics and from processing don't look the same!

Rob Ramirez's icon

as joshua mentioned above, you need to convert catmull-rom to cubic bezier.

bokemono's icon

Thank you Rob. I'm currently following Joshua's suggestions step by step.