How to create a random ground in matter.js - javascript

I am creating the ground of a game using a Perlin noise function. This gives me an array of vertices. I then add a vertex at the front that is {x:0 y: WORLD_HEIGHT} and another at the end of the array that is {x: WORLD_WIDTH y: WORLD_HEIGHT}. I am hoping that will give me a flat base with a random top.
How then do I add this into the matter.js world?
I am trying to create the ground using;
var terrain = Bodies.fromVertices(???, ???, vertexSets, {
isStatic: true
}, true);
but I don't know what to use for the ??? co-ordinates. I think they are supposed to represent the center of the object. However, I don't know what that is because it is noise. What I would like to do is specify the x & y of the first perlin noise vertex.
I am not even sure that given these vertices matter.js is creating a single body or multiple.
Is this the right way to approach it or there another way to do this? I am really struggling with the docs and the examples.

I use Matter.Body.setPosition(body, position) to override the center of mass and put the ground where I want it based on its bounds property.
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine: engine,
});
const w = 300;
const h = 300;
const vertices = [
...[...Array(16)].map((_, i) => ({
x: i * 20,
y: ~~(Math.random() * 40),
})),
{x: w, y: 100},
{x: 0, y: 100},
];
const ground = Matter.Bodies.fromVertices(
w - 10, h - 10, // offset by 10 pixels for illustration
vertices,
{isStatic: true},
/* flagInternal =*/ true,
);
Matter.Body.setPosition(ground, {
x: w - ground.bounds.min.x,
y: h - ground.bounds.max.y + 110,
});
const {min: {x}, max: {y}} = ground.bounds;
console.log(x, y); // 10 120
Matter.Composite.add(engine.world, [ground]);
Matter.Render.run(render);
Matter.Runner.run(engine);
<script src="https://cdn.jsdelivr.net/npm/poly-decomp#0.3.0/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
Without setPosition, you can see things jump around if you run this snippet a few times (just to reproduce OP's error with a concrete example):
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine: engine,
});
const vertices = [
...[...Array(16)].map((_, i) => ({
x: i * 20,
y: ~~(Math.random() * 40),
})),
{x: 300, y: 100},
{x: 0, y: 100},
];
const ground = Matter.Bodies.fromVertices(
200, 100, vertices,
{isStatic: true},
/* flagInternal =*/ true,
);
Matter.Composite.add(engine.world, [ground]);
Matter.Render.run(render);
Matter.Runner.run(engine);
<script src="https://cdn.jsdelivr.net/npm/poly-decomp#0.3.0/build/decomp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.18.0/matter.min.js"></script>
I'm not using Perlin noise and there are some internal vertices that aren't properly detected in the above examples, but the result should be the same either way.

should be integers, all width and height of the noise texture. values at those x, y integer places can be floats... no problem.
and same width and height should go to terrain and values at that places will be the height of the terrain.

Related

Auto-adjustable line between canvas objects

My intention is to create a line with canvas that adjusts itself whenever the objects change position, so that it always has a correct shape.
I currently have the following (uses a quadratic curve to make the turn):
I have found a GoJS library that does exactly what I want, which is the following:
The problem is that the library is not open source, so I wanted to know if this is some kind of generic algorithm to do it, or I have to do the calculation manually to identify the positions of the objects and calculate the best trajectory.
As extra information, I am making use of KonvaJS which natively does not implement anything like this.
It depends on how much complexity you need. This is a fiddle that does the basic pathfinding you have in the animation (without rounding the corners).
It figures out what side the paths should start from, and turns that into the offset for the path start and end, by comparing the x and y distances of the two objects:
let startsVertical = Math.abs(dx) < Math.abs(dy);
if (startsVertical) {
anchorPointOffset = {x: 0, y: Math.sign(dy) * circleRadius};
} else {
anchorPointOffset = {x: Math.sign(dx) * circleRadius, y: 0};
}
let stationaryAnchorPoint = {
x: stationaryPosition.x + anchorPointOffset.x,
y: stationaryPosition.y + anchorPointOffset.y
};
let movingAnchorPoint = {
x: movingPosition.x - anchorPointOffset.x,
y: movingPosition.y - anchorPointOffset.y
};
If your shapes do not have the same width and height, you will need to use two variables, instead of circleRadius.
Then it calculates the center point and uses that to create the middle two points of the path.
if (startsVertical) {
middleA = {
x: stationaryAnchorPoint.x,
y: centerPoint.y
}
middleB = {
x: movingAnchorPoint.x,
y: centerPoint.y
}
} else {
middleA = {
x: centerPoint.x,
y: stationaryAnchorPoint.y
}
middleB = {
x: centerPoint.x,
y: movingAnchorPoint.y
}
}
Rounding the corners is a little more complicated, but there are many guides for that.

Lens equivalent of evolve or lens to multiple values

It's my understanding is lenses are functions that contain the means to get and set values.
I have this helper function:
const overEach = uncurryN(3,
fn => lenses =>
lenses.length > 0 ?
compose(...map(flip(over)(fn), lenses)) :
identity
);
in use
const annual = ["yearsPlayed", "age"];
const annualInc = overEach(
inc,
map(lensProp, annual),
);
console.log(
annualInc({
jersey: 148,
age: 10,
yearsPlayed: 2,
id: 3.14159
})
);
The output:
{
jersey: 41,
age: 11,
yearsPlayed: 3,
id: 3.14159
}
This is interesting because (like evolve), I can define how something of a certain shape is meant to change. This is better than evolve because it gives me a clean separation of concern about the shape of my data and what I'm doing to it. This is worse than evolve because it creates an intermediate value that I never use. The more lenses I have, the more intermediate values I create.
{
jersey: 148,
age: 10,
yearsPlayed: 3,
id: 3.14159
}
I'd be curious to know if there's a way to define a lens that points to more than one value. compose(lenseIndices([1,7,9]), lensProp('parents'), lensIndex(0)) Might point to the first parent of three different people.
It seems to me this really should be possible, but I don't know what to search and I'd rather not re-invent the wheel (Especially as I haven't been in the weeds with lenses yet), if it can and also has been done.
I'd be curious to know if there's a way to define a lens that points to more than one value.
The intuition we should have for a "lens" is that it "focuses" on a particular part of a data structure. So really, no. A lens is all about working with something specific. (But see the update below that demonstrates that this something specific does not have to be a single property.)
Ramda's issue #2457 discusses the uses of lenses in greater detail.
I don't think I agree with your interpretation of additional flexibilities your function provides compared to evolve. In fact, if I were to implement it, I would probably do so atop evolve, with something like this:
const {evolve, fromPairs, inc} = R
const overEach = (fn, names) =>
evolve (fromPairs (names .map (name => [name, fn])))
const annualInc = overEach (inc, ["yearsPlayed", "age"])
console .log (annualInc ({
jersey: 148,
age: 10,
yearsPlayed: 2,
id: 3.14159
}))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js"></script>
And evolve lets you easily choose different functions for different properties, allows you to nest transformations, and is extremely declarative.
overEach simply allows us to apply the same transformation function to many different nodes. This is useful, of course, but seems likely less common than the normal cases of evolve.
Update
I want to clarify something I said above. While lenses focus on a particular part of a data structure, that does not mean that they can only affect one field or property of an object. We need to think of this more holistically. That part can be multiple fields, possibly with subfields. I think this is easiest to describe through an example.
Let's imagine you have your polished box function used to describe a box on the cartesian grid. It has read-only position, width, and height properties, and methods to move it, scale it, list the corners, find the areas And all of these are properly functional, returning new boxes rather than mutating the original. You're pretty happy with this code:
const box = (l, t, w, h) => ({
move: (dx, dy) => box (l += dx, t += dy, w, h),
scale: (dw, dh) => box (l, t, w *= dw, h *= dh),
area: () => w * h,
get position () { return {x: l, y: t} },
get width () { return w},
get height () { return h },
corners: () => [{x: l, y: t}, {x: l + w, y: t}, {x: l + w, y: t + h}, {x: l, y: t + h}],
toString: () => `Box (left: ${l}, top: ${t}, height: ${h}, width: ${w})`
})
But now you want to apply your tools to a new situation, where you have widgets that look like this:
const widget = {
topLeft: {x: 126, y: 202},
bottomRight: {x: 776, y: 682},
borderColor: 'red',
borderWidth: 3,
backgroundUrl: 'http://example.com/img.png',
// ...
}
While the topRight and bottomLeft points are a compatible way of describing the rectangle, you would have to rewrite a pile of code that already handle boxes to deal with these new widgets. Moreover, boxes seem the logical view of the situation. Heights and widths seem much more relevant than the bottom-right corners. Here we can use lenses to deal with the concerns. That is, we can think entirely in boxes, extracting a box from the widget, adjusting the values by adjusting the box. We just need to write a lens to do it:
const boxLens = lens (
({topLeft: {x: x1, y: y1}, bottomRight: {x: x2, y: y2}}) =>
box (x1, y1, x2 - x1, y2 - y1),
({position: {x, y}, width, height}, widget) => ({
...widget,
topLeft: {x, y},
bottomRight: {x: x + width, y: y + height}
})
)
Now we can deal with the position and extent of our widget as though it were described by a box:
view (boxLens, widget) .toString ()
//=> "Box (left: 126, top: 202, height: 480, width: 650)"
view (boxLens, widget) .corners ()
//=> [{x: 126, y: 202}, {x: 776, y: 202}, {x: 776, y: 682}, {x: 126, y: 682}]
set (boxLens, box (200, 150, 1600, 900), widget)
//=> {topLeft: {x: 200, y: 150}, bottomRight: {x: 1800, y: 1050}, borderColor: "red", ...}
over (boxLens, box => box .scale (.5, .5), widget)
//=> {topLeft: {x: 126, y: 202}, bottomRight: {x: 451, y: 442}, borderColor: "red", ...}
const moveWidget = (dx, dy) =>
over(boxLens, box => box .move (dx, dy))
moveWidget (10, 50) (widget)
//=> {topLeft: {x: 136, y: 252}, bottomRight: {x: 786, y: 732}, borderColor: "red", ...}
You can confirm this in the following snippet:
const {lens, view, set, over} = R
const box = (l, t, w, h) => ({
move: (dx, dy) => box (l += dx, t += dy, w, h),
scale: (dw, dh) => box (l, t, w *= dw, h *= dh),
area: () => w * h,
get position () { return {x: l, y: t} },
get width () { return w},
get height () { return h },
corners: () => [{x: l, y: t}, {x: l + w, y: t}, {x: l + w, y: t + h}, {x: l, y: t + h}],
toString: () => `Box (left: ${l}, top: ${t}, height: ${h}, width: ${w})`
})
const boxLens = lens(
({topLeft: {x: x1, y: y1}, bottomRight: {x: x2, y: y2}}) => box (x1, y1, x2 - x1, y2 - y1),
({position: {x, y}, width, height}, widget) => ({
...widget,
topLeft: {x, y},
bottomRight: {x: x + width, y: y + height}
})
)
const widget = {
topLeft: {x: 126, y: 202},
bottomRight: {x: 776, y: 682},
borderColor: 'red',
borderWidth: 3,
backgroundUrl: 'http://example.com/img.png',
// ...
}
console .log (
view (boxLens, widget) .toString ()
)
console .log (
view (boxLens, widget) .corners ()
)
console .log (
set (boxLens, box (200, 150, 1600, 900), widget)
)
console .log (
over (boxLens, box => box .scale (.5, .5), widget)
)
const moveWidget = (dx, dy) =>
over(boxLens, box => box .move (dx, dy))
console .log (
moveWidget (10, 50) (widget)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
The Point
This shows that we can use lenses to deal with more than one field at a time, as Mrk Sef's self-answer also explains. But we have to deal with them in some way isomorphic to the original. This is actually a very powerful use of lenses. But this does not imply that we can simply use them to work on arbitrary properties.
What I've Learned So Far
This is probably not a geat idea. The problem is that lenses need to have certain properties to work. One of those properties is this:
view(lens, set(lens, a, store)) ≡ a — If you set a value into the store, and immediately view the value through the lens, you get the value that was set.
If you want a lens to point at multiple values without further restrictions, then that information must be encoded (somehow) in the data structure being altered. If a key is set to an array, that array encodes it's own size. But if setting an array actually corresponds to setting something else, then some subset of that something else must be isomorphic to arrays (grow, shrink, re-order, the whole shebang). So that you can always convert back and forth.
If you're happy with further restrictions you can do a bit more, but the results are lackluster.
Here's a fully functioning (as far as I can see) lens implemention that points to multple properties but restricts the properties you're allowed to set.
const subsetOf = pipe(without, length, equals(0));
const subset = flip(subsetOf);
const lensProps = propNames => lens(
pick(propNames),
(update, data) =>
subset(keys(update), propNames) ?
({ ...data, ...update }) :
call(() => {throw new Error("OH NO! LENS LAW BROKEN!");})
);
In use:
const annualLens = lensProps(["yearsPlayed", "age"]);
const timmy = {
jersey: 148,
age: 10,
yearsPlayed: 2,
id: 3.14159
};
console.log(
"View Timmy's Annual Props: ",
view(annualLens, timmy)
);
console.log(
"Set Timmy's Annual Props: ",
set(annualLens, {yearsPlayed: 100, age: 108}, timmy)
);
console.log(
"Update Timmy's Annual Props: ",
over(annualLens, map(inc), timmy)
);
// Break the LAW
set(annualLens, {newKey: "HelloWorld"}, timmy);
The output:
View Timmy's Annual Props: { age: 10, yearsPlayed: 2 }
Set Timmy's Annual Props: { jersey: 148, age: 108, yearsPlayed: 100, id: 3.14159 }
Update Timmy's Annual Props: { jersey: 148, age: 11, yearsPlayed: 3, id: 3.14159 }
Error: OH NO! LENS LAW BROKEN!
You could imagine writting a version of this that takes pathes instead of names, but that doesn't actually help since then in order to use set, you'd need to know the paths that the lens is expecting to set.
It gets worse though. You can compose these sorts of lenses, but there really isn't any point to it:
compose(lensIndex(0), lensProps(["a","b"]), lensProp("b"))
is the same as
compose(lensIndex(0), lensProp("b"))
So while it doesn't break anything, it quickly becomes profoundly uninteresting. Its only use, really, is as the 'outermost' lens in a composition. Even then it likely must be constrained to be useful.
As an upside, as the outmost lens, it can actually change multiple values without intermediate objects. This isn't great though, as you can use evolve as a function you pass to over and you bake in extra functionality without really losing anything.

Is there a way to create a HTML element using an array of coordinates?

Say I have an array of 4 x/y co-ordinates
[{x: 10, y: 5}, {x:10, y:15}, {x:20, y:10}, {x:20, y:20}]
Is there a way to construct a HTML element, so that each of the four corners math the co-ordinates in the array?
I know this is possible using canvas, but I'm stuggling to work out how to go about doing this with HTML elements.
The array will always contain 4 sets of coordinates.
The final shape may be rotated or skewed, but will always be a "valid" shape which can be acheived using CSS transformations.
Assuming you got it in form of [topLeft, bottomLeft, topRight, BottomRight] of the original rectangle, you can try recreate it like this:
const obj1 = [{x: 10, y: 5}, {x:10, y:15}, {x:20, y:10}, {x:20, y:20}];
const obj2 = [{x: 40, y: 80}, {x: 10, y: 160}, {x: 120, y: 80}, {x: 90, y: 160}];
const obj3 = [{x: 200, y: 30}, {x: 150, y: 80}, {x: 250, y: 80}, {x: 200, y: 130}];
function render(obj) {
const skewX = obj[1].x - obj[0].x;
const skewY = obj[2].y - obj[0].y;
let translateX = Math.min(...obj.map(t => t.x));
let translateY = Math.min(...obj.map(t => t.y));
if(skewX<0) translateX -= skewX;
if(skewY<0) translateY -= skewY;
const scaleX = Math.abs(obj[0].x - obj[2].x);
const scaleY = Math.abs(obj[0].y - obj[1].y);
const el = document.createElement('div');
el.style.width = '1px';
el.style.height = '1px';
el.style.backgroundColor = 'blue';
el.style.transformOrigin = 'top left';
el.style.transform = `matrix(${scaleX}, ${skewY}, ${skewX}, ${scaleY}, ${translateX}, ${translateY})`;
document.body.appendChild(el);
}
render(obj1);
render(obj2);
render(obj3);
However, I will recommend you to not store the shapes as its vertices but as it's transformation matrix. (if it's possible, of course)
If you're simply trying to draw shapes without the use of canvas, you could maybe draw SVG shapes by translating the coordinates in your object.
If you want to deform a div, best I can think off top of my head is to make use of CSS transform:matrix, but you'd need to figure out how to translate your x/y for each corner coordinates to scale/skew/translate parameters.
If you're not deforming a div, and simply creating a regular rectangular one, then you should be able to translate your x/y coordinates into top; left; width; height; CSS properties.
Well, no. HTML is a tree-like structured DOM. Although, you can have a DOM with position: absolute (absolute to html) and top: y; left: x, but it does not have any advantage doing it this way, from my perspective.

How to add gravity to multiple bodies 'automatically'?

I know how to add gravity to any given object/element. Just add acceleration Y downwards. But "what if want my hero to fly?" or "what if I want to turn gravity off for one particular object? I'll have to set gravity = 0 which will turn off for everyone obviously. I also thought giving every shape their own 'gravity' variable, but I figured that would be too much and it's probably not how it's done...
How would I go from creating shapes
(Using EaseJS)
function spawnShape(x, y, w, h) {
var shape = new createjs.Shape();
shape.graphics.beginFill("black").drawRect(x, y, w, h);
stage.addChild(shape);
}
spawnShape(20, 250, 600, 30);
spawnShape(200, 150, 5, 5);
stage.update();
to adding gravity "automatically"? (every shape inheriting downwards acceleration) I know there's 2D physics engines made but I want to do/understand this myself, and I did try to use PhysicsJS but failed to do so.. I'll probably be using an engine but for now I want to know how to do this :P
You can create an object:
function Shape(x, y, w, h, gravity){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.gravity = gravity;
this.shape = new createjs.Shape();
stage.addChild(shape);
this.draw = function(){
shape.graphics.beginFill("black").drawRect(x, y, w, h);
}
}
Thus, you can call it as:
> x = new Shape(200, 200, 10, 10, 0.5)
Shape {x: 200, y: 200, w: 10, h: 10, gravity: 0.5}
> y = new Shape(400, 100, 50, 100, 0.75)
Shape {x: 400, y: 100, w: 50, h: 100, gravity: 0.75}
> x.gravity = 0
0
> y.gravity
0.75
I haven't worked with EaseJS so the specifics may be inaccurate but the overarching logic will be as demonstrated above.
I think you understand how to add gravity or not add gravity to an object. As you say, it is just adding acceleration Y to the object.
It sounds like you just need to think out your design a little. Let's say you have a module 'gravity.js' that is responsible for applying gravity to an object.
/* gravity.js */
const DEFAULT_GRAVITY_ACCELERATION = 1.0;
function applyGravity(shape) {
const gravity = shape.gravityAcceleration !== undefined ?
shape.gravityAcceleration : DEFAULT_GRAVITY_ACCELERATION;
//Do whatever you normally do to update Y acceleration. Code below
//is just an example.
shape.addYAcceleration(gravity);
}
If you create a shape someplace and want it to be free of gravity, just set the .gravityAcceleration member of that object. BTW, there is nothing special about that "gravityAcceleration" name--it could be whatever you want.
//Assuming spawnShape returns an object.
var superman = spawnShape(20, 250, 600, 30);
superman.gravityAcceleration = 0; //Override the default gravity.
You only need to set the .gravityAcceleration member for shape objects that will defy gravity.

Convert an SVG-path to polygons for use within Javascript Clipper

I'm trying to perform Boolean Operations on SVG Paths (that contain beziers, both quadratic and cubic) using JS Clipper.
JS Clipper starts with polygons then performs the operation and then it seems to convert them back to SVG paths.
The function below gives an SVG path but the below example starts with 2 polygons.
An example function:
// Polygon Arrays are expanded for better readability
function clip() {
var subj_polygons = [
[{
X: 10,
Y: 10
}, {
X: 110,
Y: 10
}, {
X: 110,
Y: 110
}, {
X: 10,
Y: 110
}],
[{
X: 20,
Y: 20
}, {
X: 20,
Y: 100
}, {
X: 100,
Y: 100
}, {
X: 100,
Y: 20
}]
];
var clip_polygons = [
[{
X: 50,
Y: 50
}, {
X: 150,
Y: 50
}, {
X: 150,
Y: 150
}, {
X: 50,
Y: 150
}],
[{
X: 60,
Y: 60
}, {
X: 60,
Y: 140
}, {
X: 140,
Y: 140
}, {
X: 140,
Y: 60
}]
];
var scale = 100;
subj_polygons = scaleup(subj_polygons, scale);
clip_polygons = scaleup(clip_polygons, scale);
var cpr = new ClipperLib.Clipper();
cpr.AddPolygons(subj_polygons, ClipperLib.PolyType.ptSubject);
cpr.AddPolygons(clip_polygons, ClipperLib.PolyType.ptClip);
var subject_fillType = ClipperLib.PolyFillType.pftNonZero;
var clip_fillType = ClipperLib.PolyFillType.pftNonZero;
var clipTypes = [ClipperLib.ClipType.ctUnion];
var clipTypesTexts = "Union";
var solution_polygons, svg, cont = document.getElementById('svgcontainer');
var i;
for (i = 0; i < clipTypes.length; i++) {
solution_polygons = new ClipperLib.Polygons();
cpr.Execute(clipTypes[i], solution_polygons, subject_fillType, clip_fillType);
console.log(polys2path(solution_polygons, scale));
}
}
// helper function to scale up polygon coordinates
function scaleup(poly, scale) {
var i, j;
if (!scale) scale = 1;
for (i = 0; i < poly.length; i++) {
for (j = 0; j < poly[i].length; j++) {
poly[i][j].X *= scale;
poly[i][j].Y *= scale;
}
}
return poly;
}
// converts polygons to SVG path string
function polys2path(poly, scale) {
var path = "",
i, j;
if (!scale) scale = 1;
for (i = 0; i < poly.length; i++) {
for (j = 0; j < poly[i].length; j++) {
if (!j) path += "M";
else path += "L";
path += (poly[i][j].X / scale) + ", " + (poly[i][j].Y / scale);
}
path += "Z";
}
return path;
}
I assume that you mean some sort of svg path to polygon conversion.
I have searched a lot, but not found anything reliable and out-of-the-box solution.
SVG path can consist of ten different segment, or 20 if we take into account both relative and absolute coordinates. They are represented as letters in path element's d-attribute: relative ones are mhvlcqastz and absolute ones are MHVLCQASTZ. Each have different attributes, a (elliptical arc) being the most complicated one. The most usable and flexible of types is c (cubic bezier curve), because it can represent all other types in rather high precision as these examples show: http://jsbin.com/oqojan/32, http://jsbin.com/oqojan/42.
Raphael JS library has Path2Curve-function which can convert all path segments to cubic curves and it can handle also the complicated arc to cubic conversion. Unfortunately it has a bug, so that it cannot handle all possible path segment combinations, but fortunately there is a fixed version of library available: http://jsbin.com/oqojan/32/edit (look at the Javascript-window).
When all path segments are converted to cubic curves, they can be converted to individual line segments. There are few ways, and the best seems to be an adaptive recursive subdivision method, which produces more line segments in sharp turns of curve and fewer in other parts of curve to achieve a balance of curve fidelity and low count of segments to maximize rendering speed, but unfortunately it could not handle all collinear cases. I succeeded in converting AntiGrain's method to Javascript and added presplitting functionality, which splits the curve in local extremes (first derivative roots) and after that the AntiGrain method handles also all possible collinear cases:
Collinear horizontal: http://jsbin.com/ivomiq/6
Set of different cases: http://jsbin.com/ivomiq/7
Random: http://jsbin.com/ivomiq/8
Collinear rotated: http://jsbin.com/ivomiq/9
All the above samples have two paths in top of each other to show possible errors in adaptive algorithm: the red curve is splitted using very slow brute force method and the green one is splitted using AntiGrain method. If you see not red at all, the AntiGrain's method approximate()-function is working as expected.
OK, now we have repaired Raphael and repaired AntiGrain. If we combine these both methods, we can create a function that converts ANY svg path element to polygon (single or multiple subpolygons). I'm not 100% sure that this is the best or fastest method, but it should be usable. Of course the best would be native browser implementation...
you can use De Casteljau's algorithm to break bezier curve into smaller straight lines, and join them to create polygon.
Here is some references of De Casteljau's algorithm
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html
http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html

Categories

Resources