Drawing a portion of an ellipse programmatically with a Bezier or an Elliptical path — SVG and raphael.js

StackOverflow https://stackoverflow.com/questions/16100048

Question

I'm trying to draw a bezier curve surrounding an ellipse with a given margin :

Bezier path surrounding an ellipse

I want to achieve this programmatically, so if I changes the ellipse size, the curve will follow it.

At the moment I've made this function :

function bezierPathTopRounded(ellipse, margin) {
    var box = ellipse.paper.getBBox();

    var leftX = box.x - margin; 

    var rightX = box.x + margin + box.width;

    var y = box.y + box.height/2 - margin; 

    var p = "M "+ leftX  + ", "+ y
    + " C " //could be relative too
    + ( box.x - margin + (box.width/15)  )  + ", " + ( box.y + margin - (box.height/4.5)  ) + " "
    + ( box.x + margin + box.width - (box.width/15)  )  + ", " + ( box.y + margin - (box.height/4.5) ) + " "
    + rightX +", " + y;

    return p;   
}

But I can't figure out how to calculate this direction points values so that it will work with any ellipse :

  • box.width/15
  • box.height/4.5

There is a fiddle with this example.

I've read this stackoverflow question and I tried the same on my example, but still can't figure out a simple solution, it remains random...

Edit

Now I'm trying with an elliptical Arc, the result is worser than with a Bezier Path :

Elliptical Arc test

There is the function I'm using. If I remove the margin it follows exactly my ellipse... Finally this is the matter is how may I follow the ellipse with a margin ?

function borderPath(ellipse, margin, flag) {
    var flag = flag == undefined ? 1 : 0;

    var box = ellipse.paper.getBBox();

    var leftX = box.x - margin;

    var rightX = box.x + margin + box.width;

    var y = box.y + box.height/2;
    y += (flag == 1) ? -margin : margin;

    var rx = box.width/2 + margin;
    var ry = box.height/2;

    var p = "M "+ leftX + ", "+ y
    + " A "
    + rx + " " + ry
    + " 0 0 "+ flag +" "
    + rightX +", " + y;

    return p;
}

See the updated fiddle here.

Really sorry for the awful colors, those are for example purpose.

Était-ce utile?

La solution 2

I've manage to make an elliptical arc according to the ellipse and its margin. Than i'm simply hiding the part I don't want with a rectangle.

Here is the function :

function borderPath(ellipse, flag) {
    var flag = flag == undefined ? 1 : flag;

    var box = ellipse.paper.getBBox();

    var leftX = box.x;

    var rightX = box.x + box.width;

    var y = box.y + box.height/2;

    var rx = box.width/2;
    var ry = box.height/2;

    var p = "M "+ leftX + ", "+ y
    + " A "
    + rx + " " + ry
    + " 0 0 "+ flag +" "
    + rightX +", " + y;

    return p;
}

Autres conseils

If you want to do this with Bezier curves, you'll have to decide how "wrong" you want it to look. Bezier curves cannot represent circular (and by extension, elliptical) curves, they can only get really close, in the same way a polygon can, just with higher precision using fewer sections.

I describe both circle-approximation and curve offsetting using Bezier curves in my primer on Bezier curves, http://pomax.github.io/bezierinfo/#circles_cubic and http://pomax.github.io/bezierinfo/#offsetting respectively, but if you're coding this from scratch particularly the offsetting will be overkill if you only need it for what you describe in your example.

Instead, I'd recommend firing up Inkscape or Illustrator, turning on the grid overlay, and drawing a bezier curve around your ellipse. Make it look good, then check what the coordinates are, and use that as reliable-enough information for implementing in your canvas program. You probably don't need mathematically rigidly correct, as long as people don't go "that looks wrong", you should be just fine.

Using bezier curves to draw elliptical path may cause you headaches. As you said in a comment, you are using path arc which works well with RaphaelJS.

Documentation about all the values it expects, especially the flags, can be found at http://www.svgbasics.com/arcs.html .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top