I'm trying to put resizing handles on the four corners of a rectangle, which can be dragged to resize the rectangle. What I'm having trouble with is calculating the new width, new height, and new points of the rectangle after I've dragged one of the rectangle's points.
If the rectangle were not rotated, this would obviously be very easy because the width and height would change by the same amout as the mouse's offsetX and offsetY. However, this rectangle CAN be rotated, so offsetX and offsetY don't match up to the changes in width/height.
In the image above, I've represented information that I already have in solid black, and information I want to find in light grey. I've tried to show how the rectangle should change if I dragged the a1 corner up and to the right.
Could anyone help me figure out how to calculate the missing information?
Thanks for any help! It's much appreciated.
--
EDIT: I've got drag start, drag move, and drag end callbacks on each handle. My current code simply gets the new point (in this example, a2). Unfortunately this simply moves the handle we're currently dragging into its new position, but obviously has no effect on the width/height of the rectangle, and the position of its other points. What I'm hoping for help figuring out is how do I calculate the new width and height, and the new position of the other points, based on this drag.
Handle Coordinates (before drag)
handles: {
a: { x: 11, y: 31 },
b: { x: 44, y: 12 },
c: { x: 39, y: 2 },
d: { x: 6, y: 21 }
};
Callbacks:
// Save the original x and original y coordinates
// of the handle, before dragging
onDragStart: function(x, y, handle) {
handle.data({
ox: x,
oy: y
});
}
// While dragging the handle, update it's coordinates to
// reflect its new position
onDragMove: function(dx, dy, handle) {
handle.attr({
x: handle.data('ox') + dx,
y: handle.data('oy') + dy
});
}
// Not currently using the drag end callback
onDragEnd: function(x,y,handle) {}
http://en.wikipedia.org/wiki/Cartesian_coordinate_system#Distance_between_two_points gives you the method for finding the length of a1 to a2
var len=Math.sqrt(Math.pow(a2x-a1x,2)+Math.pow(a2y-a1y,2));
Then looking at the triangle formed by the intersection of the grey and black lines (Lets call that point H) and a1 and a2. You can use trigonometry to solve. So the angle formed by the line d1 to c1 with the bottom lets call that the angle of rotation(R). That means the R is equal to angle at a2 and the angle at a1 is equal to 90-R. To find the sides then you go
//line from a2 to H
var hDif=Math.sin(R)*len;
//line from a1 to H
var wDif=Math.cos(R)*len;
You can then use these to find the new length and height. There will a few more calculations to see if you are adding or subtracting to the old width and height.
I have another idea:
Consider that your rectangle is rotated by 30 degress anticlockwise with respect to the origin.
When the user clicks on one of the edges or corners, do the following:
1) Let StartPt = the point where the mouse starts.
2) Get the point where the mouse moves to. Let it be EndPt.
3) Rotate each of the vertex of the Rectangle by -30 so that now it becomes an unrotated rectangle. (Do not draw the unrotated rectangle, it is for calculcation purpose only)
4) Rotate the StartPt and EndPt by -30 degrees. Calculate the change in the width and height of the rectangle when the point.
5) Add the change to the rotated vertices of the rectangle.
6) Rotate the vertices of the Rectangle by +30 degrees. Now draw the Rectangle.
https://www.experts-exchange.com/questions/24244758/How-can-let-a-user-drag-to-resize-a-rotated-rectangle.html#answer23964155
Related
I have a position somewhere on my map (in GTAV). In JavaScript it could be something like:let targetPos = {x: 1200, y: 653, z: 250}; and I have my position which changes every time I walk or rotate. Now what I want is to get the direction of the targetPos whenever I rotate or walk. Not the function but the math solution. Currently I'm using var angle = Math.atan2(pos1.y - pos2.y, pos1.x - pos2.x) * (180 / Math.PI); which is not working as intended. It gives me the angle in degree but not when I rotate myself or when I walk around it. In short: I want the direction of a position relative to my position. So I can rotate a circle to show in the target direction.
Here is what I have:
The player position (x, y, z), rotation (x, y, z) and heading (yaw)
The target position
As you can see in the horrible image, the circle doesn't show in the direction of the target when the player rotates
I hope you know what I mean
I have a bit of code (involving "canvas"), which generates a graph on a four-quadrant cartesian plane. (Please see the JsFiddle link in the comment below.)
I want to create a bit of code that adds a point to a specific position on the plane. However, I want the point to get plotted based on the intervals on the x- & y-axes rather than pixels. In other words, I don't want to have to guess and check where each coordinate is on the graph and then adjust accordingly. If I move the graph 200 pixels down on the page, I want the point to likewise move 200 pixels down.
Coding novice, here (if you couldn't tell already). It took me forever to get to this point, so I would greatly appreciate any help anyone is willing to offer.
Thanks!
The 2D canvas context provides a transformation to all rendering.
You can set the matrix with ctx.setTransform and you can multiply the existing transformation with ctx.transform, ctx.scale, ctx.rotate, ctx.translate
Personally I am a big fan of ctx.setTransform(a,b,c,d,e,f); where
a,b is the unit length and direction of the X axis in pixels
c,d is the unit length and direction of the Y axis in pixels
e,f is the location of the origin relative to the top left and is in
pixels.
Basicly 2 vectors defining the size (scale) and direction of a pixel x and y axis, and a coordinate defining where on the canvas the origin is. The coordinate is not effected by the scale or rotation.
So if you want the X axis to point down and the scale to be two then
a = 0, b = 2 the Y axis is then b = -2, c = 0 to be 90deg clockwise from the X axis.
If you want the axis to remain the same but the scale scale = 2 changed then
a = scale,b = 0, c= 0, d = scale. And to have the origin at the center of the canvas e = canvas.width/2, f = canvas.height/2
Now if you draw an arc ctx.arc(0,0,100,0,Math.PI*2) you will see a circle in the center of the canvas with a radius = 100*scale
Hope that makes sense....
The question is related with that other question: https://stackoverflow.com/questions/26948677/translate-coordinates-to-its-equivalent-in-scale1 that no one gave response but it does not matter anymore because it's solved, at least that part. I get the correct x and y values.
I put you in situation, the app I'm developing allows the user to create a image with 6 differents backgrounds with funny characters without face so that the user can put a photo of his/her face. To do this, they can drag, pinch to zoom and rotate the image. Drag and pinch to zoom are under control but when the image is rotated I can not match the image in the exact coordinates. The images always go up a little.
An example, I get as values that:
x: 30,
y: 80,
scale: 0.5,
deg: 40.
So, when I draw into a canvas the rotated image the y seems to go up a little depending on the degrees. Less degrees, less go up.
I'm using this function to draw the image rotated:
var TO_RADIANS = Math.PI / 180;
var drawRotatedImage = function (context, image, x, y, angle) {
context.save();
context.translate(x, y);
context.rotate(angle * TO_RADIANS);
context.drawImage(image, -(image.width / 2), -(image.height / 2));
context.restore();
}
PD: To point it out, if I do not rotate the image, it matches perfectly in the correct position.
How I can get the correct x and y values for the rotated image?
For a game project, I need to calculate positions of items on a 2D plane relative to the camera.
Camera can be rotated, and it's coordinates refer to it's center.
In the attached images, a and b are items to display and c is camera.
First image is absolute positions of items in the world.
Second image is the result I'm trying to get.
Please note that rotation doesn't have to be 90 degrees, it can be any valid angle. I just used 90 degrees to keep this example simple.
Normally this is an easy task, but because camera can be rotated, translating to/from the center is not that easy, and it makes this problem complicated.
This is not using canvas element, so using canvas translation or rotation is not an option.
Here is the data used in this example, and some boilerplate code for trying solutions:
var items = {
a: {x: 3, y: 3},
b: {x: 2, y: 4}
};
var camera = {
x: 4, y: 4,
width: 4, height: 4,
rotation: 90
}
boilerplate code on jsfiddle.net
Any help would be appreciated.
You should do these steps to achieve your result
Translate the origin to the C point
Rotate your points by Rotation matrix
Return back the origin to its original position
At this point, your items and camera has been rotated, the only work that still is left, is the clipping by camera rectangle.
As far as I know such a clipping is not very hard and can be done easily.
Hope it helps you
Here is the graphics:
http://snag.gy/aVFGA.jpg
the big rectangle is canvas element, the small rectangle is the image object in the canvas. I want to find what is the real distance from the left.
values are such from what I see in console:
regX: 564.256
regY: 41.4
scaleX: 0.4491319444444445
scaleY: 0.4491319444444445
x: 363.3333333333333
y: 409.77777777777777
So as I see x is not real. It somehow relates with regX and scaleX. But I am not finding how it relates. From the image I think the x should be about 100 - 150 px.
THe bigger the x - the more it is to the right.
But the bigger regX - the more it makes rectangle go to the left.
So if I would just take the difference 564.256 - 363.333 = ~200 - left corner of the rectangle should be in them middle of canvas because canvas is 400px widh. But it is not, so substraction does not help. So how do I get how many pixels are in real from the left?
You can do this by using the localToGlobal method (see here).
It depends to which object the given attributes belong.
If they belong to the shape and your rectangle inside the image / shape starts at (0,0):
var point = shape.localToGlobal(0, 0);
// this will calculate the global point of the shape's local point (0,0)
If they belong to the stage:
var point = stage.localToGlobal(yourRectObject.x, yourRectObject.y);
// point.x should contain the position on the canvas
You should use these methods in general because your method might work for the current situation but will probably break as soon as you scale the stage itself or put the shape in a scaled / positioned container.
I guess I found what by experimenting with values:
distanceFromLeft = x - scaleX * regX;
so getting 109.90793888888885 px
If someone has worked more with this library, they could confirm that its not accidental.