Drawing half of a Bezier path in Raphael - javascript

Let's say I have a cubic Bezier path as follows (formatted for use with the Raphael path function):
M55 246S55 247 55 248
Just an example. This was taken from my drawing application, where I use the cursor to draw a line when the user holds the mouse button down, kind of like a pencil or marker. I'm using jquery's mousemove event to draw the line between two points every time the user moves the mouse. There is another (the reference point) that is taken before the line is drawn, so that the Bezier curve can be created.
Here's my question: is it possible to make Raphael only draw half of a given path? I'm aware of the getSubpath() function, but if my understanding of Bezier curves is correct, it would be rather difficult to calculate the second argument. The problem with the animate function is that it creates double lines (that is, it creates the curved line that I want, and the boxy line around it which should not be shown, possibly because the mouse is being moved faster than the animation can handle).
Of course, if my approach itself is flawed in some way (or my understanding of the possible solutions), I'd like to hear it. Any help would be appreciated.

It is a bit messy, but maybe this will answer it:
line[line.length] = paper.path(drawPath); //drawPath being the fill line length
//get a subpath, being half the length of your bezier curve
subPath = line[line.length - 1].getSubpath(0, line[line.length - 1].getTotalLength()/2);
//remove the full-length bezier curve
line[line.length - 1].remove();
//Draw your new line
line[line.length - 1] = paper.path(subpath);
Honestly, this this is quite inefficient. But, I can't think of a better way to go about it. You can't just grab the tangent and divide by half, since a bezier curve will be longer the length of a tangent line (as a crow flies). This means that you must process the line via rapheal and then get a subPath of half the length.

The middle point can be calculated, not aware of any functionality in Raphael that will cut the bezier in half for you.
From the looks of those commands, it's standard SVG markup (see the SVG spec to understand it better: http://www.w3.org/TR/SVG/paths.html#PathDataCubicBezierCommands)
M=> MoveTo the absolute position 55,24
S=> Smooth Curve to the absolute 55,247 55,248
Smooth curve can be rewritten as a standard CurveTo or C if you want, S is only the shorthand for it and the curveto / C you can easily calculate the center point.

Splitting a bezier curve in half is just a bit of math, nothing too hard. You might be helped by the path extensions for raphaël, and it should be pretty simple to add a method there to do the splitting.
The "just a bit of math" part could e.g use De Castelau's algorithm for splitting the curve at any given point.

Related

How to draw splitting polygon continuously with Konva?

split polygon by lineArea
I want to drag LineArea to split polygon continuously with Konva.
If lineArea is a Konva.Shape. I can use following procedure to split polygon:
let prePt
lineArea.on("dragstart",function(){
prePt = this.getAbsolutePosition();
});
lineArea.on("dragmove",function(){
let curPt = this.getAbsolutePosition();
move split line denoted by lineArea;
split polygon by line
});
but how can I change lineArea's shape in dragmove event? or any improved solution is appreciated;
If I am getting this right, you want to create a kind of »sweep line« effect, such that the »lineArea« will be the intersection of the polygon and a rotated rectangle.
However, a general solution would be exactly that: The intersection of two polygons, since the rectangle/lineArea can be treated as a polygon as well. Have a look that this question, since it lists libraries that support boolean operations, whereby an intersection is one of them is paperjs.
How to compute such an Intersection is far beyond the scope of such an answer here and since this has been done already, i would recommend you to use an existing library.

How to create 2D physics blob similar to the "Sushi Cat Game" using javascript physics engine?

I am trying to create HTML5 game that similar to Sushi Cat game. I followed a similar tutorial from Emanuele Feronato's blog post and then came up with the structure like the picture A in this image, where the gray orbits are allowed to penetrate each other, and the red lines are distantConstraint.
But the problem is when the blob fell from a high place (or hitting corner), it becomes like in picture B.
I tried to use spring, different constraint force, smaller orbits, but they are not working properly.
My questions:
What is the solution for this? Or where can I find the solution on the web?
Is there any other js physics engine that has a specific feature to do this task?
Remove the symmetry
Just add some additional constraints to the points. The current symmetry of the shape means that round and folded in half are both valid and relaxed configurations.
Radial constraints.
Using one of the lines from the center to the outside as a referance, give each spoke an offset angle from that line.
Then each outside point will be moved as follows.
Get angle of ref line.
var ang = Math.atan2(refLine.p2.y - refLine.p1.y, refLine.p2.x - refLine.p1.x);
Then for each line move the end point towards its desired relative angle position.
// line is a spoke line with a property angle that is the angle from the
// reference line
var x = refLine.p1.x; // get center point
var y = refLine.p2.y;
// get position relative to ref ang
line.x = Math.cos(line.angle + ang) * line.length + x;
line.y = Math.sin(line.angle + ang) * line.length + y;
Do that for each spoked line and apply it after you apply the line length constraints.
In referance to the image you gave the line from center to 12 o'clock is the reference line then the other spoked lines will have angles restrained as follows.
1 o'clock is 30deg from ref
2 o'clock is 60
3 is 90 so on to 6 at 180deg
And the other direction
11 o'clock is -30deg from ref
10 o'clock is -60 and so on
You will be able to ignore the 6 o'clock line incase giving it a constraint makes the object want to roll to the right.
Only one
This now means that there is only one solution to the possible states rather than the many that you had.
The reason why the blob folds into itself, is because gravity will squish the blob points and the distance joints will find a new valid configuration. The job of the distance joint is just to maintain a given distance between two points, and it doesn't really do anything to prevent the self-folding.
An alternative approach is using Prismatic Joints (also called "slider joints"). With prismatic joints, the outer blob circles would slide along an axis radially from the center of the blob. To make the blob springy, you could add some kind of springs between the blob center and the circles. If the blob still self-folds, you could add limits to the prismatic joints, so the circles can only slide a certain distance.
This video demonstrates prismatic joints in a similar fashion, using the RUBE physics editor (using box2d under the hood).
A similar scene was made using p2.js physics engine, read more here. (direct link to demo). The part of the code that constructs the Prismatic Joints in the p2.js demo is:
// Constrain the capsule body to the center body.
// A prismatic constraint lets it move radially from the center body along one axis
var prismatic = new p2.PrismaticConstraint(wheelBody, body, {
localAnchorA : [0, 0],
localAnchorB : [0, 0],
localAxisA : [Math.cos(angle), Math.sin(angle)],
disableRotationalLock: true, // Let the capsule rotate around its own axis
collideConnected: true
});
In JavaScript, there are several ports of Box2D available which have the Prismatic Joint. p2.js has PrismaticConstraint.
Constant Volume Joint may be what you are looking for. As its name suggests, it tries to maintain the volume it has upon creation despite impulses from outside, much like a water balloon.
Here is a demo.
A working example with Box2dweb can be found here.
If you are interested in creating blobs with the creative application of more standard joints, this article comes to my mind.

Canvas: curve failing to start from end point of previous curve

I'm using the algorithm posted by the author of the question in the below thread to draw an N point bezier curve defined by some array of points.
how to draw smooth curve through N points using javascript HTML5 canvas?
Here's a fiddle of the project:
http://jsfiddle.net/lee2808/2YVx4/
If you copy and paste that into a js file and replace "AddImage.png" in the Curve's Ctor call on line 15 with an image file, all should work fine! You need to click on the canvas three times for the curve to begin to draw.
I'm dynamically adding points on a mousedown + mouseup event.
Anyway my implementation half works (if that's a thing lol). Once I have placed the first 3 points on the canvas a bezier is drawn as expected. However when I add further points the start point for the next curve is not at the end point of the previous curve.
It seems it's starting from the previous point.
Anyway here's my implementation :
Curve.prototype.drawCurve = function(pContext){
pContext.save();
if(this.getPoints().length >2){
pContext.moveTo(this.getPoints()[0].getX(),this.getPoints()[0].getY());
var i = 1;
for(i; i < this.getPoints().length-2; i++){
var modX = (this.getPoints()[i].getX() + this.getPoints()[i+1].getX()) /2;
var modY = (this.getPoints()[i].getY() + this.getPoints()[i+1].getY()) /2;
pContext.quadraticCurveTo(this.getPoints()[i].getX(), this.getPoints()[i].getY(),modX,modY);
}
if(this.getPoints().length > 2){
pContext.quadraticCurveTo(this.getPoints()[i].getX(),this.getPoints()[i].getY(), //last control point
this.getPoints()[i+1].getX(),this.getPoints()[i+1].getY());//end point
}
pContext.stroke();
}
pContext.restore();
};
Pretty much identical. Can anyone see the flaw in my logic?
I'm trying to produce a chain of bezier curves so that I can then animate an object to follow that path incase anyones interested as to why I want to do this.
Thanks in advance!

Determine if a 2D point is within a quadrilateral

I'm working on a JS program which I need to have determine if points are within four corners in a coordinate system.
Could somebody point me in the direction of an answer?
I'm looking at what I think is called a convex quadrilateral. That is, four pretty randomly chosen corner positions with all angles smaller than 180°.
Thanks.
There are two relatively simple approaches. The first approach is to draw a ray from the point to "infinity" (actually, to any point outside the polygon) and count how many sides of the polygon the ray intersects. The point is inside the polygon if and only if the count is odd.
The second approach is to go around the polygon in order and for every pair of vertices vi and vi+1 (wrapping around to the first vertex if necessary), compute the quantity (x - xi) * (yi+1 - yi) - (xi+1 - xi) * (y - yi). If these quantities all have the same sign, the point is inside the polygon. (These quantities are the Z component of the cross product of the vectors (vi+1 - vi) and (p - vi). The condition that they all have the same sign is the same as the condition that p is on the same side (left or right) of every edge.)
Both approaches need to deal with the case that the point is exactly on an edge or on a vertex. You first need to decide whether you want to count such points as being inside the polygon or not. Then you need to adjust the tests accordingly. Be aware that slight numerical rounding errors can give a false answer either way. It's just something you'll have to live with.
Since you have a convex quadrilateral, there's another approach. Pick any three vertices and compute the barycentric coordinates of the point and of the fourth vertex with respect to the triangle formed by the three chosen vertices. If the barycentric coordinates of the point are all positive and all less than the barycentric coordinates of the fourth vertex, then the point is inside the quadrilateral.
P.S. Just found a nice page here that lists quite a number of strategies. Some of them are very interesting.
You need to use winding, or the ray trace method.
With winding, you can determine whether any point is inside any shape built with line segments.
Basically, you take the cross product of each line segment with the point, then add up all the results. That's the way I did it to decide if a star was in a constellation, given a set of constellation lines. I can see that there are other ways..
http://en.wikipedia.org/wiki/Point_in_polygon
There must be some code for this in a few places.
It is MUCH easier to see if a point lies within a triangle.
Any quadrilateral can be divided into two triangles.
If the point is in any of the two triangles that comprise the quadrilateral, then the point is inside the quadrilateral.

Javascript physics engine and simulated infinite curve

I'm trying to do a Tiny Wings like in javascript.
I first saw a technique using Box2D, I'm using the closure-web version (because of the memory leaks fix).
In short, I explode the curve into polygons so it looks like that:
I also tried with Chipmunk-js and I use the segment shape to simulate my ground like that:
In both cases, I'm experiencing some "crashes" or "bumps" at the common points between polygons or segments when a circle is rolling.
I asked about it for Chipmunk and the author said he implemented a radius property for the segment to reduce this behavior. I tried and it indeed did the trick but it's not perfect. I still have some bumps(I had to set to 30px of radius to get a positive effect).
The "bumps" append at the shared points between two polygons :
Using, as illandril suggested to me, the edging technique (he only tested with polygon-polygon contact) to avoid the circle to crash on an edge:
Also tried to add the bullet option as Luc suggested and nothing seems to change.
Here the demo of the issue.
You can try to change the value to check :
bullet option
edge size
iterations count
the physics
(only tested on latest dev Chrome)
Be patient (or change the horizontal gravity) and you'll see what I mean.
Here the repo for the interested.
The best solution is edge shapes with ghost vertices, but if that's not available in the version/port you're using, the next best thing is like the diagram in your question called 'edging', but extend the polygons further underground with a very shallow slope, like in this thread: http://www.box2d.org/forum/viewtopic.php?f=8&t=7917
I first thought the problem could come from the change of slope between two adjacent segments, but since on a flat surface of polygons you still have bumps I think the problem is rather hitting the corner of a polygon.
I don't know if you can set two sets of polygons, overlapping each other ? Just use the same interpolation calculations and generate a second set of polygons just like in the diagram hereafter : you have the red set of polygons built and add the green set by setting the left vertices of a green polygon in the middle of a red polygon, and its right vertices in the middle of the next red polygon.
![diagram][1]
This should work on concave curves and... well you should be flying over the convex ones anyway.
If this doesn't work try setting a big number of polygons to build the slope. Use a tenth of the circle's radius for the polygon's width, maybe even less. That should reduce your slope discontinuities.
-- Edit
In Box2D.js line 5082 (in this repo at least) you have the PreSolve(contact, manifold) function that you can override to check if the manifolds (directions in which the snowball are impulsed when colliding the polygons) are correct.
To do so, you would need to recover the manifold vector and compare it to the normal of the curve. It should look like that (maybe not exactly) :
Box2D.Dynamics.b2ContactListener.prototype.PreSolve = function (contact, oldManifold) {
// contact instanceof Box2D.Dynamics.Contacts.b2Contact == true
var localManifold, worldManifold, xA, xB, man_vect, curve_vect, normal_vect, angle;
localManifold = contact.GetManifold();
if(localManifold.m_pointCount == 0)
return; // or raise an exception
worldManifold = new Box2D.Collision.b2WorldManifold();
contact.GetWorldManifold( worldManifold );
// deduce the impulse direction from the manifold points
man_vect = worldManifold.m_normal.Copy();
// we need two points close to & surrounding the collision to compute the normal vector
// not sure this is the right order of magnitude
xA = worldManifold.m_points[0].x - 0.1;
xB = worldManifold.m_points[0].x + 0.1;
man_vect.Normalize();
// now we have the abscissas let's get the ordinate of these points on the curve
// the subtraction of these two points will give us a vector parallel to the curve
var SmoothConfig;
SmoothConfig = {
params: {
method: 'cubic',
clip: 'mirror',
cubicTension: 0,
deepValidation: false
},
options: {
averageLineLength: .5
}
}
// get the points, smooth and smooth config stuff here
smooth = Smooth(global_points,SmoothConfig);
curve_vect = new Box2D.Common.Math.b2Vec2(xB, smooth(xB)[1]);
curve_vect.Subtract(new Box2D.Common.Math.b2Vec2(xA, smooth(xA)[1]));
// now turn it to have a normal vector, turned upwards
normal_vect = new Box2D.Common.Math.b2Vec2(-curve_vect.y, curve_vect.x);
if(normal_vect.y > 0)
normal_vect.NegativeSelf();
normal_vect.Normalize();
worldManifold.m_normal = normal_vect.Copy();
// and finally compute the angle between the two vectors
angle = Box2D.Common.Math.b2Math.Dot(man_vect, normal_vect);
$('#angle').text("" + Math.round(Math.acos(angle)*36000/Math.PI)/100 + "°");
// here try to raise an exception if the angle is too big (maybe after a few ms)
// with different thresholds on the angle value to see if the bumps correspond
// to a manifold that's not normal enough to your curve
};
I'd say the problem has been tackled in Box2D 2.2.0 , see its manual, section 4.5 "Edge Shapes"
The thing is it's a feature of the 2.2.0 version, along with the chainshape thing, and the box2dweb is actually ported from 2.2.1a - don't know about box2dweb-closure.
Anything I've tried by modifying Box2D.Collision.b2Collision.CollidePolygonAndCircle has resulted in erratic behaviour. At least a part of the time (e.g. ball bumping in random directions, but only when it rolls slowly).

Categories

Resources