Translating x,y while scaling - c++

I'm trying to graph x,y coordinates where the window size is 600px by 600px. (0,0) would be in the top left.
(300,300) middle of the window.
(600,600) would be in the bottom right.
I am trying to translate latitude/longitude in radians to pixels and then plotting them.
I'm calculating 1px = ? lat by
`fabs(lborder+rborder)/600`
I calculated lon by taking the top and bottom borders.
Then when I want to find a specific position for a specific lat or lon:
lat/(previous # calculated above)
Problem is my window goes from 0,0 to 600,600 as explained above and I can get negative points and I'm not sure how to move them and I don't know how to center them around 300,300 when the bounds change.
At the moment, as long as I make the center (0,0) in terms of (x,y), not pixels, points get plotted where they're supposed to go.
For example, if x is -1 to 1 and y is -3 to 3, (300px,300px) would be (0,0).
If I change the bounds to say x -.5 to 1 and y -3 to .5, (300px,300px) would be (.25, 1.25). However, the calculations above with these numbers.
1.5/600 = .0025 ----> 1px = .0025lat.
3.5/600 = .0058 ----> 1px = .0058lon.
Then taking the midpoint (.25,1.25):
.25/.0025 = 100px
1.25/.0058 = 215px
which is clearly not 300px,300px despite being the center of the graph.
Any ideas would be extremely helpful.

If you would like to adjust the coordinates to the center, then maybe somthing like this?
Coord coordsFromCenter(Coord old_coord, float height, float width)
{
Coord new_center;
float new_x_center = width/2.0;
float new_y_center = height/2.0;
new_center.set_x(old_coord.get_x() - new_x_center);
new_center.set_y(old_coord.get_y() - new_y_center);
return new_center;
}

Related

What value should Z actually be for perspective divide?

So I'm trying to understand the fundamentals of perspective projection for 3D graphics and I'm getting stuck. I'm trying to avoid matrices at the moment to try and make things easier for understanding. This is what I've come up with so far:
First I imagine I have a point coming in with screen (pixel) coordinates of x: 200, y: 600, z: 400. The z amount in this context represents the distance, in pixels, from the projection plane or monitor (this is just how I'm thinking of it). I also have a camera that I'm saying is 800 pixels from the projection plane/monitor (on the back side of the projection plane/monitor), so that acts as the focal length of the camera.
From my understanding, first I find the total z distance of the point 200, 600 by adding its z to the camera's focal length (400 + 800), which gives me a total z distance of 1200. Then, if I wanted to find the projected point of these coordinates I just need to multiply each coordinate (x & y) by (focal_length/z_distance) or 800/1200 which gives me the projected coordinates x: 133, y: 400.
Now, from what I understand, openGL expects me to send my point down in clips space (-1 to 1) so I shouldn't send my pixel values down as 200, 600. I would have to normalize my x and y coordinates to this -1 to 1 space first. So I normalize my x & y values like so:
xNorm = (x / (width/2)) - 1;
yNorm = (y / (height/2)) - 1;
This gives me normalized values of x: -.6875, y: -.0625. What I'm unsure of is what my Z would need to be if openGL is going to eventually divide these normalized values by it. I know aspect ratio probably needs to be entered into the equation but not sure how.

Char's bounding box order of vertices

Google Vision API documentation states that vertices of detected characters will always be in the same order:
// The bounding box for the symbol.
// The vertices are in the order of top-left, top-right, bottom-right,
// bottom-left. When a rotation of the bounding box is detected the rotation
// is represented as around the top-left corner as defined when the text is
// read in the 'natural' orientation.
// For example:
// * when the text is horizontal it might look like:
// 0----1
// | |
// 3----2
// * when it's rotated 180 degrees around the top-left corner it becomes:
// 2----3
// | |
// 1----0
// and the vertice order will still be (0, 1, 2, 3).
However sometimes I can see a different order of vertices. Here is an example of two characters from the same image, which have the same orientation:
[x:778 y:316 x:793 y:316 x:793 y:323 x:778 y:323 ]
0----1
| |
3----2
and
[x:857 y:295 x:857 y:287 x:874 y:287 x:874 y:295 ]
1----2
| |
0----3
Why order of vertices is not the same? and not as in documentation?
It seems like a bug in Vision API.
The solution is to detect image orientation and then reorder vertices in the correct order.
Unfortunately Vision API doesn't provide image orientation in it's output, so I had to write code to detect it.
Horizontal/vertical orientation can be detected by comparing character height and width. Height is usually larger than width.
Next step is to detect direction of text. For example in case of vertical image orientation, text may go from up to down or from down to up.
Most of characters in output seem to appear in the natural way. So by looking at stats we can detect text direction. So for example:
line 1 has Y coord 1000
line 2 has Y coord 900
line 3 has Y coord 950
line 4 has Y coord 800
We can see that image is rotated upside down.
You must to reorder vertices of four poins(clockwise inverted from A to D):
A-B-C-D that:
A: min X, min Y
B: max X, min Y
C: max X, max Y
D: min X, max Y
And save to your rectangle object.
Update: You can order vertices by distance from O(0,0) for A-B-C-D order above.

Qt 5.5 draw filled pie

The image below shows the grey pie, I would like to draw this using Qt 5.5
X increases left to right
Y increases top to bottom
I have a start angle and an end angle which represents to the top and bottom of the arc, I am calculating the arc angle using:
double dblArcAngle = fmod(mcfltElevMaxLimit - mcfltElevMinLimit + 180.0, 360.0) - 180.0;
Where:
mcfltElevMaxLimit is 60 and mcfltElevMinLimit is -10
The call to drawPie looks like this:
objOffscrPainter.drawPie(QRect(rctGeom.left() + mcintElevLeftMargin
,rctGeom.top() + mcintElevBottomMargin
,rctGeom.width() - mcintElevLeftMargin
,rctGeom.height() - mcintElevBottomMargin)
,mcfltElevMaxLimit * 16, dblArcAngle * 16);
What I get is a very small polyline about midway up where the pie should be.
(edit), just read in the documentation that both startAngle and spanAngle parameters 2 and 3 should be multiplied by 16, which does produce a pie, not in the correct orientation and not filled to the center but its progress.
(edit 2), more progress, the image below now shows the results I'm getting, the rectangle I'm passing is the outer rectangle and includes the axis, yet for some reason the pie is offset???
What I want to accomplish is the pie tucked into the bottom left aligned with the white axis and filling the image.
It looks like the passed rectangle is used to determine the center point for the pie. If this is correct then the center of the rectangle must be adjusted to be the origin (bottom left) and the size also adjusted to fill the display.
The rectangle in a first parameter of QPainter::drawPie is a bounding box of a circle which contains your arc. So, to draw what you need try something like this:
objOffscrPainter.drawPie(QRect(center.x() - r, center.y() - r, 2 * r, 2 * r)
,16*mcfltElevMaxLimit, 16*dblArcAngle);
(where center is a center of your arc)
It seems that in your case center is a QPoint(0, 0), so you can use this code:
objOffscrPainter.drawPie(-r, -r, 2*r, 2*r, 16*mcfltElevMaxLimit, 16*dblArcAngle);
(we can call it without QRect too, see the documentation)

Find a point inside a rotated rectangle

Ok so, this should be super simple, but I'm not a smart man. Technically I want to know whether a point resides inside a rectangle, however the rectangle can be in different states. In my current context when I want to draw a rectangle rotated by, lets say, 45° clockwise, what I do is rotate the entire x,y axis centered at the top-left corner of the rectangle and then I just draw the rectangle as if nothing has happened. Same goes if I want to draw the rectangle at a random coordinate. Given that is the coordinate system who gets tossed and rotated, the rectangle always thinks it's being drawn at (0,0) with 0°, therefore, the best way to find if a given point is inside the rectangle would be to find the projection for the point based on the translation + rotation of the rectangle. But I have no idea how to do that.
This is what I currently do in order to find out if a point is inside a rectangle (not taking into consideration rotation):
bool Image::isPointInsideRectangle(int x, int y, const ofRectangle & rectangle){
return x - xOffset >= rectangle.getX() && x - xOffset <= rectangle.getX() + rectangle.getWidth() &&
y - yOffset >= rectangle.getY() && y - yOffset <= rectangle.getY() + rectangle.getHeight();
}
I already have angleInDegrees stored, as long as I could use it to project the (x,y) point I receive I should be able find out if the point is inside the rectangle.
Cheers!
Axel
The easiest way is to un-rotate x,y in the reverse direction relative to the origin and rotation of the rectangle.
For example, if angleInDegrees is 45 degrees, you would rotate the point to test -45 degrees (or 315 degrees if your rotation routine only allows positive rotations). This will plot the x,y on the same coordinate system as the unrotated rectangle.
Then, you can use the function you already provided to test whether the point is within the rectangle.
Note that prior to rotating x,y, you will probably need to adjust the x,y relative to the point of rotation - the upper-left corner of the rectangle. Since the rotation is relative to that point rather than the overall coordinate origin 0,0. You can compute the difference between x,y and the upper-left corner of your rectangle (which won't change during rotation), then simply rotate the adjusted point by -angleToRotate, then add the origin point difference back into the unrotated point to get absolute coordinates on your coordinate system.
Editted:
#include <cmath>
bool Image::isPointInsideRectangle(int x, int y, const ofRectangle & rectangle){
return x*cosd(deg) - y*sin(deg) + xOffset >= rectangle.getX()
&& x*cosd(deg) - y*sin(deg) + xOffset <= rectangle.getX() + rectangle.getWidth()
&& x*sind(deg) + y*cosd(deg) + yOffset >= rectangle.getY()
&& x*sind(deg) + y*cosd(deg) + yOffset <= rectangle.getY() + rectangle.getHeight();
Like you have already told, you could translate the coordinates of your point into the space of the rectangle. This is a common task in many software products which work with geometry. Each object have it own coordinate space and works as it would be at position (0, 0) without rotation. If your rectangle is at position v and rotated about b degree/radian, than you can translate your point P into the space of the rectangle with the following formula:
| cos(-b) -sin(-b) | | P_x - v_x |
| | ⋅ | |
| sin(-b) cos(-b) | | P_y - v_y |
Many of the most important transformations can be represented as matrices. At least if you are using homogeneous coordinates. It is also very common to do that. Depending of the complexity and the goals of your program you could consider to use some math library like glm and use the transformations of your objects in form of matrices. Then you could write something like inverse(rectangle.transformation()) * point to get point translated into the space of rectangle.

Positioning a widget involving intersection of line and a circle?

Here is the problem I'm trying to solve for my game.
I have this scenario:
I'm trying to solve for the position and size of the green rectangle. The circle is at 50%, 40% of the screen and its radius is proportional to the height of the screen.
The green rectangle must always be 10 pixels away from the bottom. Its left corner must be 10 pixels away also. And as can be seen in the image, the distance from the top right corner until the rectangle touches the circle is 10 pixels also.
Another constraint is that the green rectangle must always be 3 times wider than its height (aspect ratio).
Given these constraints, how can I solve for the position and size of the green rectangle?
Essentially, the Game Window can have a bunch of different aspect ratios so the green rectangle must look good in any of these situations.
I'm not necessarily looking for code but just an idea on how this could be solved.
Thanks
The thing to do in these situations is to describe the constraints mathematically, and see if it simplifies. This is an essential skill for geometric processing.
Let's assume the bottom left corner of the image area is (0,0). That puts the bottom-left corner of the rectangle at (10,10); we'll call the top-right corner (x1,y1). I'll assume you've already calculated where the circle will be since that's pretty straight-forward, we'll call the center (x2,y2) and the radius r.
The first constraint: the rectangle is 3 times wider than it is tall.
x1-10 = 3 * (y1-10) or x1 = 3 * (y1-10) + 10 or x1 = 3*y1 - 20
The second constraint: x1,y1 lies 10 pixels away from the circle. If we describe another circle 10 pixels larger than the first, the point will lie on it.
(x1-x2)^2 + (y1-y2)^2 = (r+10)^2
Substituting for x1:
(3*y1 - 20 - x2)^2 + (y1-y2)^2 = (r+10)^2
This is great, because r, x2, and y2 are known; the only unknown left is y1. Let's see if we can gather all the y1's together.
(3*y1 + (-20 - x2))^2 + (y1-y2)^2 = (r+10)^2
3^2*y1^2 + 2*(3*y1*(-20-x2) + (-20-x2)^2 + y1^2 + 2*y1*-y2 + y2^2 = (r+10)^2
3^2*y1^2 + y1^2 + 6*(-20-x2)*y1 + 2*-y2*y1 + y2^2 = (r+10)^2
(3^2+1)*y1^2 + (-120 - 6*x2 - 2*y2)*y1 + y2^2 = (r+10)^2
At this point it's looking almost like a quadratic equation. One more little tweak:
10 * y1^2 + (-120 - 6*x2 - 2*y2) * y1 + (y2^2 - (r+10)^2) = 0
The final step is to apply the Quadratic Formula.
a*y1^2 + b*y1 + c = 0
a = 10
b = (-120 - 6*x2 - 2*y2)
c = (y2^2 - (r+10)^2)
y1 = (-b +/- sqrt(b^2 - 4*a*c)) / 2*a
There are two possible answers from the quadratic equation, but one of them will put the rectangle on the far side of the circle. It should be easy to eliminate that case.
What you have there is a classic circle-line intersection problem. You know a point on the line - the bottom left corner of the rectangle. And you know the slope of the line (from the aspect ratio). The circle you intersect with can be your red circle shifted left by 10 to give you your 10 pixel gap. The intersection will be the top right corner of the desired rectangle. That should be enough for an idea.