I have a 2-D array of squares (square shape), Each square has 50 units length and x, y co-ordinates. The distance between the squares is 5 units. The x, y co-ordinates are the bottom left corner of the square. Now, given any point(x,y co-ordinates) how can i find the closest square to this point.
square **sq = new square*[10];
for(int i=0;i<10;++i){
sq[i]=new square[10];
}
int m=0, n=0;
for(int i=0;i<10;++i){
m=0;
for(int j=0;j<10;++j){
sq[i][j].setCoOrdinates(m,n);
m+=55;
}
n+=55;
}
// Given a point (x, y) how can i find the index (i, j) of closest square to this point.
Let's rigorously define the definition of distance from a square to a point: "The minimum of all lengths from the point (x,y) to some point within the rectangle".
This gives some clear rules for defining the distance to a rectangle. For any rectangle, if the point(x,y) is directly above, below, to the left of, or to the right of the sides of the rectangle, the minimum distance to the rectangle is the straight line drawn either vertically or horizontally through the point. For instance, if your point is (40, 90) and your rectangle's bottom-left is (0,0) (and it is a 50x50 square), you can draw a vertical line through your point and the distance is min(90-(0+50), 90-0)
If the point is not directly above, below, left of, or right of the sides of the square, then the closest distance is to the closest of the four corners. You can simply take the min of all the distances to the four corners, which can be found by using the distance formula.
Simply apply this logic to each of your squares in your array and you should be good to go! Time O(NM) where n is the number of rows of squares and M is the number of columns of squares. In other words, O(number of squares you have). Space O(1).
Lets start with the simpler problem: All rectangles are 55 units wide, ie there is no empty space between them...
The best container is the one that you do not need. There is a simple relation between i and j index of a square in the array and its m and n coordinates:
const int distance = 55;
int m(int i) { return i*distance; }
int n(int j) { return m(j); }
As the relation is linear, you can invert it:
int i(int m) { return m / distance; }
int j(int n) { return i(n); }
Using integer arithmetics is fine here, because we get the same result as if we had used floating points and then rounded down.
This is already the full solution for the simpler problem. Given coordinats m and n the closest square is at index i(m),j(n).
Now lets introduce the gap:
cosnt int width = 50;
const int gap = 5;
Now we have to distinguish two possibilities: The given coordinats are inside a square or outside. When it is outside there are two candidates for the cloest square.
int i_with_gap(int m) {
int i = m / distance;
// point is inside the square?
if (m % distance <= width) return i;
// point is closer to square at index i?
if (m % distance <= width+ gap/2.0) return i;
// otherwise i+1 is closer
return i+1;
}
Related
I want to iterate over pixels along a rasterized circular arc, given its radius, start and end angles in radians, eg:
template<typename Functor>
void arc(float startRadians, float endRadians, int radius, Functor f);
To be used like:
arc(0.f, M_PI, 10, [](int x, int y) {
std::cout << "got: " << x << " " << y << "\n";
});
There's a few catches:
pixels have integer coordinates
radius is also given as an integer
the rasterised arc is effectively every pixel in a sector between the arc of radius radius and the arc of radius radius-1
In the picture below:
blue pixels have been visited, red pixel is the next to be visited
the arc is confined by the two radial lines defined by start/end angles, and the sector between the two arcs radius, radius-1.
finally, if every arc with radius 0 to 100 were to be drawn, angles 0 to 2*PI, then we'd get a filled disc/circle of radius 100 and no pixel would be visited twice.
I think Bresenham's circle algorithm doesn't directly apply to this problem, because of the angle constraints and visitation order.
In stackoverflow, I believe this is the most closely related question:
Iterate over 2d array in an expanding circular spiral
Finally, OpenCV has something similar/related in spirit, but only for lines:
https://docs.opencv.org/3.0-beta/modules/imgproc/doc/drawing_functions.html#lineiterator
Take a look at cvLinearPolar().
It maps the image from the x,y coordinate system, to polar. The resulting image is rows -> angle and columns-> radius. Your rastering at that point would be looping row column order no special functional rastering.
This means every rows is dtheta = 2*Pi/(rowNum) therefore your arc would
be startAngle = angle1/dtheta and likewise endAngle = angle2/dtheta.
Similarly your radius calculation drad = maxRad/(columnNum).
so to get your arc from the polar image:
for(int i = maxRad; i > 0; i--) // start at longest radius spiral in
{
for(int j = startAngle; j < endAngle;j++) angle
{
// do action on polarImage[i,j];
}
}
I wanted to draw a circle using graphics.h in C++, but not directly using the circle() function. The circle I want to draw uses smaller circles as it's points i.e. The smaller circles would constitute the circumference of the larger circle. So I thought, if I did something like this, it would work:
{
int radius = 4;
// Points at which smaller circles would be drawn
int x, y;
int maxx = getmaxx();
int maxy = getmaxy();
// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;
//Cartesian cirle formula >> (X-h)^2 + (Y-k)^2 = radius^2
//Effectively, this nested loop goes through every single coordinate on the screen
int gmode = DETECT;
int gdriver;
initgraph(&gmode, &gdriver, "");
for(x = 0; x<maxx; x++)
{
for(y = 0; y<maxy; y++)
{
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
circle(x, y, 5) //Draw smaller circle with radius 5
} //at points which satisfy circle equation only!
}
}
getch();
}
This is when I'm using graphics.h on Turbo C++ as this is the compiler we're learning with at school.
I know it's ancient.
So, theoretically, since the nested for loops check all the points on the screen, and draw a small circle at every point that satisfies the circle equation only, I thought I would get a large circle of radius as entered, whose circumference constitutes of the smaller circles I make in the for loop.
However, when I try the program, I get four hyperbolas (all pointing towards the center of the screen) and when I increase the radius, the pointiness (for lack of a better word) of the hyperbolas increase, until finally, when the radius is 256 or more, the two hyperbolas on the top and bottom intersect to make a large cross on my screen like : "That's it, user, I give up!"
I came to the value 256 as I noticed that of the radius was a multiple of 4 the figures looked ... better?
I looked around for a solution for quite some time, but couldn't get any answers, so here I am.
Any suggestions???
EDIT >> Here's a rough diagram of the output I got...
There are two issues in your code:
First: You should really call initgraph before you call getmaxx and getmaxy, otherwise they will not necessarily return the correct dimensions of the graphics mode. This may or may not be a contributing factor depending on your setup.
Second, and most importantly: In Turbo C++, int is 16-bit. For example, here is circle with radius 100 (after the previous initgraph order issue was fixed):
Note the stray circles in the four corners. If we do a little debugging and add some print-outs (a useful strategy that you should file away for future reference):
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
printf(": (%d-%d)^2 + (%d-%d)^2 = %d^2\n", x, h, y, k, radius);
circle(x, y, 5); //Draw smaller circle with radius
} //at points which satisfy circle equation only!
You can see what's happening (first line is maxx and maxy, not shown in above snippet):
In particular that circle at (63, 139) is one of the corners. If you do the math, you see that:
(63 - 319)2 + (139 - 239)2 = 75536
And since your ints are 16-bit, 75536 modulo 65536 = 10000 = the value that ends up being calculated = 1002 = a circle where it shouldn't be.
An easy solution to this is to just change the relevant variables to long:
maxx, maxy
x, y
h, k
So:
long x, y;
...
initgraph(...);
...
long maxx = getmaxx();
long maxy = getmaxy();
...
long h = maxx / 2;
long k = maxy / 2;
And then you'll end up with correct output:
Note of course that like other answers point out, since you are using ints, you'll miss a lot of points. This may or may not be OK, but some values will produce noticeably poorer results (e.g. radius 256 only seems to have 4 integer solutions). You could introduce a tolerance if you want. You could also use a more direct approach but that might defeat the purpose of your exercise with the Cartesian circle formula. If you're into this sort of thing, here is a 24-page document containing a bunch of discussion, proofs, and properties about integers that are the sum of two squares.
I don't know enough about Turbo C++ to know if you can make it use 32-bit ints, I'll leave that as an exercise to you.
First of all, maxx and maxy are integers, which you initialize using some functions representing the borders of the screen and then later you use them as functions. Just remove the paranthesis:
// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;
Then, you are checking for exact equality to check whether a point is on a circle. Since the screen is a grid of pixels, many of your points will be missed. You need to add a tolerance, a maximum distance between the point you check and the actual circle. So change this line:
if(((x-h)*(x-h)) + ((y-k)*(y-k)) == radius*radius)
to this:
if(abs(((x-h)*(x-h)) + ((y-k)*(y-k)) - radius*radius) < 2)
Introduction of some level of tolerance will solve the problem.
But it is not wise to check all the points in graphical window. Would you change an approach? You can draw needed small circles without checks at all:
To fill all big circle circumference (with RBig radius), you need NCircles small circles with RSmall radius
NCircles = round to integer (Pi / ArcSin(RSmall / RBig));
Center of i-th small circle is at position
cx = mx + Round(RBig * Cos(i * 2 * Pi / N));
cy = my + Round(RBig * Sin(i * 2 * Pi / N));
where mx, my - center of the big circle
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.
Given a set of integral coordinates, check whether all the points given lie on side of a possible square such that axis of the square so formed lie parallel to both X-axis and Y-axis. If such a square is possible give the minimum possible side of the square.
Suppose points are (0,0), (1,1), (2,2).
Answer : square is not possible .
Suppose points are (0,0), (0,2), (0,5), (0,7), `(3,0).
Answer : square is possible and minimum length of the side is 7.
I tried it and came up with many corner cases and it seemed impossible to tackle them individually. I was wondering if anyone can give a more generalized approach towards this kind of problem and how to think in the right direction.
Thanks in advance.
Range of coordinates: -1000 <= x ,y <= 1000
The number of points is <= 50.
New edit :
One more corner case :
(2,0) , (0,4) , (1,5) , (5,3)
Answer : Square is possible with length 5 . Corner points of the square are (0,0) , (0,5) ,(5,5) ,(5,0)
If you define the square through xmin, xmax, ymin and ymax, then all points must lie on one of these coordinates. I.e. the square is valid, if for all vertices v:
v.x == xmin || v.x == xmax || v.y == ymin || v.y == ymax
Candidates for the bounds are the points' bounding rectangle's bounds. If you compute these boundaries, maintain a list of vertices for each edge.
If you can't assign every vertex to an edge, it is not possible to create the square.
Now it is very likely that the rectangle is not a square. So we need to enlarge its shortest side. If we have chosen the side, we need to choose whether to move the min or max edge. That's where the list of associated vertices comes into play. For the edge to move check whether all associated vertices are also associated with another edge. Then it is safe to move this edge. If we can move neither the min nor the max edge, it is impossible to create the square.
The resulting minimal side length is the distance of the edges.
I'm trying to think of a way to do this in a single pass, but it's late at night here and I'm tired, so...
Run through all the elements once and record the minimum and maximum x and y values of the whole set. The side length of the square (if it exists) will be max(xmax-xmin, ymax-ymin).
Run through the points again. To describe a square parallel to the axes, each point must have
x == xmin || x == xmax || y == ymin || y == ymax,
that is, at least one coordinate must be on the side of the square. If any point fails, then you don't have a square.
I'm pretty sure this is sufficient, but doing it in two steps seems less than optimal. This is an interesting problem though, good luck.
The requirement of the axis helps us make following observations
Every such square is bounded by two parallel vertical lines and every point on that vertical line has same X-coordinate. Let's call those coordinates maxX and minX. (One of them is smaller than other)
Every such square is bounded by two parallel horizontal lines and every point on that vertical line has same Y-coordinate. Let's call those coordinates maxY and minY.
This is crucial: Every point in input list must have a X-coordinate matching maxX or minX OR a Y-coordinate matching maxY or minY. (Notice the OR. If there is a point that matches neither, like (1, 1) in your earlier example, you have a counterexample).
Here is a c++-like pseudocode to compute these quantities. Assume you have an appropriate Point structure.
bool isSquare(vector<Point> points) {
double maxX = points[0].X;
double minX = points[0].X;
double maxY = points[0].Y;
double minY = points[0].Y;
// set maxX, minX, maxY, minY
for(int i = 0; i < points.size(); i++) {
maxX = max(points[i].X, maxX);
minX = min(points[i].X, minX);
maxY = max(points[i].Y, maxY);
minY = min(points[i].Y, minY);
}
// Finally, find a point which matches neither {maxX, minX, maxY, minY}
for(int i = 0; i < points.size(); i++) {
if (points[i].X != maxX && points[i].X != minX && points[i].Y != maxY && points[i].Y != minY) return false;
}
// We are not done yet!
}
Now passing the check in this code makes sure that the points at least form a rectangle and there is no point inside the rectangle. Making sure that the rectangle is a square is the harder part. For that part, you must check that:
A point is on the corner of the rectangle., i.e., both its X-coordinate matches {maxX, minX} AND its Y-coordinate matches {maxY, minY}. If found, you then need to find the largest distance of such point from any other point on the corresponding edges.
If no such corner exists, you are much better off!. In that case, length of the square-side is simply max(maxX-minX, maxY-minY).
You need to be careful while writing pseudocode for this corner-finding part and consider all cases. But I think once done, this would ultimately give the answer.
You can tackle this with the common concept of Axis Aligned Bounding Box (ABB). Given a set of points, compute ABB:
Loop once through all points and find minimum x, minimum y, maximum x and maximum y. Then the box defined by two corners, lower left corner (min_x,min_y) and upper right corner (max, max y) will need to be checked against all the points to see if they lie on its perimeter. Since coordinates are integral (no floating point errors) its fairly easy to do: for each point, either the x-coordinate or the y-coordinate must match with the corresponding coordinates of the AAB, and the other coordinate has to be within range of the other coordinates. Hope that makes sense.
I have two of these:
bool isPointOnShape(int a, int b)
{
}
bool isPointInShape(int a, int b)
{
}
Say I have a square, first point (bottom left corner) is x,y (0,0) second point (top left) is (0,2), third is (2,2) and fourth is (0,2).
The Points on shape would be (0,1) (1,2) (2,1) (1,0) and Points in shape is (1,1)
How do I find out the points on shape / in shape and return a true value so that I can store it somewhere?
I'll offer a general solution for any shape that can be divided in straight segments.
So, as you may have guessed, I'll start by consider your "shape" as a list of segments that completes a loop. Or simply put a circular list of points that represents a loop, for example, your square would be this list of points:
0, 0
0, 2
2, 2
2, 0
Note that we consider that there are segments from each point to the next and that the final point connects to the first. Also, we require that no consecutive points are equal, nor the first and last. If there are any, those must be removed before proceeding.
Now, for each segment we can determinate the bounding box. For example given this segment:
a = (0, 2)
b = (2, 2)
Then the range of values in x is [0, 2] and in y is [2, 2] and that is your bounding box for that segment.
The next thing you need is the director vector of the line of the segment. To get that, first calculate the length of the segment:
length = sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y))
And then:
director.x = (a.x - b.x)/length
director.y = (a.y - b.y)/length
Note 1: when then length is 0, then you have an invalid segment. That's why we don't want repeated points.
Note 2: Using the director vector instead of using the equation of the line will make things easier.
Now, given a point p, you can determinate if that point is in a segment (if it is one of the points in the list). For the rest of cases we start by looking if it is inside of the axis aligned bounding box. This is done simply by checking the range:
if
(
(p.x >= box.left && p.x <= box.right) &&
(p.y >= box.top && p.y <= box.bottom) // with origin at the top-left corner
)
{
//It is inside of the bounding box
}
And if it is, then we calculate the distance from the point to the line, if it is
0 then it is on the line. Now, because of floating point arithmetics, you could test if the distance is less or equal to epsilon, where epsilon is a very small number.
We use this formula:
distance vector = (a - p) - ((a - p) · director) * director
distance = the norm of distance vector
Where "·" denotes a dot product and "*" denotes an scalar product.
All that rests is to iterate over the segments, for each one calculate the distance and if for anyone the distance is less than epsilon then the point is "on the shape".
Ok, but what about "in the shape"?
Well, with a little help of a trick from topology we can determinate if a point is inside or not. This is the same algorithm Windows would use to fill a polygon or polyline (such as deciding what is inside a selected area with free hand in Microsoft Paint).
It goes like this:
Count the number of segments you have to cross to get to the point from outside. If the number is pair, then it is outside, if it is odd then inside.
You can choose from what direction to reach the point. I choose left.
Once more, you are going to iterate over the segments. For each one we need to decide if it is at the vertical range. For that use the bounding box:
if ((p.y >= box.top && p.y <= box.bottom))
{
//In the vertical range
}
Now, determinate if the segment is at left, or right:
if (p.x < box.left)
{
//The segment is at the left
}
else if (p.x > box.right)
{
//The segment is at the right
}
else
{
//The segment is close, need further calculation
}
In the case that the segment is close we need to calculate the vector distance to that segment and check it's direction.
The vector distance? Well, we already have it, we are taking its norm to determinate the distance. Now, instead of taking the norm, verify the sign of the x coordinate. If it is less than 0, it is right, if it is more than 0 then it is left. If it is 0... it means that the segment is horizontal (because the distance vector is always perpendicular to the segment), you can skip that segment*.
*: In fact, if the segment is horizontal and it is in vertical range, it means that it is at the segment. Are segments "in shape" or not?
Now, you need to count the number of segments at the left, and if it odd, the point is inside the shape. It is out otherwise. This can also be done with the segments that are up, or right, or below. I just picked left.
For large shapes where iterating over all the segments is expensive, you can store the segments in some space partitioning data structure. That is beyond the scope of this post.
If I suppose you have a Rectangle class and that this class has members bottomLeft and topRight, you can write something like this:
bool Rectangle::isPointOnShape(int x, int y) {
if (x == bottomLeft.x || x == topRight.x)
if (y > bottomLeft.y && y < topRight.y)
return true;
if (y == bottomLeft.y || y == topRight.y)
if (x > bottomLeft.x && x < topRight.x)
return true;
}
bool Rectangle::isPointInShape(int x, int y) {
bool inX = false;
bool inY = false;
if (x > bottomLeft.x && x < topRight.x)
inX = true;
if (y > bottomLeft.y && y < topRight.y)
inY = true;
return (inX && inY);
}
If your shape is not a rectangle, this functions will be different of course.