Unknown bug affecting Graham's algorithm for finding convex hull - c++

I have programmed the Graham's algorithm but it still gives me the wrong points for the convex hull. I need help. Think I have a bug in my sign function but dunno what it is.
#include <cstdio>
#include <algorithm>
#include <math.h>
#define pb push_back
#define mp make_pair
#include <vector>
using namespace std;
vector <pair<double, double> > st;
pair<double, double> p[1000];
double x, y;
int f(pair <double,double> a, pair<double, double> b)
{
double x1 = x - a.first, x2 = x - b.first;
double y1 = y - a.second, y2 = y - b.second;
return ((x1*y2-y1*x2) < 0);
}
void setlast(double &x1, double &y1, double &x2, double &y2)
{
x2 = st[st.size()-1].first;
y2 = st[st.size()-1].second;
x1 = st[st.size()-2].first;
y1 = st[st.size()-2].second;
}
sign improved I use doubles
double sign(double x1,double y1, double x2,double y2, double y3,double x3)
{
double xx1 = x2 - x1, xx2 = x3 - x1;
double yy1 = y2 - y1, yy2 = y3 - y1;
return (xx1*yy2-yy1*xx2);
}
int main()
{
int n;
x = 0x3f3f3f3f;
y = 0x3f3f3f3f;
scanf("%d", &n);
for(int i = 0; i < n; i++)
{
scanf("%lf %lf", &p[i].first, &p[i].second);
if(p[i].first <= x && p[i].second <= y)
x = p[i].first,
y = p[i].second;
}
sort(p, p + n, f);
p[n].first = x;
p[n].second = y;
st.pb(mp(p[0].first, p[0].second));
st.pb(mp(p[1].first, p[1].second));
double x1, x2, x3, y1, y2, y3;
here I iterate through all vectors and try to determine the points of convex hull
for(int i = 2; i < n; i++)
{
x3 = p[i].first;
y3 = p[i].second;
setlast(x1,y1,x2,y2);
while(1)
if(sign(x1,y1,x2,y2,x3,y3) < 0)
{
st.pb(mp(x3, y3));
break;
}
else
st.pop_back(),
setlast(x1, y1, x2, y2);
}
here printing the convex hull
for(int i = 0; i < st.size(); i++)
printf("%lf %lf\n", st[i].first, st[i].second);
return 0
}

My question, why does int f(pair<int, int>, pair<int, int>) take pair<int, int> instead of pair<double, double>?
Also, why isn't it named something informative like compare_blah?
Lastly, why doesn't it return bool instead of an int? Either works of course, but it will be clearer that this is intended simply as a comparison function if you return a bool. And making your program clear to people who read it should be your primary goal. Getting it to do what it's supposed to is a secondary goal. After all, it doing what it's supposed to is only a transitory state of affairs. Eventually someone will want it to do something else.
The pair<int, int> thing could be your problem right there. You are doing several implicit type conversions in that function between int and double and losing information left and right. I doubt that's what you intended.
If you would use a typedef for your pair like typedef pair<double, double> point2d_t and then use point2d_t everywhere you could protect yourself from mistakes like that and make your program clearer in the bargain.
I'm not familiar enough with Graham's algorithm to evaluate your use of abs inside of f, though it's quite possible the person who commented on this is correct.

Related

How to create a C++ array with variable elements?

I have this C++ program:
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cmath>
using namespace std;
double dx2(int t, int x, int dx)
{
return (-9.8*cos(x));
}
int square(int x)
{
return (x*x);
}
double RK4(float t, float x, float dx, float h)
{
double k1, k2, k3, k4, l1, l2, l3, l4, diff1, diff2;
k1 = h*dx2(t,x,dx);
l1 = h*k1;
k2 = h*dx2(t+h/2,x+l1/2,dx+k1/2);
l2 = h*k2;
k3 = h*dx2(t+h/2,x+l2/2,dx+k2/2);
l3 = h*k3;
k4 = h*dx2(t+h,x+l3,dx+k3);
l4 = h*k4;
diff1 = (l1+2*l2+2*l3+l4)/float(6);
diff2 = (k1+2*k2+2*k3+k4)/float(6);
double OUT[] = {diff1, diff2};
return OUT;
}
int main()
{
double diff, t, t0, t1, x, x0, dx, dx0, h, N;
N = 1000;
t0 = 0;
t = t0;
t1 = 10;
x0 = 0;
x = x0;
dx0 = 0;
dx = dx0;
h = (t1 - t0) / float(N);
for(int i = 1; i<=N; i++) {
diff = RK4(t,x,dx,h);
x = x + diff;
t = t + h;
}
cout << diff;
return 0;
}
As you can see in this program I am solving the 2nd-order differential equation (if there is a way to insert LaTeX equations into my question please tell me):
d2x/dt2= -9.8 cos(x)
which is an example of the simple pendulum's equations of motion. The problem lines are 33 and 34. In it I am attempting to define the first element of the OUT array as diff1 and the second element as diff2. Whenever I compile this program (named example.cpp) I get the error:
g++ -Wall -o "example" "example.cpp" (in directory: /home/fusion809/Documents/CodeLite/firstExample)
example.cpp: In function ‘double RK4(float, float, float, float)’:
example.cpp:33:9: error: cannot convert ‘double*’ to ‘double’ in return
return OUT;
^~~
Compilation failed.
Exactly, since you're returning an array of double's, that decays to double*, but the function is defined to return double. An array of type T and the type T are different types in C++, and they can't be converted between, generally speaking.
In this case, you might be better off with a std::pair<T1, T2> (#include <utility>) since you're using C++ and the standard library, or a structure with two fields of type double. Look up std::pair<> and std::tie<>, the former being used to make pairs of elements of different types, and the latter being used to make tuples of different types of arbitrary size.
When you write the std::pair's elements to std::cout, use the first, second members to access the pair's fields. A std::pair can't be directly output using the overloaded stream operator for std::cout.
Edit:
#include <utility>
std::pair<double, double> RK4(float t, float x, float dx, float h)
{
/* snip */
diff1 = (l1+2*l2+2*l3+l4)/float(6);
diff2 = (k1+2*k2+2*k3+k4)/float(6);
return {diff1, diff2};
}
int main()
{
double x, dx;
/* snip */
for(int i = 1; i<=N; i++) {
std::pair<double, double> diff = RK4(t,x,dx,h);
// or use with C++11 and above for brevity
auto diff = RK4(t,x,dx,h);
x = x + diff.first;
dx = dx + diff.second;
t = t + h;
}
cout << x << " " << dx << "\n" ;
return 0;
}
The return type of your RK4 function is double, which is a single value, but you're trying to return an array of two of them. That won't work. You could change the return type to double* and use new double[2] to allocate an array, but it'd be simpler and safer to use std::pair<double, double> as the return type. Then you can just do return { diff1, diff2 };.
To return several values from function you have several choice:
as all you returned type are identical, you may return array:
std::array<double, 2> RK4(float t, float x, float dx, float h)
{
// ...
return {{diff1, diff2}};
}
or std::vector
std::vector<double> RK4(float t, float x, float dx, float h)
{
// ...
return {{diff1, diff2}};
}
You may return std::tuple or std::pair (limited to 2 elements):
std::pair<double, double> RK4(float t, float x, float dx, float h)
{
// ...
return {{diff1, diff2}};
}
or
std::tuple<double, double> RK4(float t, float x, float dx, float h)
{
// ...
return {{diff1, diff2}};
}
You may also create a custom class
struct RK4Result
{
double diff1;
double diff2;
};
RK4Result RK4(float t, float x, float dx, float h)
{
// ...
return {diff1, diff2};
}
And for type expensive to move, you may use any previous method, but by out parameters:
struct RK4Result
{
double diff1;
double diff2;
};
void RK4(float t, float x, float dx, float h, RK4Result& res)
{
// ...
res = {diff1, diff2};
}

In CUDA / Thrust, how can I access a vector element's neighbor during a for-each operation?

I am trying to do some scientific simulation using Thrust library in CUDA, but I got stuck in the following operation which is basically a for-each loop:
device_vector<float> In(N);
for-each In(x) in In
Out(x) = some_calculation(In(x-1),In(x),In(x+1));
end
I have already looked up stackoverflow.com and find some similar questions:
Similar questions 1
But it seems using a transform iterator is only possible when the some_calculation function is done between 2 parameters, for transform iterator passes two parameters at most.
Then, for question 2:
Similar questions 2
The discussion just ended without a conclusion.
I believe this is a simple problem because it's a natural requirements for parallel calculation. Anyone could tell me what to do?
Fancy iterators are the key to this sort of operation, which isn't all that intuitive in thrust. You can use the zip_iterator to create tuples of values which can then be iterated over, so for a typical f(x[i-1], x[i], x[i+1]) type function, you get something like this:
#include <iostream>
#include <cmath>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>
#include <thrust/transform.h>
struct divided_diff {
float dx;
divided_diff(float _dx) : dx(_dx) {};
float operator()(const thrust::tuple<float, float, float> &in) const {
float y0 = in.get<0>();
float y1 = in.get<1>();
float y2 = in.get<2>();
return (y0 - 2.f * y1 + y2) / (dx * dx);
}
};
int main() {
const int N = 10;
const float dx = 0.1f;
float x[N], y[N], dydx[N];
for (int i = 0; i < N; ++i) {
x[i] = dx * float(i);
y[i] = std::sin(x[i]);
dydx[i] = 0.f;
}
auto begin = thrust::make_zip_iterator(thrust::make_tuple(&y[0], &y[1], &y[2]));
auto end = thrust::make_zip_iterator(thrust::make_tuple(&y[N-2], &y[N-1], &y[N]));
divided_diff f(dx);
thrust::transform(begin, end, &dydx[1], f);
for (int i = 0; i < N; ++i) {
std::cout << i << " " << dydx[i] << std::endl;
}
return 0;
}
Here the functor processes one tuple at a time, where the tuple contains the three inputs from three different starting points in the same array or iterative sequence.
EDIT: Apparently converting a host version of this code to use device constructs was proving challenging for the originally poster, so here is a version which executes everything on the device using thrust::device_vector as the base container:
#include <iostream>
#include <cmath>
#include <thrust/tuple.h>
#include <thrust/transform.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
struct divided_diff {
float dx;
divided_diff(float _dx) : dx(_dx) {};
__device__
float operator()(const thrust::tuple<float, float, float> &in) {
float y0 = in.get<0>();
float y1 = in.get<1>();
float y2 = in.get<2>();
return (y0 - 2.f*y1 + y2) / (dx * dx);
}
};
struct mysinf {
__device__
float operator()(const float &x) {
return __sinf(x);
}
};
int main()
{
const int N = 10;
const float dx = 0.1f;
thrust::device_vector<float> x(N), y(N), dydx(N-2);
thrust::sequence(x.begin(), x.end(), 0.f, dx);
thrust::transform(x.begin(), x.end(), y.begin(), mysinf());
auto start = thrust::make_zip_iterator(thrust::make_tuple(y.begin(), y.begin()+1, y.begin()+2));
auto finish = thrust::make_zip_iterator(thrust::make_tuple(y.end()-2, y.end()-1, y.end()));
divided_diff f(dx);
thrust::transform( start, finish, dydx.begin(), f);
thrust::device_vector<float>::iterator it = dydx.begin();
for(; it != dydx.end(); ++it) {
float val = *it;
std::cout << val << std::endl;
}
return 0;
}

Finding minimum and maximum points coordinates with C++

I have a text file that include X,Y,Z coordinates of points. My aim is finding minimum and maximum points and write it another file. For this aim I write a distance function. The points that have maximum distance is minimum and maximum points. here is my code. It works but it does not calculate or write anything.
#include <iostream>
#include<fstream>
#include <math.h>
using namespace std;
double distance (float X1, float Y1, float Z1, float X2, float Y2, float Z2)
{
return sqrt(pow((X2-X1),2)+ pow((Y2-Y1),2)+pow((Z2-Z1),2));
}
int main ()
{
float x1, y1, z1,x2, y2,z2;
ifstream file("D:\\points.txt");
ofstream result ("D:\\result.txt");
double bigdistance=0;
if (file.is_open())
{
while (!file.eof())
{
file>>x1>>y1>>z1;
while (!file.eof())
{
file>>x2>>y2>>z2;
double d= distance (x1,y1,z1,x2,y2,z2);
if (bigdistance<d)
{
bigdistance=d;
result<<x1<<y1<<z1<<endl<<x2<<y2<<z2;
}
}
}
}
else cout <<"cannot open file";
system ("PAUSE");
return 0;
}
A couple of suggestions:
while (file >> x1 >> y1 >> z1 >> x2 >> y2 >> z2) {
}
will read your input and stop if any of the reads failed.
You will want to read the entire input and store it in a vector of points, or similar. Then, you can use two nested loops to iterate over each pair of points. Right now, your programs assumes that the input file contains all pairs. That is, each point is read multiple times form the input, in the inner loop.
There are also algorithms that are faster than quadratic, and you might need those if you have more than a couple thousand input points. See for example this StackOverflow question.
#include <iostream>
#include<fstream>
#include <math.h>
using namespace std;
enter code here`{
for (int i = 1; !f1.eof(); i++)
{
int x1, y1, x2, y2, x3, y3, x4, y4);
read(f1, x1, y1, x3, y3);
x2 = x3;
y2 = y1;
x4 = x1;
y4 = y3;
if (y4 > y1)
{
a = y1 - y4;
}
else
a = y4 - y1;
if (x4 > x3)
{
b = x4 - x3;
}
else
b = x3 - x4;
}
}

Polygon intersection with Boost::geometry severe performance deterioration

I have a particle system and I am using boost::geometry to approximate my elliptical particles as polygons and then use the intersection function of the library to find the overlap area. I am calculating an "inner" and "outer" ellipse(polygon) area to assign a "potential" for each particle-particle interaction.
My potential function is this:
double Potential(Cell* current, Cell* next)
{
double areaRep, areaAtt;
double distance = Distance(current,next);
double A1 = current->getLength();
double B1 = A1/2.0;
double theta1 = current->getTheta(); //*180.0/M_PI
double x1 = current->getCurrX();
double y1 = current->getCurrY();
double A2 = next->getLength();
double B2 = A2/2.0;
double theta2 = next->getTheta();
double x2 = next->getCurrX();
double y2 = next->getCurrY();
polygon_2d poly1, poly2, poly3, poly4;
double lamda1, lamda2;
lamda1 = 0.0005; lamda2 = 0.00001;
if(distance < 2.0*1.5*A1) {
ellipse2poly(theta1, A1, B1, x1, y1, &poly1);
ellipse2poly(theta2, A2, B2, x2, y2, &poly2);
areaRep = getOverlapingAreaPoly(poly1,poly2);
ellipse2poly(theta1, 1.5*A1, 1.5*B1, x1, y1, &poly3);
ellipse2poly(theta2, 1.5*A2, 1.5*B2, x2, y2, &poly4);
areaAtt = getOverlapingAreaPoly(poly3, poly4);
return (lamda1*areaRep - lamda2*areaAtt);
}
else
return 0.0;
}
The "polygonizing" function is:
int ellipse2poly(double theta, double A1, double B1, double H1, double K1, polygon_2d *po)
{
using namespace boost::geometry;
polygon_2d poly;
const int n = 20;
double angle = theta; // cell orientation
double a = A1; // Long semi-axis length
double b = B1; // short semi-axis length
double xc = H1; // current X position
double yc = K1; // current Y position
if(!n)
{
std::cout << "error ellipse(): n should be >0\n" <<std::endl;
return 0;
}
double t = 0;
int i = 0;
double coor[2*n+1][2];
double x, y;
double step = M_PI/(double)n;
double sinphi = sin(angle);
double cosphi = cos(angle);
for(i=0; i<2*n+1; i++)
{
x = xc + a*cos(t)*cosphi - b*sin(t)*sinphi;
y = yc + a*cos(t)*sinphi + b*sin(t)*cosphi;
coor[i][0] = x;
coor[i][1] = y;
t += step;
}
assign_points(poly, coor);
correct(poly);
*po = poly;
return 1;
}
And the returned area is:
double getOverlapingAreaPoly(polygon_2d poly, polygon_2d poly2)
{
point_2d cent; //centre of overlaping area
double overAreaPoly = 0.0;
typedef std::vector<polygon_2d > polygon_list;
polygon_list v;
intersection(poly,poly2,v);
for (polygon_list::const_iterator it = v.begin(); it != v.end(); ++it)
{
centroid(*it, cent);
overAreaPoly = area(*it);
}
return overAreaPoly;
}
The function is called for every cell (particle) as long as it is not for the same one. Previously, using another method, one iteration of my algorithm would take approximately 43 ms for one iteration for 100 particles. Now it takes approximately 1 min(!!!), so I guess I have done something horribly wrong!
I have tested this only in MSVC2012 under win7 64bit. I will report back for Linux Mint with Qt 4.7.4.
EDIT:
I have tested on Linux Mint with Qt 4.7.4 and it is running very reasonably; maybe 90-100 ms per iteration which is fine. I don't know what is wrong in win7...
I have actually fixed it. I started a new project in Visual Studio and copied all source and header files, recompiled and everything runs smoothly now. I guess radically changing code and adding / subtracting stuff must have some impact...

Orthogonal variables code duplication problem

I've started refactoring some legacy code recently and came across two functions for drawing a coordinate grid, the problem is that these functions differ only in orthogonal variables they treat, something like that
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
MoveToEx(dc, x, y0, NULL);
LineTo(dc, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
}
}
So if I decide to add some fancy stuff, like antialiasing or merely change drawing pencil or whatever I'll have to put the same code in both of them and it's code duplication and it's bad we all know why.
My question is how would you rewrite these two functions into a single one to avoid this problem?
Why you just do not extract the body of the for cycle into a separate function? Then you can do the funny stuff in the extracted function.
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
DrawScale(dc, x, y0, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
DrawScale(dc, x0, y, x1, y);
}
}
private void DrawScale(HDC dc, int x0, int y0, int x1, int y1)
{
//Add funny stuff here
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
//Add funny stuff here
}
Drawing a line is simply joining two points, and drawing a scaling incrementing (x0,y0) and(x1,y1) in a particular direction, through X, and/or through Y.
This boils down to, in the scale case, which direction(s) stepping occurs (maybe both directions for fun).
template< int XIncrement, YIncrement >
struct DrawScale
{
void operator()(HDC dc, int step, int x0, int x1, int y0, int y1)
{
const int deltaX = XIncrement*step;
const int deltaY = YIncrement*step;
const int ymax = y1;
const int xmax = x1;
while( x0 < xmax && y0 < ymax )
{
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
x0 += deltaX;
x1 += deltaX;
y0 += deltaY;
y1 += deltaY;
}
}
};
typedef DrawScale< 1, 0 > DrawScaleX;
typedef DrawScale< 0, 1 > DrawScaleY;
The template will do its job: at compile time the compiler will remove all the null statements i.e. deltaX or deltaY is 0 regarding which function is called and half of the code goes away in each functor.
You can add you anti-alias, pencil stuff inside this uniq function and get the code properly generated generated by the compiler.
This is cut and paste on steroids ;-)
-- ppi
Here is my own solution
class CoordGenerator
{
public:
CoordGenerator(int _from, int _to, int _step)
:from(_from), to(_to), step(_step), pos(_from){}
virtual POINT GetPoint00() const = 0;
virtual POINT GetPoint01() const = 0;
bool Next()
{
if(pos > step) return false;
pos += step;
}
protected:
int from;
int to;
int step;
int pos;
};
class GenX: public CoordGenerator
{
public:
GenX(int x0, int x1, int step, int _y0, int _y1)
:CoordGenerator(x0, x1, step),y0(_y0), y1(_y1){}
virtual POINT GetPoint00() const
{
const POINT p = {pos, y0};
return p;
}
virtual POINT GetPoint01() const
{
const POINT p = {pos, y1};
return p;
}
private:
int y0;
int y1;
};
class GenY: public CoordGenerator
{
public:
GenY(int y0, int y1, int step, int _x0, int _x1)
:CoordGenerator(y0, y1, step),x0(_x0), x1(_x1){}
virtual POINT GetPoint00() const
{
const POINT p = {x0, pos};
return p;
}
virtual POINT GetPoint01() const
{
const POINT p = {x1, pos};
return p;
}
private:
int x1;
int x0;
};
void DrawScale(HDC dc, CoordGenerator* g)
{
do
{
POINT p = g->GetPoint00();
MoveToEx(dc, p.x, p.y, 0);
p = g->GetPoint01();
LineTo(dc, p.x, p.y);
}while(g->Next());
}
But I it seems to me too complicated for such a tiny problem, so I'm looking forward to still see your solutions.
Well, an obvious "solution" would be to make a single function and add one extra parameter (of enum-like type). And then do an if() or switch() inside, and perform the appropriate actions. Because hey, the functionality of the functions is different, so you have to do those different actions somewhere.
However, this adds runtime complexity (check things at runtime) in a place that could be just better checked at compile time.
I don't understand what's the problem in adding extra parameters in the future in both (or more functions). It goes like this:
add more parameters to all functions
compile your code, it won't compile in a bunch of places because it does not pass new parameters.
fix all places that call those functions by passing new parameters.
profit! :)
If it's C++, of course you could make the function be a template, and instead adding an extra parameter, you add a template parameter, and then specialize template implementations to do different things. But this is just obfuscating the point, in my opinion. Code becomes harder to understand, and the process of extending it with more parameters is still exactly the same:
add extra parameters
compile code, it won't compile in a bunch of places
fix all places that call that function
So you've won nothing, but made code harder to understand. Not a worthy goal, IMO.
I think I'd move:
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
into their own function DrawLine(x0,y0,x0,y0), which you can call from each of the existing functions.
Then there's one place to add extra drawing effects?
A little templates... :)
void DrawLine(HDC dc, int x0, int y0, int x0, int x1)
{
// anti-aliasing stuff
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
}
struct DrawBinderX
{
DrawBinderX(int y0, int y1) : y0_(y0), y1_(y1) {}
void operator()(HDC dc, int i)
{
DrawLine(dc, i, y0_, i, y1_);
}
private:
int y0_;
int y1_;
};
struct DrawBinderY
{
DrawBinderX(int x0, int x1) : x0_(x0), x1_(x1) {}
void operator()(HDC dc, int i)
{
DrawLine(dc, x0_, i, x1_, i);
}
private:
int x0_;
int x1_;
};
template< class Drawer >
void DrawScale(Drawer drawer, HDC dc, int from, int to, int step)
{
for (int i = from; i < to; i += step)
{
drawer(dc, i);
}
}
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
DrawBindexX drawer(y0, y1);
DrawScale(drawer, dc, x0, x1, step);
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
DrawBindexY drawer( x0, x1 );
DrawScale(drawer, dc, y0, y1, step);
}