How do I move my rectangle in Javascript Graphics? - javascript

SO right now I have this code just to make the rectngle itself.
var x = getWidth();
var y = getHeight();
var rect = new Rectangle (x, y);
rect.setPosition(395,399);
rect.setColor("blue");
add(rect);
The problem I'm having is that I dont know how to more it to the left more. IF someone can maybe explain this to me I will aprreciate it. Thanks
I tried using this
rect.move(dx, dy);
rect.move(dx, dy);
But I dont have dx or dy defined. Also when i tried putting them as a var with a x,y it didnt show up on the screen at all.

Related

d3.js -- line connecting two transformed svg elements

I created an array of small circles (dots) laid on a circumference of a larger circle in a loop, with each iteration I rotate the same dot with the same cx and cy by a different angle using transform=rotate(i*angle,0,0).
Now I want to connect a line between two of the dots, but since each dot has the same cx and cy, my naive way of passing in the cx and cy of the two dots as coordinates doesn't seem to work.
Strangely on JSFiddle, half of the line is shown, even though the line's x0 == x1 and y0 == y1: https://jsfiddle.net/8wn30vqn/1/
What is a good way of obtaining the coordinates of a transformed svg element so I can pass them into the line? Or is there some other way I can connect two elements with a line?
The good way would be to take transformation matrix from each of your small circles and apply it to the same point to get new point (and then connect these new points).
var svgNode = d3circle.node();
var matrix = svgNode.transform.baseVal.consolidate().matrix;
var pt = svgNode.ownerSVGElement.createSVGPoint();
pt.x = 0;
pt.y = 0;
var transformedPoint = pt.matrixTransform(matrix);
... use transformedPoint to create line

a failed attempt at placing a dot over an image based on known lat and lng points

I apologize for the vague title, I really can't figure out a batter way to sum it up. Suggestions are more than welcome.
I'm working on a project that really doesn't NEED a google map, it'd just create extra overhead for this project. But, I can't figure out how to do this WITHOUT google maps... so far.
If I were to place a graphical overlay of a floor plan into google maps, I could use a browser location to approximate a users position. For this, it's a VERY large place, so there's room for some poor accuracy.
Now what I'm trying to do is knowing the bounding of that overlay, place the image into a div, then calculate the users position in the div based on their browser lat/lng.
I'm able to get close using an image that is square in that the top of the sides are horizontal and vertical, because that crates my area. But since none of the world works like that, I need an area that isn't square to appear squared. I'm really struggling on the math.
Here's what I'm trying to do!
And here's a link that tests my concept, but doesn't account for an image that needs to be rotated on a map: http://www.freeptools.com/mapster/singlerun/maptest.php
Like I said, I'm sure that this can be done, but I haven't been able to figure out the math for it just yet. It's driving me crazy.
Here's my code that's doing the magic. A function gets the browser coordinates and sends them to the initialize function. Then based on mapping it myself earlier, I have the bounds of the image I'm trying to map. I'm using the haversine formuls to try to get the height and width at the points of the user (since the map curves, it'll be inaccurate anywhere else) position, then the distance from the top and left most points, then taking the distance from the left/top and dividing it by the width/height to get a percentage of how far they are from the left/top to position the dot. This idea, while I can't get it to be super accurate, works in this example, because the image lines up horizontally on a map. My problem is how do I calculate those distances when the image is rotated on a map? I can't figure out that math.
function initialize(y3, x3) { //lat, lon
//var overlayBounds = new google.maps.LatLngBounds(new google.maps.LatLng(41.11246878918085, -90.5712890625), new google.maps.LatLng(47.68652571374621, -82.001953125));
var box = $("#map_canvas");
//image bounds
var x1 = -82.001953125;
var x2 = -90.5712890625;
var y1 = 41.11246878918085;
var y2 = 47.68652571374621;
var boxWidth = x2 - x1;
var boxHeight = y2 - y1;
//now we need to figure out where this rests, first we get the percentage
//var posLeft = haversine(y3, x1, y3, x3); //(x3 - x1);
var posLeft = (x3 - x1);
var posLeftPct = (posLeft/boxWidth)*100;
//var posTop = haversine(y2, x3, y3, x3); //(y2 - y3);
var posTop = (y2 - y3);
var posTopPct = (posTop/boxHeight)*100;
box.append('<img src="http://www.freeptools.com/mapster/icons/icon23.png" style="position:absolute; z-index:200; right:'+posLeftPct+'%; top:'+posTopPct+'%">');
}
Assuming the area is a parallelogram, you'll need to know 3 of the vertices of the area and the width/height of the area where you want to draw the pin(e.g. the floorplan-image).
The following will use the Geo-and LatLon-libraries from http://www.movable-type.co.uk/scripts/latlong.html
An image for better understanding:
initially calculate some values:
bearings(nw to sw and nw to ne) via LatLon.bearingTo
distances(sw to nw and ne to nw) via LatLon.distanceTo
now calculate the intersections(marked as intersection-x and intersection-y in the image) via LatLon.intersection
The calculation would be:
intersection-x:
LatLon.intersection(ne, bearingNWtoSW, target, bearingNWtoNE)
intersection-y:
LatLon.intersection(sw, bearingNWtoNE, target,bearingNWtoSW)
now calculate percentual values for the distance of border-north to target and border-west to target:
border-north to target:
((distanceNWtoNE-(target.distanceTo(intersection-x)))*100)/distanceNWtoNE
border-west to target:
((distanceNWtoSW-(target.distanceTo(intersection-y)))*100)/distanceNWtoSW
Finally calculate the coordinates based on the width/height of the given floorplan and the results of the previous calculation
x=((width*distanceBorderNorthToTargetInPercent)/100);
y=((height*distanceBorderWestToTargetInPercent)/100);
A method(extension of the mentioned LatLon-library) that performs all these calculations:
/**
*#param w int width of the drawing
*#param h int height of the drawing
*#param sw object LatLon of southwest of the drawing
*#param nw object LatLon of northwest of the drawing
*#param ne object LatLon of northeast of the drawing
*#return mixed object with x/y-coordinates or null when LatLon is outside of the area
**/
LatLon.prototype.translate = function(w,h,sw,nw,ne) {
var x = {distance:nw.distanceTo(ne),bearing:nw.bearingTo(ne)},
y = {distance:nw.distanceTo(sw),bearing:nw.bearingTo(sw)},
intersectionY = LatLon.intersection(sw, x.bearing, this, y.bearing),
intersectionX = LatLon.intersection(ne, y.bearing, this, x.bearing),
distanceX,distanceY;
if(intersectionX && intersectionY){
distanceX=((x.distance-(this.distanceTo(intersectionX)))*100)/x.distance,
distanceY=((y.distance-(this.distanceTo(intersectionY)))*100)/y.distance;
return {x:((w*distanceX)/100),y:((h*distanceY)/100)};
}
return null;
};
Demo:http://jsfiddle.net/doktormolle/nsbqpcvg/embedded/result/
Hover the highlighted floorplan on the google-map to see the result of the calculation(the google-Maps-API is only used for the demonstration, the calculation will be done without using the Maps-API)

Raphael.js get rectangle coords after transform

I have a small little game I'm making in javascript and Raphael.js(which i'm fairly new to) and I'm making a turret essentially, just a circle that has a rectangle swivel around it. And that works fine and dandy!
Code for transform is :
this.self = this.self.animate({ transform : this.transform }, 250);
However, I need to find the coords of the rectangle after I animate it, but getBBox() keeps getting the same coords. Does anyone have any suggestions? A visual picture of the transform would be:
So I need the turret coords after the transformation. I need to find the front of the turret so I know where the bullet needs to come out of! Any advice will be appreciated!
By using the rotation number, will help you to find the coordinates. Lets say the rotation angel is q = 45 degrees.
This means that y changes by asin(q) and x changes by a - acos(q).
EDIT
Pay attention to all cases. In this particular case, both coordinates got decreased, but if you turn to southeast, then y increases and x decreases. Or if northwest: y and x decrease.
Transform is just a visual effect, it's not affects on coordinates.
You know width of turret and you know rotation angle.
Use sin & cos to calculate new coords.
X = Math.cos((i * Math.PI) / 180) * R + x;
Y = Math.sin((i * Math.PI) / 180) * R + y;
i - angle
R - width of turret
x and y - turret offset

Finding if a point is on a line

Let's say I have a line drawn as so in HTML5 Canvas:
...
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(x1,y1);
ctx.closePath();
...
I want to find out if the mouse down event happened on this line, and I have code like this:
var handleMouseDown = function(e) {
var coords = translateCoords(e.x,e.y);
...
if (ctx.isPointInPath(coords.x, coords.y) {
...
Now, this code works fine in the case of circles & rectangles, but not for lines. I have 2 questions:
My thinking is that perhaps calling closePath() on a line itself is incorrect. Question - how can I check if the mouse down event happened on this line?
How can I extend this to find if the mouse down event happened near the line?
The first step is to find the normal projection of the point onto the line. This is actually quite simple: take the distance from point 1 to the target, and point 2 to the target, and call them D1 and D2 respectively. Then calculate D1+(D2-D1)/2. This is the distance to the projected point on the line from point 1.
You can now find that point, and get the distance from that point to the target. If the distance is zero, then the target is exactly on the line. If the distance is less than 5, then the target was less than 5px away, and so on.
EDIT: A picture is worth a thousand words. Here's a diagram:
(source: adamhaskell.net)
(In hindsight, probably should have made those circles a different colour... Also, the purple line is supposed to be perpendicular to line AB. Blame my terrible aim with the blue line!)
Here is the approach taken from Wikipedia article Distance from a point to a line (Line defined by two points)
var Dx = x2 - x1;
var Dy = y2 - y1;
var d = Math.abs(Dy*x0 - Dx*y0 - x1*y2+x2*y1)/Math.sqrt(Math.pow(Dx, 2) + Math.pow(Dy, 2));
where (x0,y0) is your Point coordinates and your Line is ((x1,y1),(x2,y2))
However, this does not checks for boundaries of the line, so I had to add another check for it.
function inBox(x0, y0, rect) {
var x1 = Math.min(rect.startX, rect.startX + rect.w);
var x2 = Math.max(rect.startX, rect.startX + rect.w);
var y1 = Math.min(rect.startY, rect.startY + rect.h);
var y2 = Math.max(rect.startY, rect.startY + rect.h);
return (x1 <= x0 && x0 <= x2 && y1 <= y0 && y0 <= y2);
}
Where your Line defined as rectangle. Hope this helps.
You have two options for this. Your "simple" option is to use canvas to do it -- Read the pixel data wherever the mouse is and if it's the same color as your line then the user clicked on the line. This makes a lot of assumptions, however, like that everything on your canvas is rendered in a different solid color. This is possible, however, as a common trick is to render everything to an off-screen canvas in a different solid color. Then when the user clicks something you know exactly what it is by reading the color of that one pixel and mapping it back to the original object.
But that's not exactly what you asked for :)
You don't want to know if the user clicked on a line because they almost never will. A line is infinitely thin, so unless it's exactly horizontal or exactly vertical they will never click on it. What you want instead is to see how far the mouse is from the line. Kolink just answered that part, so I'll stop here :)

Translating an element with canvas

I'm trying to learn canvas by implementing a pie chart. I've managed to parse my data, draw the slices, and calculate the center of each arc, as noted by the black circles. But now I'm trying to draw one of the slices as though it had been "slid out". Not animate it (yet), just simply draw the slice as though it had been slid out.
I thought the easiest way would be to first calculate the point at which the new corner of the slice should be (free-hand drawn with the red X), translate there, draw my slice, then translate the origin back. I thought I could calculate this easily, since I know the center of the pie chart, and the point of the center of the arc (connected with a free-hand black line on the beige slice). But after asking this question, it seems this will involve solving a system of equations, one of which is second order. That's easy with a pen and paper, dauntingly hard in JavaScript.
Is there a simpler approach? Should I take a step back and realize that doing this is really the same as doing XYZ?
I know I haven't provided any code, but I'm just looking for ideas / pseudocode. (jQuery is tagged in the off chance there's a plugin will somehow help in this endeavor)
Getting the x and y of the translation is easy enough.
// cx and cy are the coordinates of the centre of your pie
// px and py are the coordinates of the black circle on your diagram
// off is the amount (range 0-1) by which to offset the arc
// adjust off as needed.
// rx and ry will be the amount to translate by
var dx = px-cx, dy = py-cy,
angle = Math.atan2(dy,dx),
dist = Math.sqrt(dx*dx+dy*dy);
rx = Math.cos(angle)*off*dist;
ry = Math.sin(angle)*off*dist;
Plug that into the code Simon Sarris gave you and you're done. I'd suggest an off value of 0.25.
Merely translating an element on a canvas is very easy and there shouldn't be any tricky equations here. In the most basic sense it is:
ctx.save();
ctx.translate(x, y);
// Draw the things you want offset by x, y
ctx.restore();
Here's a rudimentary example of a square pie and the same pie with one of the four "slices" translated:
http://jsfiddle.net/XqwY2/
To make the pie piece "slide out" the only thing you need to calculate is how far you want it to be. In my simple example the blue block is slid out 10, -10.
If you are wondering merely how to get the X and Y you want in the first place, well, that's not quite a javascript/canvas question. For points on a line given a distance this question: Finding points on a line with a given distance seems the most clear
Edit, here you are (from comments):
// Center point of pie
var x1 = 100;
var y1 = 100;
// End of pie slice (your black dot)
var x2 = 200;
var y2 = 0;
// The distance you want
var distance = 3;
var vx = x2 - x1; // x vector
var vy = y2 - y1; // y vector
var mag = Math.sqrt(vx*vx + vy*vy); // length
vx = mag/vx;
vy = mag/vy;
// The red X location that you want:
var px = x1 + vx * ( distance);
var py = y1 + vy * ( distance);
This would give you a px,py of (104.24, 95.76) for my made-up inputs.

Categories

Resources