Qt 5.5 draw filled pie - c++

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)

Related

Move 3d object right/left + up/down independent of its rotation

Goal:
Move a 3D object as if it is in 2D space (screen). So if the user moves the mouse left the object should move left (the same should apply for all other directions: right, up, down).
Description:
I am working with OpenTK (OpenGL - 3D space)
Since the object itself should always rotate around it's center I first apply the rotation then the translation matrix.
What works
With trying out I was able to get the translation for the x-Axis and y-Axis (both 2d space) working separately.
// works for x-Axis movement
var rotation = _control.Rotation;
// vector is a 2d vector that contains the vector from the mouse drag start position
// (so the pixels the mouse was moved from the drag start to its current position)
// factor is a value that depends on the current zoom value - can be ignored for the problem itself
var xTranslationVector = new Vector3(
vector.X * (float)Math.Cos(rotation.Y) * factor,
0,
vector.X * (float)Math.Sin(rotation.Y) * factor);
// initial value is the original translation on drag start
_control.Translation = initialValue + xTranslationVector;
// vector for y-Axis
var yTranslationVector = new Vector3(0,
-vector.Y * (float) Math.Cos(rotation.X) * factor,
vector.Y * (float) Math.Sin(rotation.X) * factor);
// _control.Translation = initialValue + yTranslationVector;
Both work when used independent from each other.
Questions
How do I need to combine the xTranslationVector and yTranslationVector so that it would work as expected (multiplication doesn't work because any vector component could be 0 which results in no movement at all; addition does not work when the object is rotated around some axis partially)
I would like to understand what I am doing there, what are the mathematical terms i should look for to find explanations?
How can I do the same for rotation (f.e. the object is rotated 45° degrees around the y axis and I want to rotate - currently the object would tilt around it's x axis but i would like to tilt it always as if the object was not rotated around it's x axis - sorry not sure how to word this well)

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.

Set the orientation of objects in 3d space

I have program in which I am drawing some shapes such as rectangle/circle/triangle etc. in 3D space, equidistant from the centre.
Example of two points which are equidistant from the centre (0,0,0) are
x1: 93, 313, 123
x2: -263, -135, -186
and there may be more points as well.
At these two points, I am drawing the shapes by something like
glRectangle(x1, width, height);
The shapes (rectangles/triangles etc.) come out very well at the starting vertex (x1 or x2) equi-distant from the centre. However, the shapes have wrong orientation in space as to what I am looking for.
I want centre of the plane of in which the shape lies to to be prependicular to an imaginary line coming from the centre. This probably can be solved by rotation of the plane but I am not sure about the approach to adopt. For the current example, let's say I have the vertex of the shape but how do I figure out the plane in which the the rectangle is and rotate that plane to make it prependicular (to the line coming from the centre of the space (0,0,0))
If the center needs to be perpendicular to the vector C (Line between coord-center and rect-center), it should work like this (pseudo-code):
A = C x UP_VECTOR (CROSS-PRODUCT to calculate helper vector pointing in "sideway" direction of "rectangle")
B = C x A (CROSS-PRODUCT to get the local "up/down" vector of the "rectangle")
A = normalize(A)
B = normalize(B)
P1 = width/2 * A + height/2 * B
P2 = -width/2 * A + height/2 * B
P3 = -width/2 * A + -height/2 * B
P4 = width/2 * A + -height/2 * B
Hopefully this is understandable and right (didn't try it and had some trouble finding the right vocabulary)
Some additional informations:
A and B are helper vectors and are the local up and left directions on the rectangle, after normalizing they can be used to calculate the 4 points of the rectangle accordingly.
Also be careful if no rectangle is displayed it's probably related to the drawing order so just reverse the order then if front and backfaces are wrong...

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.

OpenGL - GlVertex relative/absolute position

Imagen I have a list of 2D points (x,y) that describe a 2D terrain in my simple game.
I have then glVertex() to draw all those points in GL_POINTS mode.
Then I have a Ball that also has it's (x,y) coordinates.
I want the ball to have a definite size in relation to everything else (such as the terrain).
How should I set the values of the (x,y) coordinates to draw everything the size I want it?
Having a 600x400 screen.
I am troubled also because glVertex2f(1,1) will draw a primitive point on the upper right corner. So 1 represents to go 100% to the right or top. But the screen is 600x400 so I can't have dimensions of equal length on x and y axis.
Since 0 is 0% (absolute left/bottom) and 1 is 100% (absolute right/top), you just have to find a point in between that will line up with the pixels.
For example. Say your ball is 20x20 pixels. This means that it is 5% of the screen tall and 3.33% of the screen wide. Therefore, the square surrounding your ball would have the following vertices:
void drawBall()
{
glVertex2f(ball.x - (20/600)/2, ball.y - (20/400)/2);
glVertex2f(ball.x - (20/600)/2, ball.y + (20/400)/2);
glVertex2f(ball.x + (20/600)/2, ball.y + (20/400)/2);
glVertex2f(ball.x + (20/600)/2, ball.y - (20/400)/2);
}
See how I'm dividing the width of the ball by the width of the screen to get a floating point value that works with glVertex2f? Also, ball.x and ball.y should be a floating point value between 0 and 1.
I divide these numbers by 2 because I'm assuming that (ball.x, ball.y) is the coordinate of the center of the ball, so half of the addition goes on either side of the center.
You can write your own function that draws the vertices and that takes pixels in arguments:
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
void glVertex_pixels(const double x,const double y){
glVertex2d(x * 2.0 / (double)WINDOW_WIDTH - 1.0, 1.0 - y * 2.0 / (double)WINDOW_HEIGHT);
}
You can also use a macro:
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
#define glVertex_pixels(x,y) glVertex2d((double)(x) * 2.0 / (double)WINDOW_WIDTH - 1.0, 1.0 - (double)(y) * 2.0 / (double)WINDOW_HEIGHT);
No matter which of the above codes you use, the use of this function is simple. For example, the following code draws a vertex 10 pixels from the left side and 20 pixels from the top side:
glVertex_pixels(10,20);