Offsetting polygons in Javascript - javascript

EDIT5: Finally got Angus Johnson's Clipper library implemented in Javascript and selected Sourceforge for host.
LIVE DEMO: http://jsclipper.sourceforge.net/6.1.1.1/main_demo.html
Download source:
https://sourceforge.net/projects/jsclipper/
Wikipage with step-by-step tutorial:
https://sourceforge.net/p/jsclipper/wiki/Home%206/
Presentation of Demo Program including tens of sample polygons:
https://sourceforge.net/p/jsclipper/wiki/Main_Demo%206/
I hope this helps anyone who needs polyline and polygon clipping library with offsetting features.
EDIT4: The one possibility is to convert pascal to javascript using
http://p2js.gelicon.biz/en/ . Not succeeded yet. p2js.exe clipper.pas gives Fatal error "Can't find unit system used by clipper".
EDIT: I found script# (Github), which seems to be able to convert C# to Javascript. Clipper lib is available in C#, so would it be possible to make C#->JS conversion using Script# and how?
EDIT3: Got not converted with script#, but there is also Emscripten, but 4000 cpp lines converted to 300 000 Javascript lines, so not an option. Manual conversion seems to be a king.
EDIT2: I made an example, which shows the problem. Use arrow left and right to apply offset. In certain distance it works ok, but then something goes wrong. The yellow stroked polygon is so called raw offset polygon, and AFAIK Clipper lib provides a way to take care of removing unneeded parts of raw offset polygon.
There is a Clipper library by Angus Johnson for offsetting polygons.
I'd need this functionality in Javascript for offsetting SVG polygons.
Has someone made a Javascript port of it?
If not, I'd appreciate some guidelines eg. the following:
- how enormous task it would be?
- which one to choose for source (Delphi, C#, C++)?
- is everything in lib needed for offsetting?
The Clipper library produces the following results which are just the desired functionality:
Some links:
- Files in Sourceforge
- Clipper Documentation
- One Stackoverflow answer
- Offsetting algorithm

I have succeded in porting clipper to JS, and after a while, after thorough testing going to release it. Seems that all the functionality could have been ported.
One caveat, 128bit support is reduced to 106bit.
One of the pros is to reach large space of browsers and possibility to use svg, vml, html5 canvas as graphics interface.
Any ideas, Which host would be easiest to publish, with demo possibility?
EDIT:
Finally got Angus Johnson's Clipper library implemented in Javascript and selected Sourceforge for host.
LIVE DEMO:
http://jsclipper.sourceforge.net/6.1.1.1/main_demo.html
Downloads:
https://sourceforge.net/projects/jsclipper/
Wikipage with step-by-step tutorial:
https://sourceforge.net/p/jsclipper/wiki/Home%206/
Presentation of Demo Program including tens of sample polygons:
https://sourceforge.net/p/jsclipper/wiki/Main_Demo%206/
I hope this helps anyone who needs polyline and polygon clipping library with offsetting features.

There are no simple solutions when it comes to polygon inflating. If you have a concave polygon, sooner or later it will break into several smaller polygons if you decrease the offset enough. So I would suggest using an existing, proven, algorithm (Clipper should be a good one).
On your question about porting C# to JS, I would say it's certainly possible, but the question is how much time it would take and whether the auto-porting tools will be of any use. Judging from this discussion, I doubt it:
I took a quick stab at using ScriptSharp to translate the C# code to
Javascript, but there are too many incompatible structures to use that
and I couldn't get it to output a javascript file. Trying to implement
the Vatti clipping algorithm in Javascript seems to be the next step.
...
And yes, it won't help you using all sorts of automatics conversion
tools.The clipper has data structures like Int64 or Int128 which are
non existent in JS or AS .I just removed them altogether .Int32 should
be enough for most cases unless you work on smth related to geography
or huge maps .
The ActionScript port one of the users there mentions is no longer available, unfortunately.

function offsetPoints(pts, offset) {
let newPoints = [];
for (let j = 0; j < pts.length; j++) {
let i = (j - 1);
if (i < 0) i += pts.length;
let k = (j + 1) % pts.length;
let v1 = [pts[j].x - pts[i].x, pts[j].y - pts[i].y];
let mag1 = Math.sqrt(v1[0] * v1[0] + v1[1] * v1[1])
v1 = [v1[0] / mag1, v1[1] / mag1]
v1 = [v1[0] * offset, v1[1] * offset]
let n1 = [-v1[1], v1[0]];
let x1 = pts[i].x + n1[0];
let y1 = pts[i].y + n1[1];
let x2 = pts[j].x + n1[0];
let y2 = pts[j].y + n1[1];
let v2 = [pts[k].x - pts[j].x, pts[k].y - pts[j].y];
let mag2 = Math.sqrt(v2[0] * v2[0] + v2[1] * v2[1])
v2 = [v2[0] / mag2, v2[1] / mag2]
v2 = [v2[0] * offset, v2[1] * offset]
let n2 = [-v2[1], v2[0]];
let x3 = pts[j].x + n2[0];
let y3 = pts[j].y + n2[1];
let x4 = pts[k].x + n2[0];
let y4 = pts[k].y + n2[1];
let den = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / den;
let x = x1 + ua * (x2 - x1);
let y = y1 + ua * (y2 - y1);
newPoints.push({ x, y });
}
return newPoints;
}

Related

Rope physics - rope not moving correctly under gravity

I am creating a circular motion simulation, where a box of mass m hangs freely on a string. A force will then be applied to the box which will either put it in circular motion, or put it in weird motion depending on the strength of the force applied.
The rope physics works fine - at least it looks ropelike, and I used a Verlet algorithm based upon suggestions from other threads on stackoverflow and various YouTube videos after failing to apply a forces and angles based approach. This is the first time I have used this method.
The problem is that the time dependency doesn't seem to work correctly, its far too slow. I have created a stack blitz with the base code for this part of the sim. Without timeSimSpeed it looks ropey and like I would expect in real life, except far too fast.
I assumed it is something to do how I applied the force and time dependency to the sim:
processPoints2() {
for(var i = 0; i < this.points.length; i++) {
var p = this.points[i];
var timeSimSpeed = ((this.elapsedSinceFrame + this.previousElapsedSinceFrame) / 2000) * this.simulationSpeed;
if(!p.fixed) {
var vx = (p.x - p.oldx);
var vy = (p.y - p.oldy);
p.oldx = p.x;
p.oldy = p.y;
p.x += vx * timeSimSpeed;
p.y += (this.gravity + vy) * timeSimSpeed;
}
}
}
But this, logically at least, seems to make sense to me. Elasped and previousElasped are in ms and averaged which is why I have 2000 there, but even using only the current frame speed its the same outcome. I'm not familiar enough with Verlet methods to be able to work through the mathematics of whether the sticks could be restricting the motion and creating this speed issue.
Any help is much appreciated, even if it is a link to somewhere this has been addressed before that I have failed to see.
EDIT:
OK so after a bunch of comments on this I have gotten around to make some modifications. I have dropped the weird way of calculating velocity and am explicit with that now, and have also been explicit with the distance units (before it was 1 pixel per meter, but this is now defined, and I changed it to 10meters per pixel. I have also updated my stackblitz.
You will notice there are still some errors (the rope has no maximum extension and will keep stretching!) but the major one for me is that it still doesnt fall under gravity correctly...
The processing looks a lot simpler now:
processPoints2() {
for(var i = 0; i < this.points.length; i++) {
var p: point = this.points[i];
var timeSimSpeed: number = (this.elapsedSinceFrame / 1000) * this.simulationSpeed;
if(!p.fixed) {
p.vx += p.ax * timeSimSpeed;
p.vy += p.ay * timeSimSpeed;
p.x += p.vx * this.pixelsPerMeter * timeSimSpeed;
p.y += p.vy * this.pixelsPerMeter * timeSimSpeed;
}
}
}
As it just uses a classical method of calculating velocity and position.
Any help would continue to be appreciated. It has been pointed out that this isnt verlet so I have amended the title and tags to appropriately represent the question.

After Effects Expression to get 3rd point in a triangle with 2 points & all lengths known (but variable)

Caveat A: This is a personal project solely for the purpose of learning, so I don't need a better way to skin this cat.
Caveat B: I have looked at THIS for a while & it doesn't quite get me where I need to go because it assumes that the B is on the same y coordinate as A. I don't have that luxury.
I am trying to build out a sort of IK chain for a character in After Effects with expressions. For the legs(also the arms for that matter, but one step at a time), I was thinking I could use the formula to determine the point in a triangle (hip to knee to foot, 3 points, a triangle) but I have never been good at math & the last math class I took was 15 years ago.
I have the calf parented to the hip, & the foot parented to the calf. So the anchor point of the hip is essentially the origin. I know in the code below there will be a little bit of toWorld or toComp trickery but I wanted to get the actual equation down first.
Reference Image A
Reference Image B
Down below you can see the code I have so far to see the variables I am referencing. With that in mind here are the two equations I think I am supposed to use.
Math.pow(x, 2) + Math.pow(y, 2) = Math.pow(A2B, 2)
Math.pow((x - C.position[0]), 2) + Math.pow((y - C.position[1]), 2) = Math.pow(A2B, 2)
or in more traditional syntax
xˆ2 + yˆ2 = A2Bˆ2
(x - Cx)ˆ2 + (y - Cy)ˆ2 = B2Cˆ2
If I am solving the first equation for y I get this. y = A2B - x
showing my work
xˆ2 + yˆ2 = A2Bˆ2
yˆ2 = A2Bˆ2 - xˆ2
y = √(A2Bˆ2 - xˆ2)
y = A2B - x
I am not even sure if this is correct....
That being said here's what I have worked up so far.
// A is the hip
A = thisComp.layer("HIP");
// B is the calf
B = thisLayer;
// C is the foot
C = thisComp.layer("FOOT");
// A2B & B2C are both fixed lengths, based on the size of the layer.
A2B = A.height - (B.anchorPoint[1] * 2);
B2C = B.height - (C.anchorPoint[1] * 2);
A2C = length(A.position, C.position);
y = A2B - x;
This where I get stuck. I plug y into the second equation & it gets wooly really fast.
Math.pow(((A2B - x) - C.position[0]), 2) + Math.pow(((A2B - x) - C.position[1]), 2) = Math.pow(B2C, 2)
or
((A2B - x) - Cx)ˆ2 + ((A2B - x) - Cy)ˆ2 = B2Cˆ2
Trying to solve this for x so I can plug that back into y is eluding me. X is used twice here & it's buried within a parenthetical & part of an exponent. I can't wrap my head around how to pull X out of the bear traps that its in.
Also if it's easier to write the answer out in traditional math syntax I can read that (mostly) too.
Lastly, like I said above I haven't taken a math class in over a decade so if my terminology is wrong or this is super easy (if you must laugh at me, do it privately... please) or anything along those lines, I apologize in advance.
Help me Obi-Wans, you're my only hope.
x^2 + y^2 = a^2 (1)
(x-cx)^2 + (y-cy)^2 = c^2
so
x^2 - 2*x*cx + cx^2 + y^2 - 2*y*cy + cy^2 = c^2 (2)
subtract (2) from (1)
2*x*cx - cx^2 + 2*y*cy - cy^2 = a^2 - c^2
y = (a^2 - c^2 - 2*x*cx + cx^2 + cy^2) / (2*cy) (3)
substitute y from (3) into (1) and solve quadratic equation for x - you'll get two (if possible) coordinates

Find Inverse Tangent?

I'm new to Javascript and I'm trying to use inverse tangent to find the angle in degrees between a line and the x axis on an elevated y. I don't see any command for it so I really need some help.
Use Math.atan() function and then Math.toDegrees() multiply it by 180/Math.PI to convert radians to degrees
Found the answer it here
Later edit:
Here is an example of angle calculation between a line defined by 2 points (A and B) and the X axis.
The elevation of the second line (parallel with the X axis) is irrelevant since the angle stays the same.
/*
* Calculates the angle between AB and the X axis
* A and B are points (ax,ay) and (bx,by)
*/
function getAngleDeg(ax,ay,bx,by) {
var angleRad = Math.atan((ay-by)/(ax-bx));
var angleDeg = angleRad * 180 / Math.PI;
return(angleDeg);
}
console.log(getAngleDeg(0,1,0,0));
I found this short and simple:
const calculateAngle = (width, height) => Math.atan(width/height)/(Math.PI / 180) // Angle in degrees
Try using Math.atan (outputs angle in radians) and some trigonometry.
Questions like these are best answered by the reference. I see a bunch of trigonometric functions there, including:
acos()
asin()
atan()
atan2()
cos()
degrees()
radians()
sin()
tan()
Note: As of Dec 5, 2018, the repository has been archived and processingjs.org redirects there.
With the development of p5js and the API advances in Processing itself, as well as Processing.js itself having been in maintenance mode for quite a few years now, this project has been archived as of December 2018.
Processing.js would like to thank everyone who contributed over the years: it's been an amazing project! The code will still be available in read-only mode, no releases will be pulled from any of the places it was distributed through, but the last version is, and will forever be, v1.6.6.
Thank you for your support, and happy coding (with newer solutions)!

Converting Latitude, Longitude in Decimals to the pixels for plotting markers on a plane svg image

I can see many answers to this question, but I don't clearly seem to follow most of those.
What I have been trying is to create an interactive world map with dynamic markers based on given latitudes and longitudes.
I have tried various equations found online but couldn't get the closer result.
The things I have tried so far,
var y = Math.round(((-1 * lat) + 90) * (containerHeight / 180));
var x = Math.round((lon + 180) * (containerWidth / 360));
x = R * Math.cos(lat) * Math.cos(lon)
y = R * Math.cos(lat) * Math.sin(lon)
var x = 1.9928145063077821*1000000 - 14017.262662576404*lat + 19202.720184031*lon;
var y = 334427.99241686985 - 33618.80202858345*lat - 14069.747257820272*lon;
Is there any better of implementing the same? Mercator, Azimuthal, Cylindrical ?
You can search for "Web Mercator". Google, Bing, OpenStreetMap uses this one and its kind a standard for web now. I don't have experience and enough information about calculation methods but formula which given on Wikipedia may help you.

paper.js union difference and intersection

I'm working on a project in paper.js where I need to create new paths based on the intersection, difference and union of two others. I did some digging and found the mathematical function that interpolates a cubic bezier spline, but I was wondering if there were any javascript libraries that did svg-like vector arithmetic. If anything, I'll copy inkscape's and convert it to javascript, but you never know.
Anyway, the mathematical function for interpolating cubic beziers is as follows:
Pointx = (Ax * percent^3) + (Bx * 3 * (percent^2 * (1-percent))) + (Cx * 3 * (percent * (1-percent)^2)) + (Dx * (1-percent)^3)
Pointy = (Ay * percent^3) + (By * 3 * (percent^2 * (1-percent))) + (Cy * 3 * (percent * (1-percent)^2)) + (Dy * (1-percent)^3)
Where A, B, C and D are the points for the curve. A is the start, D is the end, and B and C are the "control points" that manipulate the curvature between A and D. The percent is how far along the curve to calculate on a scale from 0 to 1.
So it would be pretty trivial coming up with an interpolation function that returns a point for a provided bezier and a percentage along the bezier. Finding the inverse - a percentage(s) for a given point (or x value or y value) would be difficult. Or even more difficult, where two beziers intersect (I'm not very good at math). I'm hoping that's what inkscape's functions provide.
Are there any javascript libraries that can do this kind of vector interpolation quickly? If not, I'll post the algorithm I come up with here.
Thank you!
What you are looking for is something called Boolean Operations on Polygons
Paper.js seems to now use fairly nice BoolOps and they deal directly with bezier curves. This should be the first choice if you ask me. Here's a nice example.
In another scenario, you could polygonize the shapes using De-Casteljau algorithm and feed them into Javascript Clipper. If you use high sampling the visual result is identical to true curves, but you lose the curvy nature of the paths.
While I wouldn't go so far as to say this is a duplicate question I believe you will find great insight from the answers to this question as it is quite similar.
I did find one other resource that is not mentioned amongst the answers to that question here:
http://13thparallel.com/archive/bezier-curves/
Other than that the best resource that was mentioned in that question is here:
http://blog.mackerron.com/2011/01/01/javascript-cubic-splines/
Both these resources detail specific functions that will do what you are looking for. While they are not quite "libraries" the code will be easily ported to your project for your purposes.

Categories

Resources