Can somebody please help me with a geometric transformation problem? - javascript

I need to draw a circular arc between two given points. I also have the arc's radius. I understand that this can be done using standard canvas APIs but I need to handle the case of elliptical arcs too. This code is a generalized solution. The only problem right now is that it doesn't work!
The mathematical concept behind this code is at https://math.stackexchange.com/questions/53093/how-to-find-the-center-of-an-ellipse.
My JS code is implementation of that. My JS code can be found at http://jsfiddle.net/BkEnz/2/. Ideally both the circles there should pass through the two little pink dots.
I hope somebody can point me towards the right direction. I have been trying to solve this for past few days now!

Fixed this issue. The corrected working code is at http://jsfiddle.net/ZxRBT.
Notice the line
var t = translate(-R1R2x, -R1R2y, IDENTITY_TRANSFORM());
In my previous version of the code this line was
var t = translate(-R1R2x, -R1R2y, sr);
So when I was calculating the value of C1 and C2, using the following code
C1 = compose(vut, [[R1x],[R1y],[1]]);
C2 = compose(vut, [[R2x],[R2y],[1]]);
I was also applying the sr composition over R1x,R1y and R2x,R2y, but these points were already in sr coordinate.
This was a grave mistake which I overlooked for really a long time.

Related

struggling to create a smooth-moving snake in p5 js - tail catching up to head

I'm putting together a p5 sketch with little wiggling snakes that move randomly across the screen.
Unfortunately, the tail keeps catching up to the head every time it does a sharpish turn.
Here is the function I'm using to calculate the move, I've tried with a few different ways of calculating the speed, fixed numbers, relative to the snake's length.
It's supposed to work by moving the snakes head (points[3]) in a semi-random direction and then having each body point move towards the one before it by the same amount. This isn't working, and I feel there's something wrong with my algorithm itself. I'm not familiar with these kinds of intermediate random-walks, so I've just been going by guesswork for the most part.
this["moveCurve"] = function() {
let newDir = this["oldDir"] + (random() - 1/2)*PI/6;
let velocity = createVector(1,0);
velocity.setMag(5);
velocity.setHeading(newDir);
this["points"][3].add(velocity);
for (let i = 2; i >= 0; i--) {
this["points"][i].add(p5.Vector.sub(this["points"][i + 1],this["points"][i]).setMag(5));
}
this["oldDir"] = newDir;
}
If you have any idea what I could do to make this work properly, I'd love to hear your advice. Thanks!
This does look like an algorithmic issue / not a bug with how you implemented it.
Here's my go at explaining why the gap between two points must decrease in this algorithm:
Let's consider just a two point snake, with two points Hi (head) and Ti (tail) at an initial locations Hi: (20, 0), and Ti: (0, 0). So, the heading here is 0 radians.
What happens when moveCurve is called? A new heading is chosen (let's use PI/2, a right angle to make it easy to imagine) and using a fixed velocity of 5 we calculate a new position for the head of (20, 5), let's call it Hf. T also moves, but it also moves toward Hf at the same 5 unit velocity, ending up at about (4.85, 1.21). The distance between these two final positions is now 15.62657, which is smaller than the initial distance.
To visualize this, think of the triangle formed between Ti, Hi, and Hf. Ti, and Hi, form the base of this triangle. Ti will move along the hypotenuse to get to Tf, while Hi will move along the other side. The directions they are moving in form an angle which is smaller than PI radians and both points are moving at the same speed so intuitively the points must be getting closer together.
So how to solve this? Well if we consider our tiny snake's movement, the tail moved in a decent direction but too far. One solution might be to scale the velocity vector in order to maintain a fixed distance between points instead of using a fixed velocity. For example instead of stepping 5 units along the hypotenuse from Ti toward Hf in the example, you could step 20 units along the hypotenuse from Hf toward Ti. I'm not sure how this would work out for your snake, just an idea!
Keep slithering!
Fortunately, it turns out p5's documentation itself had the answer for me. By adapting the code from here to use p5 Vectors, I was able to get it all working.
The segLengths property is defined when the object is made, just takes the distances between all the points.
this["moveCurve"] = function() {
let newDir = this["oldDir"] + (random() - 1/2)*PI/6;
let velocity = p5.Vector.fromAngle(newDir).setMag(5);
this["points"][3].add(velocity);
for (let i = 2; i >= 0; i--) {
this["points"][i].set(p5.Vector.sub(this["points"][i+1], p5.Vector.fromAngle(p5.Vector.sub(this["points"][i+1],this["points"][i]).heading()).setMag(this["segLengths"][i])));
}
this["oldDir"] = newDir;
}
I might spend a little time trying to clean up the code a bit, it's a jot messy for my tastes at the moment. But it works.

Find 'view' co-ordinates in vis.js

I'm working on a modification to vis.js's Graph3d to do a filled line graph, like this:
The hard part - unsurprisingly - is working out the rendering order for the polygons. I think I can do this by checking whether a ray from the viewer to a given line B crosses line A:
In this example, since line A is "in the way" of line B, we should draw line A first. I'll use a snippet of code from How do you detect where two line segments intersect? to check whether the lines cross.
However, I haven't figured how to find the position of the user's view. I kind of assumed this would be the camera object, so wrote a little bit of debug code to draw the camera on the graph:
var camera = this._convert3Dto2D(this.camera.getCameraLocation());
ctx.strokeStyle = Math.random()>0.5 ? 'ff0000' : '00ff00';
ctx.beginPath();
ctx.moveTo(camera.x, camera.y);
ctx.lineTo(camera.x, camera.y+5);
ctx.stroke();
In fact, the camera co-ordinates as measured by this are always at 0,0,0 on the graph (which would be the far top right on the above screengrab). What I need, I think, is effectively the bottom of the screen.
How can I find this? Or is there a better way to achieve what I'm trying to do?
I don't know if this is still an active issue, but FWIW, Graph3D has internal handling of the sort ordering.
All graph points are sorted with respect to the viewpoint, using a representative coordinate called point.bottom. The rendering is then done using this ordering, with the most distant elements drawn first. This works fine as long as none of the elements intersect; in that case, you can expect artefacts.
Basically, all you need to do, is define point.bottom per graph polygon, and Graph3D will then pick it up from there.
If you are still interested in working on this:
This happens in Graph3d.js, method Graph3d.prototype._calcTranslations(). For an example, have a look at how the Grid and Surface graph elements are initialized in Graph3d.prototype._getDataPoints(). The relevant code is:
obj = {};
obj.point = point3d;
obj.trans = undefined;
obj.screen = undefined;
obj.bottom = new Point3d(x, y, this.zRange.min);

Growing Google map polygon by certain meters

I have drawn a polygon on google map(with certain lats and lngs) now I would like to grow the outer of this polygon by 40 meters(input from users). How can I achieve this? Thank you
Thank you #geocodezip, I tried buffering polygon data(without using center point of polygon) and got this
distance between black and red lines seems not same.
Thanks for all replies && answers! I found a way to do that without buffering polygon/polylines data. Should have a better way to do this. But I would like to share what I have done in here:
I know two gps points: A and B so I could get bearing between those two points.
Based on this bearing I could get the bearing between A and the point(C) 40 meters away from A because line between A and C is 90 degrees against the line between A and B
With the new bearing and distance(40m) I could get the gps point of C (How to calculate the latlng of a point a certain distance away from another?)
finally do step from 1~3 again with point from B to A
Here is a screenshot of what I have done (I have not finish yet, will upload a final screenshot later.)
Draw lines parallel to the existing ones 40 meters (or whatever the desired buffer is) to either side.
Remove the ones that have either endpoint inside the polygon
Extend the new lines and find their intersections
The intersections define the new "bigger" polygon.
Finally got this problem solved, not perfect I know.XD
Implement lines intersection: from here ( [http://jsfiddle.net/justin_c_rounds/Gd2S2/])

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!

Drawing half of a Bezier path in Raphael

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.

Categories

Resources