Algorithm for finding number of squares in a given circle - c++

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.

Related

Point inside rectangle given sides and center

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.

Counting integer points inside a sphere of radius R and dimension D

I am trying to write an efficient algorithm that counts the number of points inside a Sphere of Radius R and Dimension D. The sphere is always at the origin. Suppose we have a sphere of dimension 2 (circle) with radius 5.
My strategy is to generate all possible points within the first quadrant, so for the above example we know that (1,2) is in the circle, so must all + / - combinations of that point which is simply dimension squared. So for each point found in a single quadrant of an n-dimensional sphere we add 2 ^ dimension to the total count.
I'm not sure if there is a much more efficient solution to this problem but this is what I have so far in terms of implementation.
int count_lattice_points(const double radius, const int dimension) {
int R = static_cast<int>(radius);
int count = 0;
std::vector<int> points;
std::vector<int> point;
for(int i = 0; i <= R; i++)
points.push_back(i);
do {
for(int i = 0; i < dimension - 1; i++)
point.push_back(points.at(i));
if(isPointWithinSphere(point, radius)) count += std::pow(2,dimension);
point.clear();
}while(std::next_permutation(points.begin(), points.end()));
return count + 3;
}
What can I fix or improve in this situation ?
For 2D case this is Gauss's circle problem. One possible formula:
N(r) = 1 + 4 * r + 4 * Sum[i=1..r]{Floor(Sqrt(r^2-i^2))}
(central point + four quadrants, 4*r for points at the axis, others for in-quadrant region).
Note that there is no known simple closed math expression for 2D case.
In general your idea with quadrants, octants etc is right, but checking all the points is too expensive.
One might find the number of ways to compose all squares from 0 to r^2 from 1..D
integer squares (extension of (4) formula).
Note that combinatorics would help to make calculation faster. For example, it is enough to find the number of ways to
make X^2 from D natural squares, and multiply by 2^D (different sign combinations); find the number of ways to make X^2 from D-1 natural squares, and multiply by D*2^(D-1) (different sign combinations + D places for zero addend) etc
Example for D=2, R=3
addends: 0,1,4,9
possible sum compositions number of variants
0 0+0 1
1 0+1,1+0 2*2=4
2 1+1 4
4 0+4,4+0 2*2=4
5 1+4,4+1 2*4=8
8 4+4 4
9 0+9,9+0 2*2=4
-------------------------------------
29
I presented my algorithm for 2D here (with some source code and an ugly but handy illustration):
https://stackoverflow.com/a/42373448/5298879
It's around 3.4x faster than MBo's counting points between the origin and the edge of the circle in one of the quarters.
You just imagine an inscribed square and count only one-eighth of what's outside that square inside that circle.
public static int gaussCircleProblem(int radius) {
int allPoints=0; //holds the sum of points
double y=0; //will hold the precise y coordinate of a point on the circle edge for a given x coordinate.
long inscribedSquare=(long) Math.sqrt(radius*radius/2); //the length of the side of an inscribed square in the upper right quarter of the circle
int x=(int)inscribedSquare; //will hold x coordinate - starts on the edge of the inscribed square
while(x<=radius){
allPoints+=(long) y; //returns floor of y, which is initially 0
x++; //because we need to start behind the inscribed square and move outwards from there
y=Math.sqrt(radius*radius-x*x); // Pythagorean equation - returns how many points there are vertically between the X axis and the edge of the circle for given x
}
allPoints*=8; //because we were counting points in the right half of the upper right corner of that circle, so we had just one-eightth
allPoints+=(4*inscribedSquare*inscribedSquare); //how many points there are in the inscribed square
allPoints+=(4*radius+1); //the loop and the inscribed square calculations did not touch the points on the axis and in the center
return allPoints;
}
An approach similar to that described by MBo, including source code, can be found at
https://monsiterdex.wordpress.com/2013/04/05/integer-lattice-in-n-dimensional-sphere-count-of-points-with-integer-coordinates-using-parallel-programming-part-i/.
The approach consists in finding partitions of the radius, and then for each partition in the sphere compute the number of ways it can be represented in the sphere by both permuting coordinates and flipping the signs of nonzero coordinates.

CGAL Intersection Circle and Vertical Lines (not segments)

In CGAL I need to compute the exact intersection points between a set of lines and a set o circles. Starting from the circles (which can have irrational radius but rational squared_radius) I should compute the vertical line passing through the x_extremal_points of each circle (not segment but lines) and calculate the intersection point of each circle with each line.
I’m using CircularKernel and Circle_2 for the circles and Line_2 for the lines.
Here’s an example of how I compute the circles and the lines and how I check if they intersect.
int main()
{
Point_2 a = Point_2(250.5, 98.5);
Point_2 b = Point_2(156, 139);
//Radius is half distance ab
Circular_k::FT aRad = CGAL::squared_distance(a, b);
Circle_2 circle_a = Circle_2(a, aRad/4);
Circular_arc_point_2 a_left_point = CGAL::x_extremal_point(circle_a, false);
Circular_arc_point_2 a_right_point = CGAL::x_extremal_point(circle_a, true);
//for example use only left extremal point of circle a
CGAL::Bbox_2 a_left_point_bb = a_left_point.bbox();
Line_2 a_left_line = Line_2(Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymin()),
Point_2(a_left_point_bb.xmin(), a_left_point_bb.ymax()));
if ( do_intersect(a_left_line, circle_a) ) {
std::cout << "intersect";
}
else {
std::cout << " do not intersect ";
}
return 0;
}
This flow rises this exception:
CGAL error: precondition violation!
Expression : y != 0
File : c:\dev\cgal-4.7\include\cgal\gmp\gmpq_type.h
Line : 371
Explanation:
Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html
I can’t figure out how I can calculate the intersection points.
Also, Is there a better way to compute the lines? I know abot the x_extremal_point function but it returns the Circular_arc_point point and I’m not able to construct a vertical line passing through them directly without using Bounding box.
In your code, you seem to compute the intersection of a circle with the vertical line that passes through the extremal point of the circle (I forget the bounding box). Well, then the (double) intersection is the extremal point itself...
More globally, you say in your text of introduction that you want to compute exact intersections. Then you should certainly not use bounding boxes, which by definition introduce some approximation.
If I understand your text correctly,
* for testing the intersection of your vertical lines with the other circles, you don't need to construct the lines, you only need to compare the abscissae of the extremal points of two circles, which you can do with the CGAL circular kernel.
* for computing the intersection of a vertical line that has non-rational coefficients (since its equation is of the form x= +-sqrt(r)) with another circle, then the CGAL circular kernel will not give you a pre-cooked solution. That kernel will help, but you must still compute a few things by hand.
If you don't want to bother, then you can also just take a standard CGAL kernel with Core::Expr as underlying number type. It can do "anything", but it will be slower.
For efficiency, you should look at the underlying 1D problem: projecting the lines and the circle on the X axis, you have a set of points and a set of intervals [Xc-R, Xc+R].
If the L points are sorted increasingly, you can locate the left bound of an interval in time Lg(L) by dichotomy, and scan the list of points until the right bound. This results in a O(Lg(L).C + I) behavior (C circle intervals), where I is the number of intersections reported.
I guess that with a merge-like process using an active list, if the interval bounds are also sorted you can lower to O(L + C + I).
The extension to 2D is elementary.

Number of Sides Required to draw a circle in OpenGL

Does anyone know some algorithm to calculate the number of sides required to approximate a circle using polygon, if radius, r of the circle and maximum departure of the polygon from circularity, D is given? I really need to find the number of sides as I need to draw the approximated circle in OpenGL.
Also, we have the resolution of the screen in NDC coordinates per pixel given by P and solving D = P/2, we could guarantee that our circle is within half-pixel of accuracy.
What you're describing here is effectively a quality factor, which often goes hand-in-hand with error estimates.
A common way we handle this is to calculate the error for a a small portion of the circumference of the circle. The most trivial is to determine the difference in arc length of a slice of the circle, compared to a line segment joining the same two points on the circumference. You could use more effective measures, like difference in area, radius, etc, but this method should be adequate.
Think of an octagon, circumscribed with a perfect circle. In this case, the error is the difference in length of the line between two adjacent points on the octagon, and the arc length of the circle joining those two points.
The arc length is easy enough to calculate: PI * r * theta, where r is your radius, and theta is the angle, in radians, between the two points, assuming you draw lines from each of these points to the center of the circle/polygon. For a closed polygon with n sides, the angle is just (2*PI/n) radians. Let the arc length corresponding to this value of n be equal to A, ie A=2*PI*r/n.
The line length between the two points is easily calculated. Just divide your circle into n isosceles triangles, and each of those into two right-triangles. You know the angle in each right triangle is theta/2 = (2*PI/n)/2 = (PI/n), and the hypotenuse is r. So, you get your equation of sin(PI/n)=x/r, where x is half the length of the line segment joining two adjacent points on your circumscribed polygon. Let this value be B (ie: B=2x, so B=2*r*sin(PI/n)).
Now, just calculate the relative error, E = |A-B| / A (ie: |TrueValue-ApproxValue|/|TrueValue|), and you get a nice little percentage, represented in decimal, of your error vector. You can use the above equations to set a constraint on E (ie: it cannot be greater than some value, say, 1.05), in order for it to "look good".
So, you could write a function that calculates A, B, and E from the above equations, and loop through values of n, and have it stop looping when the calculated value of E is less than your threshold.
I would say that you need to set the number of sides depending on two variables the radius and the zoom (if you allow zoom)
A circle or radius 20 pixels can look ok with 32 to 56 sides, but if you use the same number of sided for a radios of 200 pixels that number of sides will not be enough
numberOfSides = radius * 3
If you allow zoom in and out you will need to do something like this
numberOfSides = radiusOfPaintedCircle * 3
When you zoom in radiusOfPaintedCircle will be bigger that the "property" of the circle being drawn
I've got an algorithm to draw a circle using fixed function opengl, maybe it'll help?
It's hard to know what you mean when you say you want to "approximate a circle using polygon"
You'll notice in my algorithm below that I don't calculate the number of lines needed to draw the circle, I just iterate between 0 .. 2Pi, stepping the angle by 0.1 each time, drawing a line with glVertex2f to that point on the circle, from the previous point.
void Circle::Render()
{
glLoadIdentity();
glPushMatrix();
glBegin(GL_LINES);
glColor3f(_vColour._x, _vColour._y, _vColour._z);
glVertex3f(_State._position._x, _State._position._y, 0);
glVertex3f(
(_State._position._x + (sinf(_State._angle)*_rRadius)),
(_State._position._y + (cosf(_State._angle)*_rRadius)),
0
);
glEnd();
glTranslatef(_State._position._x, _State._position._y, 0);
glBegin(GL_LINE_LOOP);
glColor3f(_vColour._x, _vColour._y, _vColour._z);
for(float angle = 0.0f; angle < g_k2Pi; angle += 0.1f)
glVertex2f(sinf(angle)*_rRadius, cosf(angle)*_rRadius);
glEnd();
glPopMatrix();
}

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.