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
Related
I am using jsPDF to create a PDF from existing objects in my canvas. Thus I have the coordinates and the rotation angle of my objects, I want to then add to my PDF. However, every image doesn't rotate around its own center, thus it changes the coordinates drastically.
var doc = new jsPDF('p', 'mm', 'a3');
doc.addImage(image, 'PNG', 100, 100, 52.916667, 52.916667, null, null, 45);
doc.save('a3.pdf');
Can somebody help me rotate the image around its own center?
Here is a jsFiddle
https://jsfiddle.net/bx0ucszo/6/
I have the same Issue, You can solve it by playing with the degrees in X and Y for the position.
Meaning that if when you rotate your img 45 degrees it descends some pixels on Y, my solution was to put a negative value for Y, for example -100 instead of 100
Hope it's usefull for you
When trying to position a shape in Konva you can use the .position() function and you use coordinates like in most 2d graphics stuff an inverted y grid so 100, 100 would be right 100px and down 100px.
BUT! when using .position() on the stage object you seem to get very strange effects where you (unlike any grid i've ever encountered) get an inverted x grid so that 100, 100 would be left 100px and up 100px
I haven't worked that much with 2d graphics so i might be missing something obvious but the documentation for stage.position() says get/set node position relative to parent and that it's inherited from Konva.Node#position Exactly the same as is said on shape.position() documentation. Is it that stage doesn't have a parent so it behaves differently? Or am i missing something else?
Example that shows how the positioning works on stage vs shape
https://jsfiddle.net/uvp3k6wy/
They work exactly the same.
The node.position() will define "where we need to draw a node".
stage.position({x: 50, y: 50}); means that all nodes that stage has will be drawn from {x: 50, y: 50} position on canvas. So whole stage is moved by 50, 50 px to right-bottom direction.
If you have a red circle in {x: 0, y: 0}, it will have an absolute position {x: 50, y: 50} because it is moved my stage position.
I'm working on a project in which I create 3d Widget to rotate, scale and translate a mesh. The Widget I'm creating should adapt to each different 3d object that is present in my scene. Therefore i get the bounding box of the "selected" 3d object and based on the bbox.size() i know how big and where to put the widgets.
The probelm I'm facing is:
look at the image
Basically if I get the bbox of the blue clock and print the size is:
{x: 13.435844927051697, y: 20.660064093076173, z: 9.228819840426326}
While the size of the bbox of the green clock is {x: 87.35781379326076, y: 84.16006027837891, z: 210.26757627254415}, but they should be exactly the same. Please note that the green clock is a child of the Cabinet, while the blue clock is child of the Scene
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.
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