Point inside rectangle given sides and center - c++

I'm given rectangle by it's height(h) and width(w), and it's center O(x0,y0). I need to calculate if given point A(x,y) is inside that rectangle. It is parallel to x and y axis. All values are real.
I came up with following test but for some reason website on which I'm testing the code is not working for all examples. Could someone point me in the right direction.
#include <iostream>
#include <cmath>
using namespace std;
int main(){
long x,y,x0,y0,r,h,w;
scanf("%ld",&x);
scanf("%ld",&y);
scanf("%ld",&x0);
scanf("%ld",&y0);
scanf("%ld",&h);
scanf("%ld",&w);
if((x0+w/2.0>=x)&&(x0-w/2.0<=x)&&(y0+h/2.0>=y)&&(y0-h/2.0<=y))
printf("inside a rectangle");
else
printf("outside a rectangle");
}
Thanks in advance.

After OP's Edit:
The rectangle's side are parallel to x axis and y-axis. Then also it is possible to get the co-ordinates and apply the below mentioned algorithm.
Centre -- (x0,y0)
A -- (x0-w/2,y0-h/2)
B -- (x0-w/2.y0+h/2)
C -- (x0+w/2,y0+h/2)
D -- (x0+w/2,y0-h/2)
So all you have to do is, Apply the algorithms provided below.
More simply we can do this,
if( 2*x <= 2*x0+w && 2*x >= 2*x0-w && 2*y <= 2*y0+h && 2*y >= 2*y0-h)
// it's inside
Before OP's edit
Your logic is wrong. It may say a point inside rectangle to be outside of it.
(For any rectangle this is wrong - OP didn't mention the condition of being sides parallel to x-y axes)
There is a simple way and cleaner way to do this for rectangle. Find the Area of the rectangle.
Suppose it's A.
Now if the point P lies inside ABCD then
area of PAB+PBC+PCD+PDA = A
For better thing do this with ,
AB.Bc+BC.CD+CD.DA+DA.AB = 2*AB*BC
or even better make a square of both side
LHS^2 = 4*AB^2*BC^2
Now you will just multiply and check it. One drawback of this solution is for large values of side length you have a chance of overflow.
Another method would be to consider the projections.
If point is inside of the rectangle then the projection of the corner of rectangle to point, on two of it's side must be less than the corresponding sides. You can check the projection length using dot products.
For example if P is the point and ABCD is rectangle check,
if AP's projection on AB has greater than zero length but less than the length of AB. Check the same with BC and BP and check if length is greater than zero and less than BC or not.
This two condition makes sure that your point lies inside the rectangle.

Related

Starting from a source, find the next point closest to an objective on a grid in C++

I have an NxN grid with 2 points, the source and destination. I need to move step by step from the source to the destination (which is also moving). How do I determine what the next point is to move to?
One way is to assess all 8 points and see which yields the lowest distance using an Euclidian distance. However, I was hoping there is a cool (mathematical) trick which will yield more elegant results.
Your question statement allows moving diagonally, which is faster (since it's moving both horizontally and vertically in a single step): this solution will always do that unless it has the same x or y coordinate as the target.
using Position = pair<int,int>;
Position move(Position const &current, Position const &target) {
// horizontal and vertical distances
const int dx = target.first - current.first;
const int dy = target.second - current.second;
// horizontal and vertical steps [-1,+1]
const int sx = dx ? dx/abs(dx) : 0;
const int sy = dy ? dy/abs(dy) : 0;
return { current.first + sx, current.second + sy };
}
I'm not sure if this counts as a cool mathematical trick though, it just depends on knowing that:
dx = target.x-current.x is positive if you should move in the positive x-direction, negative if you should go in the negative direction, and zero if you should go straight up/down
dx/abs(dx) keeps the sign and removes the magnitude, so it's always one of -1,0,+1 (avoiding however division by zero)
I suppose that answer to your question is Bresenham's line algorithm. It allows to build sequence of integer points between start and end points in your grid. Anyway you can adapt ideas from it to your problem
For more information see https://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html
I would simply use some vector math, take dest minus source as a vector, and then calculate the angle between that vector and some reference vector, e.g. <1, 0>, with standard methods.
Then you can simply divide the circle in 8 (or 4 if your prefer) sections and determine in which section your vector lies from the angle you obtained.
See euclidean space for how to calculate the angle between two vectors.

Determine if point is in frustum

I'm trying to work out the best way to determine whether a point is inside a frustum. I have something working, but not sure whether it is too cumbersome, and perhaps there is a more elegant / efficient way I should be doing this.
Suppose I want to find out whether point 'x' is inside a frustrum:
Once I have the locations of the 8 points of the frustrum (4 near points, four far points), I am calculating the normal for each plane of the frustum based on a triangle made from three of the points. For example (as in the diagram above), for the right side, I am making two vectors from three of the points:
Vector U = FBR - NBR
Vector V = FTR - NBR
Then I am making the cross product between these two vectors, ensuring that the winding order is correct for the normal to be pointing inside the frustum, in this case V x U will give the correct normal.
Right_normal = V x U
Once I have the normal for each plane, I am then checking whether point x is in front of or behind the plane by drawing a vector from x to one of the plane's points:
Vector xNBR = x - NBR
Then I am doing the dot product between this vector and the normal and testing whether the answer is positive, confirming whether point x is the correct side of that plane of the frustrum:
if ( xNBR . Right_normal < 0 )
{
return false;
}
else continue testing x against other planes...
If x is positive for all planes, then it is inside the frustum.
So this seems to work, but I'm just wondering whether I'm doing this in a stupid way. I didn't even know what 'cross product' meant until yesterday, so it's all rather new to me and I might be doing something rather silly.
To adapt the approach you have taken, rather than change it totally, you can make use of the fact that 2 of the pairs of planes are parallel. Create only one normal for that pair of planes. You already have the test for the point being "in front" of one of the planes, but assuming you know the depth of the frustum, you can use the same distance to test the point against the other parallel face.
double distancePastFrontPlane = xNBR . Right_normal;
if (distancePastFrontPlane < 0 )
{
// point is in front of front plane
return false;
if(distancePastFrontPlane > depthFaceRtoFaceL)
{
// point is behind back plane
return false;
}
}
If you have multiple points to test against the same frustum you can benefit because you only calculate the frustum depth once (per pair of parallel planes).

Algorithm for finding number of squares in a given circle

Here is my drawing: CLICK
I need to write a program, that will find the number of squares(1x1), that we can draw into a circle of given radius.The squares can only by drawn fully and placed like lego blocks- one on another. In some cases, vertexes of squares can lie on the circle.
Examples: for 1- it makes 0, for 2- it gives four, for 3- 16 squares, for 4-32, for 5-52.
I have written something, but it doesn't work fine for 5+ (I mean- radius bigger than 5). Here it goes: CLICK. In my code- r is radius of the circle, sum is the sum of all squares and height is the height of triangles I try to "draw" into the circle (using Pythagorean theorem).
Now- any help? Is my algorithm even correct? Should I change something?
There is Gauss's Circle Problem that gives a formula to count integer points inside the circle of given radius. You may use this logic to count squares that lie in the circle.
N = 4 * Sum[i=1..R] (Floor(Sqrt((R^2-i^2)))
example:
R = 3
i=1 n1 = Floor(Sqrt(9-1))~Floor(2.8)=2
i=2 n2 = Floor(Sqrt(9-4))~Floor(2.2)=2
i=3 n2 = Floor(Sqrt(9-9))=0
N=4*(n1+n2+n3)=16
First off - circle with a radius of 5 fits 60 1x1 squares, not 52. My bet would be someone didn't count the points {[3,4],[3,-4],[4,3],[4,-3],[-4,3],[-4,-3],[-3,4],[-3,-4]} when drawing that on paper and counting by hand, being unsure whether they are right on the circle or just outside of it. They are exactly on the circle.
Second - MBo's answer brought me here - I sometimes search StackOverflow for Gauss Circle Problem to see if someone suggested some new, fun algorithm.
Third - here's the code:
int allSquares=0,
squaredRadius=radius*radius,
sideOfQuarterOfInscribedSquare=(int)(long)(radius/sqrt(2));
for(int x=sideOfQuarterOfInscribedSquare+1;
x<radius;
x++){
allSquares+=(long)sqrt(squaredRadius-x*x);
}
allSquares= allSquares*8+4*sideOfQuarterOfInscribedSquare*sideOfQuarterOfInscribedSquare;
return allSquares;
What it does is just count the squares inside one-eighth of the circle, outside an inscribed square. Sorry for my hipster formatting and overly verbose variable names.

Theory - How to Tell if Elements Overlap?

I have a question, and I don't want an implementation. I just want a bit of help in my reasoning.
I want to determine if two objects overlap (their x and y coordinates, as well as their height and width are stored in a vector) and then, if they do, remove them from their current vector and add them to another with combined properties.
My question is, generally, how do you tell when something overlaps? Obviously, they can have the same x and not overlap due to differing y's, or vice versa. I am thinking I need information about the width and height in addition to the location of the edge of the object, but I don't even know how to turn this into pseudo code at present.
Any help in helping me figure this out would be greatly appreciated!
EDIT: The objects are strictly rectangular, and the coordinates follow a pixel monitor convention. i.e. 0,0 is the upper left corner of the object, and an increase in x corresponds to going right, while an increase in y means going downwards.
Consider two rectangles R1 and R2.
Overlap in x:
if (R2.x < R1.x + R1.width) AND (R1.x < R2.x + R2.width)
Overlap in y
if (R2.y < R1.y + R1.height) AND (R1.y < R2.y + R2.height)
PS. Note that Im using a pseudolanguage
Maybe a picture will help. This is your coordinate system with two objects.
Two objects overlap on x axis if the distance between x1 and x2 is smaller than the width of the object that's closer to the x axis (w1 in the case on the picture).
pseudocode:
w = width of leftmost object
if ( abs (x1-x2) < w ) /* overlap on x axis */
You need to do the same for y axis. If both checks return true, the objects overlap.
A particularly bad (but intuitive) way of doing this is along this line of reasoning:
If two 2D rectangles overlap, then definitely some of the sides of one of them intersects some of the sides of the other. Actually, even if one of the line segments making up one of them intersects one of the line segments of the other, then the rectangles overlap.
So, you can just loop over their sides and check their intersection pair by pair. Finding code or ideas for line segment intersection shouldn't be hard at all.
Important note: you need to define for yourself whether sharing a side between the rectangles constitutes overlapping or not. If it doesn't, then you have to be extra careful in the implementation of the above method.
For axis-aligned rectangles (rectangles with sides parallel to the axes,) the solution is quite simpler:
Assume the two rectangles are named A and B, and assume and their 4 sides are named left (minimum X coordinate) , right (maximum X coordinate), top (minimum Y coordinate) and bottom (maximum Y coordinate.) Then I think you can say that they overlap if (and only if) any of these is true:
A.right is less than B.left (A is completely to the left of B)
A.left is greater than B.right (A is completely to the right of B)
A.bottom is less than B.top (A is completely above B)
A.top is greater than B.bottom (A is completely below of B)
In (somewhat) pseudo code, you can write:
if (A.right < B.left || A.left > B.right || A.bottom < B.top || A.top > B.bottom)
/* don't overlap */
or written in another (more symmetrical and maybe easier to understand) form:
if (A.right < B.left || B.right < A.left || A.bottom < B.top || B.bottom < A.top)
/* don't overlap */
Again note that rectangles with touching sides need to be handled with a little care.

Points on a circle, with limits. How To calculate without angle, but radius and centre point?

This is quite complicated to explain, so I will do my best, sorry if there is anything I missed out, let me know and I will rectify it.
My question is, I have been tasked to draw this shape,
(source: learnersdictionary.com)
This is to be done using C++ to write code that will calculate the points on this shape.
Important details.
User Input - Centre Point (X, Y), number of points to be shown, Font Size (influences radius)
Output - List of co-ordinates on the shape.
The overall aim once I have the points is to put them into a graph on Excel and it will hopefully draw it for me, at the user inputted size!
I know that the maximum Radius is 165mm and the minimum is 35mm. I have decided that my base Font Size shall be 20. I then did some thinking and came up with the equation.
Radius = (Chosen Font Size/20)*130. This is just an estimation, I realise it probably not right, but I thought it could work at least as a template.
I then decided that I should create two different circles, with two different centre points, then link them together to create the shape. I thought that the INSIDE line will have to have a larger Radius and a centre point further along the X-Axis (Y staying constant), as then it could cut into the outside line.
So I defined 2nd Centre point as (X+4, Y). (Again, just estimation, thought it doesn't really matter how far apart they are).
I then decided Radius 2 = (Chosen Font Size/20)*165 (max radius)
So, I have my 2 Radii, and two centre points.
Now to calculate the points on the circles, I am really struggling. I decided the best way to do it would be to create an increment (here is template)
for(int i=0; i<=n; i++) //where 'n' is users chosen number of points
{
//Equation for X point
//Equation for Y Point
cout<<"("<<X<<","<<Y<<")"<<endl;
}
Now, for the life of me, I cannot figure out an equation to calculate the points. I have found equations that involve angles, but as I do not have any, I'm struggling.
I am, in essence, trying to calculate Point 'P' here, except all the way round the circle.
(source: tutorvista.com)
Another point I am thinking may be a problem is imposing limits on the values calculated to only display the values that are on the shape.? Not sure how to chose limits exactly other than to make the outside line a full Half Circle so I have a maximum radius?
So. Does anyone have any hints/tips/links they can share with me on how to proceed exactly?
Thanks again, any problems with the question, sorry will do my best to rectify if you let me know.
Cheers
UPDATE;
R1 = (Font/20)*130;
R2 = (Font/20)*165;
for(X1=0; X1<=n; X1++)
{
Y1 = ((2*Y)+(pow(((4*((pow((X1-X), 2)))+(pow(R1, 2)))), 0.5)))/2;
Y2 = ((2*Y)-(pow(((4*((pow((X1-X), 2)))+(pow(R1, 2)))), 0.5)))/2;
cout<<"("<<X1<<","<<Y1<<")";
cout<<"("<<X1<<","<<Y2<<")";
}
Opinion?
As per Code-Guru's comments on the question, the inner circle looks more like a half circle than the outer. Use the equation in Code-Guru's answer to calculate the points for the inner circle. Then, have a look at this question for how to calculate the radius of a circle which intersects your circle, given the distance (which you can set arbitrarily) and the points of intersection (which you know, because it's a half circle). From this you can draw the outer arc for any given distance, and all you need to do is vary the distance until you produce a shape that you're happy with.
This question may help you to apply Code-Guru's equation.
The equation of a circle is
(x - h)^2 + (y - k)^2 = r^2
With a little bit of algebra, you can iterate x over the range from h to h+r incrementing by some appropriate delta and calculate the two corresponding values of y. This will draw a complete circle.
The next step is to find the x-coordinate for the intersection of the two circles (assuming that the moon shape is defined by two appropriate circles). Again, some algebra and a pencil and paper will help.
More details:
To draw a circle without using polar coordinates and trig, you can do something like this:
for x in h-r to h+r increment by delta
calculate both y coordinates
To calculate the y-coordinates, you need to solve the equation of a circle for y. The easiest way to do this is to transform it into a quadratic equation of the form A*y^2+B*y+C=0 and use the quadratic equation:
(x - h)^2 + (y - k)^2 = r^2
(x - h)^2 + (y - k)^2 - r^2 = 0
(y^2 - 2*k*y + k^2) + (x - h)^2 - r^2 = 0
y^2 - 2*k*y + (k^2 + (x - h)^2 - r^2) = 0
So we have
A = 1
B = -2*k
C = k^2 + (x - h)^2 - r^2
Now plug these into the quadratic equation and chug out the two y-values for each x value in the for loop. (Most likely, you will want to do the calculations in a separate function -- or functions.)
As you can see this is pretty messy. Doing this with trigonometry and angles will be much cleaner.
More thoughts:
Even though there are no angles in the user input described in the question, there is no intrinsic reason why you cannot use them during calculations (unless you have a specific requirement otherwise, say because your teacher told you not to). With that said, using polar coordinates makes this much easier. For a complete circle you can do something like this:
for theta = 0 to 2*PI increment by delta
x = r * cos(theta)
y = r * sin(theta)
To draw an arc, rather than a full circle, you simply change the limits for theta in the for loop. For example, the left-half of the circle goes from PI/2 to 3*PI/2.