I am attempting to translate the C++ code given here to MATLAB:
// Implementation of Andrew's monotone chain 2D convex hull algorithm.
// Asymptotic complexity: O(n log n).
// Practical performance: 0.5-1.0 seconds for n=1000000 on a 1GHz machine.
#include <algorithm>
#include <vector>
using namespace std;
typedef int coord_t; // coordinate type
typedef long long coord2_t; // must be big enough to hold 2*max(|coordinate|)^2
struct Point {
coord_t x, y;
bool operator <(const Point &p) const {
return x < p.x || (x == p.x && y < p.y);
}
};
// 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
// Returns a positive value, if OAB makes a counter-clockwise turn,
// negative for clockwise turn, and zero if the points are collinear.
coord2_t cross(const Point &O, const Point &A, const Point &B)
{
return (A.x - O.x) * (B.y - O.y) - (A.y - O.y) * (B.x - O.x);
}
// Returns a list of points on the convex hull in counter-clockwise order.
// Note: the last point in the returned list is the same as the first one.
vector<Point> convex_hull(vector<Point> P)
{
int n = P.size(), k = 0;
vector<Point> H(2*n);
// Sort points lexicographically
sort(P.begin(), P.end());
// Build lower hull
for (int i = 0; i < n; i++) {
while (k >= 2 && cross(H[k-2], H[k-1], P[i]) <= 0) k--;
H[k++] = P[i];
}
// Build upper hull
for (int i = n-2, t = k+1; i >= 0; i--) {
while (k >= t && cross(H[k-2], H[k-1], P[i]) <= 0) k--;
H[k++] = P[i];
}
H.resize(k);
return H;
}
I am having some trouble because in the C++ program, iterating through the points is easier. I wish to do the same in MATLAB but want to do that taking one point (both x and y coordinates) at a time instead of one particular value at a given index at a time.
To generate the matrix of coordinates I am using the following as of now -
x = randi(1000,100,1);
y = randi(1000,100,1);
points = [x,y];
Iteration is often unnecessary in Matlab. Given your vectors x and y I think that the C++ code translates to
convhull(x,y)
in Matlab. No (programmer-written) iteration, not much else either.
If you have a matrix C columns by 2 rows M, you just do. (where row1 =x and row2 = y)
M=[x;y]
FOR point = drange(M)
//code
end
Related
The concrete question is:
n lines, each line containing two integers. The i-th line contains xi, yi — the i-th vertex of the polygon in clockwise or counterclockwise order. Note that it is possible that more than two vertices appear in a side, such as the follow picture:
Now you need to judge that the vertices's order of polygon is clockwise or counterclockwise?
c++ code is:
struct Node
{
int x, y;
Node operator-(Node node) const
{
Node t;
t.x = x - node.x;
t.y = y - node.y;
return t;
}
int operator*(Node node) const // I konow this is Cross-Product
{
return x * node.y - y * node.x;
}
}node[1000];
for (int i = 0; i < n; i++)
scanf("%d %d", &node[i].x, &node[i].y);
int tmp = 0;
node[n].x = node[0].x, node[n].y = node[0].y;
for (int i = 0; i < n; i++)
tmp += (node[i] * node[i + 1]);
if (tmp > 0)
it is counterclockwise order;
But I don't understand the code, who can prove it?
The shoelace formula will give the oriented area of any polygon. By examining its sign, you can therefore determine the orientation. The code you have does compute twice the area, but as the sign is all that matters, this is irrelevant.
This program should read for input an integer N then the x and y coordinates of the N points
and return the number of points that are the middle points of any two other points in the set.
First the program stores the points in an array then we loop throgh the points and calculate the distance between points[i] and every other point. We sort the points according to that distance then if we find that any two points have the same distance we check if point[i] is aligned with them if it is the case we store point[i] in the middles list.
We then get rid of doubles in the list and return the size of the list.
I submitted my solution and it doesn't work for all the cases. Please help:
#include <iostream>
#include <cmath>
#include <algorithm>
#include <list>
#include <stdio.h>
using namespace std;
struct Point
{
int x;
int y;
int distance;
};
bool PointSort(Point a,Point b);
bool colinear(Point a,Point b,Point c);
bool same_point (Point first, Point second);
int main()
{
list<Point> middles;
int N;scanf("%d", &N);
Point points[N];
Point points2[N];
for(int i=0;i<N;i++)
{ scanf("%d", &points[i].x);
scanf("%d", &points[i].y);
points2[i].x=points[i].x;
points2[i].y=points[i].y;
}
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
points2[j]=points[j];
}
for(int j=0;j<N;j++)
{
points2[j].distance=(points[i].x-points2[j].x)*(points[i].x- points2[j].x)+(points[i].y-points2[j].y)*(points[i].y-points2[j].y);
}
sort(points2,points2+N,&PointSort);
for(int j=0;j<N;j++)
{
int k=j+1;
while(points2[j].distance==points2[k].distance)
{
bool coli=colinear(points[i],points2[j],points2[k]);
if(coli){middles.push_back(points2[i]);}
k++;
}
}
}
middles.unique(same_point);
cout<<middles.size();
}
bool PointSort(Point a,Point b)
{
return a.distance<b.distance;
}
bool colinear(Point a,Point b,Point c)
{
return (a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y))/2.0==0.0;
}
bool same_point (Point first, Point second)
{ return (first.x==second.x && first.y==second.y) ; }
You actually don't need to calculate distances to check if something is the midpoint. The coordinates of the midpoint between A and B is M=(A+B)/2. Or, to keep everything as an integer, A+B=2M where M is the midpoint. Here's a pseudocode solution for the problem:
for ( A=0; A<N-1; A++ ) {
for ( B=A+1; B<N; B++ ) {
M2 = A+B;
for ( C=0; C<N; C++ ) {
if ( C*2 == M2 ) {
// C is the midpoint of A and B
}
}
}
}
I see the following potential problems with your code:
Your code computes the distance squared (not the distance as stated) between pairs of points. Since the calculation is being done using integer arithmetic, there's a chance of arithmetic overflow.
Your code removes all midpoints found with duplicated x and y coordinates. But, is this what the problem statement requires? If duplicate points actually appear in the input stream, and happen to be midpoints of some other points, should the second and all subsequent duplicates be ignored? Also, if a point is duplicated three (or more) times in the input stream, how many midpoints does that count as? You should carefully check the problem statement to see how duplicates in the input stream should be counted and follow the requirements precisely.
Your check for collinearity looks wrong. You appear to be trying to take a 2d cross of (points[i] - points2[j]) with (points[i] - points2[k]), but this is not the correct way to do it. Here is how to take a 2d cross:
int cross2d(Point a, Point mid, Point c)
{
// Take the 2d cross product (a - mid) X (c - mid).
// 2d cross = (u.x * v.y - u.y * v.x) where u = (a-mid) and v=(c - mid)
int cross = (a.x - mid.x) * (c.y - mid.y) - (a.y - mid.y) * (c.x - mid.x);
return cross;
}
bool collinear(Point a, Point mid, Point c)
{
// Check for the points being collinear (or degenerate, i.e. return true if a == mid or mid == c).
return cross2d(a, mid, c) == 0;
}
Again, integer overflow is a potential problem for point triplets with large coordinates that are nearly perpendicular. And if you were not trying to take a 2d cross, what were you trying to do?
You're trying create an O(n-squared) algorithm by sorting the points by distance from some prospective midpoint. That's creditable, but since your code isn't working I would start by creating a naive O(n-cubed) algorithm that solves the problem straightforwardly. Then you can use that to unit-test your improved n-squared algorithm.
Adding some spacing into your mathematical expressions makes them easier to read.
So, to start you off, here's the naive n-cubed algorithm. Note that I am preserving duplicates in the input stream while avoiding double-counting of points that are midpoints of multiple pairs of points:
#include <iostream>
#include <cmath>
#include <algorithm>
#include <list>
#include <stdio.h>
using namespace std;
struct Point
{
int x;
int y;
int id;
};
bool is_middle(Point a, Point middle, Point c);
bool same_point_id(Point first, Point second);
int main()
{
list<Point> middles;
int N;
scanf("%d", &N);
// https://stackoverflow.com/questions/25437597/find-middle-pointscomputational-geometry-c
// This program should read for input an integer N then the x and y coordinates of the N points
// and return the number of points that are the middle points of any two other points in the set.
Point *points = new Point[N];
for(int i=0;i<N;i++)
{
scanf("%d", &points[i].x);
scanf("%d", &points[i].y);
points[i].id = i;
}
for(int i=0; i<N-2; i++)
{
for(int j=i+1; j<N-1; j++)
{
for(int k=j+1; k<N; k++)
{
// Check the problem requirement to determine how to count sets of three identical points in the input stream.
if (is_middle(points[i], points[j], points[k]))
middles.push_back(points[j]);
if (is_middle(points[j], points[k], points[i]))
middles.push_back(points[k]);
if (is_middle(points[k], points[i], points[j]))
middles.push_back(points[i]);
}
}
}
// Prevent the same input point from being counted multiple times.
middles.unique(same_point_id);
cout<<middles.size();
delete [] points;
}
bool is_middle(Point a, Point mid, Point c)
{
if (a.x - c.x != 2*(a.x - mid.x))
return false;
if (a.y - c.y != 2*(a.y - mid.y))
return false;
return true;
}
bool same_point_id(Point first, Point second)
{
return (first.id==second.id);
}
Update: If you do need an n-squared algorithm then sorting potential endpoints by distance squared from the midpoint isn't a bad idea. If you want to avoid potential arithmetic overflows, you can do calculate the distance squared in 64bit long long ints:
long long distance_squared(Point a, Point b)
{
long long dx = ((long long)a.x - (long long)b.x);
long long dy = ((long long)a.y - (long long)b.y);
return dx*dx + dy*dy;
}
On most platforms these will have more bits than a regular int -- and certainly not fewer.
I was searching for the closest pair code and i found this which has used qsort() library function. I basically didn't get the concept of how it's compare parameter works. Explanation related to this particular code will be more appreciated. Thanks.
#include <iostream>
#include <float.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
// A structure to represent a Point in 2D plane
struct Point
{
int x, y;
};
/* Following two functions are needed for library function qsort().
Refer: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/ */
// Needed to sort array of points according to X coordinate
int compareX(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
// Needed to sort array of points according to Y coordinate
int compareY(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->y - p2->y);
}
// A utility function to find the distance between two points
float dist(Point p1, Point p2)
{
return sqrt( (p1.x - p2.x)*(p1.x - p2.x) +
(p1.y - p2.y)*(p1.y - p2.y)
);
}
// A Brute Force method to return the smallest distance between two points
// in P[] of size n
float bruteForce(Point P[], int n)
{
float min = FLT_MAX;
for (int i = 0; i < n; ++i)
for (int j = i+1; j < n; ++j)
if (dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
return min;
}
// A utility function to find minimum of two float values
float min(float x, float y)
{
return (x < y)? x : y;
}
// A utility function to find the distance beween the closest points of
// strip of given size. All points in strip[] are sorted accordint to
// y coordinate. They all have an upper bound on minimum distance as d.
// Note that this method seems to be a O(n^2) method, but it's a O(n)
// method as the inner loop runs at most 6 times
float stripClosest(Point strip[], int size, float d)
{
float min = d; // Initialize the minimum distance as d
// Pick all points one by one and try the next points till the difference
// between y coordinates is smaller than d.
// This is a proven fact that this loop runs at most 6 times
for (int i = 0; i < size; ++i)
for (int j = i+1; j < size && (strip[j].y - strip[i].y) < min; ++j)
if (dist(strip[i],strip[j]) < min)
min = dist(strip[i], strip[j]);
return min;
}
// A recursive function to find the smallest distance. The array Px contains
// all points sorted according to x coordinates and Py contains all points
// sorted according to y coordinates
float closestUtil(Point Px[], Point Py[], int n)
{
// If there are 2 or 3 points, then use brute force
if (n <= 3)
return bruteForce(Px, n);
// Find the middle point
int mid = n/2;
Point midPoint = Px[mid];
// Divide points in y sorted array around the vertical line.
// Assumption: All x coordinates are distinct.
Point Pyl[mid+1]; // y sorted points on left of vertical line
Point Pyr[n-mid-1]; // y sorted points on right of vertical line
int li = 0, ri = 0; // indexes of left and right subarrays
for (int i = 0; i < n; i++)
{
if (Py[i].x <= midPoint.x)
Pyl[li++] = Py[i];
else
Pyr[ri++] = Py[i];
}
// Consider the vertical line passing through the middle point
// calculate the smallest distance dl on left of middle point and
// dr on right side
float dl = closestUtil(Px, Pyl, mid);
float dr = closestUtil(Px + mid, Pyr, n-mid);
// Find the smaller of two distances
float d = min(dl, dr);
// Build an array strip[] that contains points close (closer than d)
// to the line passing through the middle point
Point strip[n];
int j = 0;
for (int i = 0; i < n; i++)
if (abs(Py[i].x - midPoint.x) < d)
strip[j] = Py[i], j++;
// Find the closest points in strip. Return the minimum of d and closest
// distance is strip[]
return min(d, stripClosest(strip, j, d) );
}
// The main functin that finds the smallest distance
// This method mainly uses closestUtil()
float closest(Point P[], int n)
{
Point Px[n];
Point Py[n];
for (int i = 0; i < n; i++)
{
Px[i] = P[i];
Py[i] = P[i];
}
qsort(Px, n, sizeof(Point), compareX);
qsort(Py, n, sizeof(Point), compareY);
// Use recursive function closestUtil() to find the smallest distance
return closestUtil(Px, Py, n);
}
// Driver program to test above functions
int main()
{
Point P[] = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};
int n = sizeof(P) / sizeof(P[0]);
cout << "The smallest distance is " << closest(P, n);
return 0;
}
The last parameter of qsort is a pointer to a function with a specific signature: it must take two void* pointers, and return an int that indicates which of the two passed items is smaller or if the two items are the same. The specifics are here, but generally a positive result indicates that the second item is smaller, a negative indicates that the first item is smaller, and zero indicates the equaliity.
The implementation of compareX
int compareX(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
follows the general pattern for comparison functions. First, it converts the void* pointer to the Point type, because it "knows" that it is used together with an array of Point structures. Then it subtracts the x coordinates of the two points:
p1->x - p2->x
Note that the result of the subtraction is going to be positive if the second point's x is smaller, negative when the second point's x is greater, and zero when the two xs are the same. This is precisely what qsort wants the cmp function to do, so the subtraction operation fulfills the contract of the comparison function.
If I have a simple 2-D matrix with normalized values on x-axis between 0 and 1 and y-axys between 0 and 1, and I have 3 points in this matrix e.g. P1 (x=0.2,y=0.9), P2 (x=0.5,y=0.1) and P3 (x=0.9,y=0.4).
How can I simply calculate a curve thru this points, meaning having a function which is giving me the y for any x.
I now that there are any number of possible curves thru 3 points. But hey, you know what I mean: I want a smooth curve thru it, usable for audio-sample-interpolation, usable for calculation a volume-fade-curve, usable for calculating a monster-walking-path in a game.
Now I have searched the net for this question about 3 days, and I cannot believe that there is no usable solution for this task. All the text dealing about Catmull-rom-Splines, bezier-curves and all that theroretical stuff has all at least one point which doesn't make it for me usable. For example Catmull-Rom-splines need to have a fix distance between the control-points (I would use this code and set the 4. point-y to the 3. point y) :
void CatmullRomSpline(float *x,float *y,float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,float u)
{
//x,y are calculated for x1,y1,x2,y2,x3,y3 and x4,y4 if u is the normalized distance (0-1) in relation to the distance between x2 and x3 for my whiched point
float u3,u2,f1,f2,f3,f4;
u3=u*u*u;
u2=u*u;
f1=-0.5f * u3 + u2 -0.5f *u;
f2= 1.5f * u3 -2.5f * u2+1.0f;
f3=-1.5f * u3 +2.0f * u2+0.5f*u;
f4=0.5f*u3-0.5f*u2;
*x=x1*f1+x2*f2+x3*f3+x4*f4;
*y=y1*f1+y2*f2+y3*f3+y4*f4;
}
But I don't see that x1 to x4 have any affect on the calculation of y, so I think x1 to x4 must have the same distance?
...
Or bezier-code doesn't calcuate the curve thru the points. The points (at least the 2. point) seem only to have a force-effect on the line.
typedef struct Point2D
{
double x;
double y;
} Point2D;
class bezier
{
std::vector<Point2D> points;
bezier();
void PushPoint2D( Point2D point );
Point2D GetPoint( double time );
~bezier();
};
void bezier::PushPoint2D(Point2D point)
{
points.push_back(point);
}
Point2D bezier::GetPoint( double x )
{
int i;
Point2D p;
p.x=0;
p.y=0;
if( points.size() == 1 ) return points[0];
if( points.size() == 0 ) return p;
bezier b;
for (i=0;i<(int)points.size()-1;i++)
{
p.x = ( points[i+1].x - points[i].x ) * x + points[i].x;
p.y = ( points[i+1].y - points[i].y ) * x + points[i].y;
if (points.size()<=2) return p;
b.PushPoint2D(p);
}
return b.GetPoint(x);
}
double GetLogicalYAtX(double x)
{
bezier bz;
Point2D p;
p.x=0.2;
p.y=0.9;
bz.PushPoint2D(p);
p.x=0.5;
p.y=0.1;
bz.PushPoint2D(p);
p.x=0.9;
p.y=0.4;
bz.PushPoint2D(p);
p=bz.GetPoint(x);
return p.y;
}
This is better than nothing, but it is 1. very slow (recursive) and 2. as I said doesn't really calculate the line thru the 2. point.
Is there a mathematical brain outside which could help me?
Thank you TOCS (Scott) for providing your code, I will also try it if I have some time. But what I have tested now is the hint by INFACT (answer 3): This "Largrange polynomials" are very very close to what I am searching for:
I have renamed my class bezier to curve, because I have added some code for lagrangeinterpolation. I also have added 3 pictures of graphical presentation what the code is calculation.
In Picture 1 you can see the loose middle point of the old bezier-function.
In Picture 2 you can now see the going thru all-points-result of lagrange interpolation.
In Picture 3 you can see the only problem, or should I say "thing which I also need to be solved" (anyway its the best solution till now): If I move the middle point, the curve to going to fast, to quick to the upper or lower boundaries). I would like it to go more smoothely to the upper and lower. So that it looks more logarithm-function like. So that it doesn't exeed the y-boundaries between 0 and 1 too soon.
Now my code looks like this:
curve::curve(void)
{
}
void curve::PushPoint2D(Point2D point)
{
points.push_back(point);
}
Point2D curve::GetPoint( double x )
{
//GetPoint y for x with bezier-mathematics...
//was the only calculating function in old class "bezier"
//now the class is renamed "curve"
int i;
Point2D p;
p.x=0;
p.y=0;
if( points.size() == 1 ) return points[0];
if( points.size() == 0 ) return p;
curve b;
for (i=0;i<(int)points.size()-1;i++)
{
p.x = ( points[i+1].x - points[i].x ) * x + points[i].x;
p.y = ( points[i+1].y - points[i].y ) * x + points[i].y;
if (points.size()<=2) return p;
b.PushPoint2D(p);
}
return b.GetPoint(x);
}
//THIS IS NEW AND VERY VERY COOL
double curve::LagrangeInterpolation(double x)
{
double y = 0;
for (int i = 0; i <= (int)points.size()-1; i++)
{
double numerator = 1;
double denominator = 1;
for (int c = 0; c <= (int)points.size()-1; c++)
{
if (c != i)
{
numerator *= (x - points[c].x);
denominator *= (points[i].x - points[c].x);
}
}
y += (points[i].y * (numerator / denominator));
}
return y;
}
curve::~curve(void)
{
}
double GetLogicalYAtX(double x)
{
curve cv;
Point2D p;
p.x=0; //always left edge
p.y=y1; //now by var
cv.PushPoint2D(p);
p.x=x2; //now by var
p.y=y2; //now by var
cv.PushPoint2D(p);
p.x=1; //always right edge
p.y=y3; //now by var
cv.PushPoint2D(p);
//p=cv.GetPoint(x);
//return p.y;
return cv.LagrangeInterpolation(x);
}
Do you have any ideas how I could get the new solution a little bit more "soft"? So that I can move the 2. Point in larger areas without the curve going out of boundaries? Thank you
static bezier From3Points(const Point2D &a, const Point2D &b, const Point2D &c)
{
bezier result;
result.PushPoint2D(a);
Point2D middle;
middle.x = 2*b.x - a.x/2 - c.x/2;
middle.y = 2*b.y - a.y/2 - c.y/2;
result.PushPoint2D(middle);
result.PushPoint2D(c);
return result;
}
Untested, but should return a bezier curve where at t=0.5 the curve passes through point 'b'.
Additionally (more untested code ahead), you can calculate your points using bernstein basis polynomials like so.
static int binomialcoefficient (int n, int k)
{
if (k == 0)
return 1;
if (n == 0)
return 0;
int result = 0;
for (int i = 1; i <= k; ++i)
{
result += (n - (k - i))/i;
}
return result;
}
static double bernstein (int v, int n, double t)
{
return binomialcoefficient(v,n) * pow(t,v) * pow(1 - t,n - v);
}
Point2D GetPoint (double t)
{
Point2D result;
result.x = 0;
result.y = 0;
for (int i = 0; i < points.size(); ++i)
{
double coeff = bernstein (i,points.size(),t);
result.x += coeff * points[i].x;
result.y += coeff * points[i].y;
}
return result;
}
How would you solve the problem of finding the points of a (integer) grid within a circle centered on the origin of the axis, with the results ordered by norm, as in distance from the centre, in C++?
I wrote an implementation that works (yeah, I know, it is extremely inefficient, but for my problem anything more would be overkill). I'm extremely new to C++, so my biggest problem was finding a data structure capable of
being sort-able;
being able to save an array in one of its elements,
rather than the implementation of the algorithm. My code is as follows. Thanks in advance, everyone!
typedef std::pair<int, int[2]> norm_vec2d;
bool norm_vec2d_cmp (norm_vec2d a, norm_vec2d b)
{
bool bo;
bo = (a.first < b.first ? true: false);
return bo;
}
int energy_to_momenta_2D (int energy, std::list<norm_vec2d> *momenta)
{
int i, j, norm, n=0;
int energy_root = (int) std::sqrt(energy);
norm_vec2d temp;
for (i=-energy_root; i<=energy_root; i++)
{
for (j =-energy_root; j<=energy_root; j++)
{
norm = i*i + j*j;
if (norm <= energy)
{
temp.first = norm;
temp.second[0] = i;
temp.second[1] = j;
(*momenta).push_back (temp);
n++;
}
}
}
(*momenta).sort(norm_vec2d_cmp);
return n;
}
How would you solve the problem of finding the points of a (integer) grid within a circle centered on the origin of the axis, with the results ordered by norm, as in distance from the centre, in C++?
I wouldn't use a std::pair to hold the points. I'd create my own more descriptive type.
struct Point {
int x;
int y;
int square() const { return x*x + y*y; }
Point(int x = 0, int y = 0)
: x(x), y(y) {}
bool operator<(const Point& pt) const {
if( square() < pt.square() )
return true;
if( pt.square() < square() )
return false;
if( x < pt.x )
return true;
if( pt.x < x)
return false;
return y < pt.y;
}
friend std::ostream& operator<<(std::ostream& os, const Point& pt) {
return os << "(" << pt.x << "," << pt.y << ")";
}
};
This data structure is (probably) exactly the same size as two ints, it is less-than comparable, it is assignable, and it is easily printable.
The algorithm walks through all of the valid points that satisfy x=[0,radius] && y=[0,x] && (x,y) inside circle:
std::set<Point>
GetListOfPointsInsideCircle(double radius = 1) {
std::set<Point> result;
// Only examine bottom half of quadrant 1, then
// apply symmetry 8 ways
for(Point pt(0,0); pt.x <= radius; pt.x++, pt.y = 0) {
for(; pt.y <= pt.x && pt.square()<=radius*radius; pt.y++) {
result.insert(pt);
result.insert(Point(-pt.x, pt.y));
result.insert(Point(pt.x, -pt.y));
result.insert(Point(-pt.x, -pt.y));
result.insert(Point(pt.y, pt.x));
result.insert(Point(-pt.y, pt.x));
result.insert(Point(pt.y, -pt.x));
result.insert(Point(-pt.y, -pt.x));
}
}
return result;
}
I chose a std::set to hold the data for two reasons:
It is stored is sorted order, so I don't have to std::sort it, and
It rejects duplicates, so I don't have to worry about points whose reflection are identical
Finally, using this algorithm is dead simple:
int main () {
std::set<Point> vp = GetListOfPointsInsideCircle(2);
std::copy(vp.begin(), vp.end(),
std::ostream_iterator<Point>(std::cout, "\n"));
}
It's always worth it to add a point class for such geometric problem, since usually you have more than one to solve. But I don't think it's a good idea to overload the 'less' operator to satisfy the first need encountered. Because:
Specifying the comparator where you sort will make it clear what order you want there.
Specifying the comparator will allow to easily change it without affecting your generic point class.
Distance to origin is not a bad order, but for a grid but it's probably better to use row and columns (sort by x first then y).
Such comparator is slower and will thus slow any other set of points where you don't even care about norm.
Anyway, here is a simple solution using a specific comparator and trying to optimize a bit:
struct v2i{
int x,y;
v2i(int px, int py) : x(px), y(py) {}
int norm() const {return x*x+y*y;}
};
bool r_comp(const v2i& a, const v2i& b)
{ return a.norm() < b.norm(); }
std::vector<v2i> result;
for(int x = -r; x <= r; ++x) {
int my = r*r - x*x;
for(int y = 0; y*y <= my; ++y) {
result.push_back(v2i(x,y));
if(y > 0)
result.push_back(v2i(x,-y));
}
}
std::sort(result.begin(), result.end(), r_comp);