Is that possible to give floating values to the clipper Paths - c++

Clipper takes integer input but I want to pass floating values without losing the precision.
Clipper struct for Integer and double value.
struct IntPoint {
cInt X;
cInt Y;
#ifdef use_xyz
cInt Z;
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
#else
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
#endif
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
{
return a.X != b.X || a.Y != b.Y;
}
};
struct DoublePoint
{
double X;
double Y;
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
};
why it is not taking the double value as an input.
Paths Polygon(2);
Polygon[0] << IntPoint(10, 10) << IntPoint(60, 10) << IntPoint(30, 100) ;
Polygon[1] << IntPoint(20, 20) << IntPoint(50, 20) << IntPoint(30, 80) ; //it Works
Paths Line(1);
line[0] << DoublePoint(40.2, 10.2) << DoublePoint(56.5, 85.45); //Not works

Clipper only uses integer point types.
The IntPoint structure is used to represent all vertices in the Clipper Library. An integer storage type has been deliberately chosen to preserve numerical robustness. (Early versions of the library used floating point coordinates, but it became apparent that floating point imprecision would always cause occasional errors.) [src]
You can however scale your input coordinates by a desirable factor.
So instead of wanting this, (which doesn't exist)
line[0] << DoublePoint(40.2, 10.2) << DoublePoint(56.5, 85.45); //Not works
You can scale by 100.
line[0] << IntPoint(4020, 1020) << IntPoint(5650, 8545); //works
Just remember to scale output coordinates by 0.01 to get back to your coordinate system.

Related

Why my compare operator is not comparing my point length and double value?

I create new operator to compare my point vector length and double value. I have condition to tolerate different which is less than 0.01.
When i using this operator to compare my Point and my double value (both values after approaching are same) but the operator == is not returning true.
class Point {
private:
double x, y, z;
public:
Point() { x = y = z = 0.0; }
Point(double v) { x = y = z = v; }
Point(double x, double y, double z){
this->x = x; this->y = y; this->z = z;
}
double getLength(){
return sqrt(pow(x,2)+pow(y,2)+pow(z,2));
}
friend const bool operator== (double &d, Point &v);
};
double approach(double num){
return floor(num*100)/100;
}
const bool operator== (const double &d, Point &v){
return (approach(d) == approach(v.getLength()));
}
int main()
{
Point p1(3,4,1);
cout << p1.getLength() << endl; // 5.09902
cout << approach(p1.getLength()) << endl;
cout << approach(5.091) << endl;
if(5.091 == p1)
cout << "True";
return 0;
}
This issue can be reproduced on gcc with 32 bit Intel architecture, without optimization.
Here is an example of it happening:
compiler explorer example.
This is due to the infamous 323 bug of gcc, which struggles to work with Intel's 80 bit floating point registers, which are wider than the 64 bits of type double. Some of the values end up in the 80-bit register, and some values in the 64-bit memory value.
In your case, approach(d) is called first, and then get spilled to memory when v.getLength() is called. The value of approach(v.getLength()), on the other hand, is not getting spilled and gets all of register's 80-bit precision.
When you compare an 80-bit accurate value, and a truncated 64-bit value, the comparison result is false.
A possible solution is to avoid the division by 100 in approach(), since it is what introduces the extra bits. Instead, you can try:
static constexpr double magnitude = 100.0;
const bool operator== (double d, const Point &v){
return floor(d * magnitude) == floor(v.getLength() * magnitude));
}

Finding 4th vertex of a rectangle

I need my code to find the 4th vertex of a rectangle. Tried to make something but as always failed. It works in some cases, bot not everytime. Could someone help me with it?
Also, it has to be done with 2 classes, one for vertices and other one for a whole rectangle.
Problem is that my code works for a certain vertex setting. I was trying many things but still fail.
Here's the code:
#include <iostream>
#include <cmath>
using namespace std;
class vertex{
public:
double x;
double y;
void insert(){
cin>>x;
cin>>y;
}
};
class rect{
private:
double ax, ay, bx, by, cx, cy, dx, dy;
public:
void insert_data(vertex A, vertex B, vertex C){ //inserting rectangle data
ax=A.x;
ay=A.y;
bx=B.x;
by=B.y;
cx=C.x;
cy=C.y;
}
void calculate(){ //finding 4h vertex coordinates
dx=cx+(abs(ax-bx));
dy=cy+(abs(ay+by));
}
void out(){ //output
cout<<dx<<" "<<dy;
}
};
using namespace std;
int main() {
vertex A, B, C;
A.insert();
B.insert();
C.insert();
rect X;
X.insert_data(A, B, C);
X.calculate();
X.out();
return 0;
}
As I think about it now it may have something to do with inserting the coordinates to the right variables, but can't think of a solution to fix this.
For example:
Input:
1 1
0 3
3 2
Output:
2 4
Order of inputing each vertex is not specified.
Working with vectors is a very interesting topic. Here are some good explainations about vector
To answer your question:
From 3 givens vertexs A, B and C, you have only three cases of the right angle : at A, at B or at C. If you found the right angle, for example, at B (no matter order of A and C), you have the D coordinate calculated by the formulation : D = A + C - B.
To detect if the right angle is at B: the dot product of two vectors BA and BC is 0, no matter order of A and C.
In C++ way, (not C way) you should add operators to manipulate vectors in your vertex class, here is an example :
#define MY_EPSILON 10E-6
class vertex {
public:
double X, Y;
vertex(double x_, double y_ ) :X(x_), Y( y_){}
vertex():X(0), Y(0){}
vertex operator +( vertex v ){ return vertex( X + v.X, Y + v.Y ); }
vertex operator -( vertex v ){ return vertex( X - v.X, Y - v.Y ); }
double dot( vertex v ){ return X * v.X + Y * v.Y; }
double length() { return sqrt(X * X + Y * Y ); }
vertex normalize( bool &bOk ){
double len = length(); bOk = false;
if( len > MY_EPSILON ){ bOk = true; return vertex( X/len, Y/len ); }
return *this;
}
};
std::ostream & operator << ( std::ostream & s, vertex v ){
s << std::setprecision(6) << "(" << v.X << "," << v.Y << ") ";
return s;
}
Dot product of two vectors:
To verify if the right angle is at the point B, we can use the following function, it will compute the dot product of two normalized vectors of AB and BC :
bool isRighAngle( vertex a, vertex b, vertex c){
bool bOkAB, bOkBC;
vertex uAB = ( b - a ).normalize( bOkAB ), uBC = ( c - b ).normalize( bOkBC );
return bOkAB && bOkBC && fabs(uAB.dot( uBC )) < MY_EPSILON;
}
Note that when we compaire a double value with zero, use always an epsilon, there is no zero absolut for a double. This function also return false if one of normalized vectors cannot be computed (two points are too close to each other).
Compute the last coordinate from the right angle :
This following function return true if the last cordinate D is calculated from the right angle B:
bool getLastCoordinateIfRightAngle( vertex a, vertex b, vertex c, vertex & d ){
if( isRighAngle( a, b, c ) ){
d = (a + c) - b;
return true;
}
return false;
}
Look for the right angle:
So to find the last coordinate D from 3 vertexs A, B and C, you should do the test for three cases of right angle, the test stops when a solution was found :
bool getLastCoordinate( vertex a, vertex b, vertex c, vertex &d ){
if( getLastCoordinateIfRightAngle( a, b, c, d ) //if B is at the right angle
|| getLastCoordinateIfRightAngle( a, c, b, d ) //if C is at the right angle
|| getLastCoordinateIfRightAngle( b, a, c, d ) ) //if A is at the right angle
{
return true;
}
//No right angle found.
return false;
}
Quick test :
We can do a quick test if it works:
int main(int argc, char *argv[])
{
vertex A(0.0, 0.0), B(1.0, 0.0), C(0.0, 1.0), D;
if( getLastCoordinate( A, B, C, D ) ){
std::cout << "D coordinate " << D << " found from inputs : " << A << B << C << std::endl;
}else {
std::cout << "D coordinate not found for input: " << A << B << C << std::endl;
}
return 0;
}
EPSILON CHOICE:
It depends on your domain, if you work in a very small object domain that (X, Y) are very small (close to 10E-5 for example), you will have some difficulties in calculations (floating point in GPU is very limited in precision). It's better to transform the working domain to a normal range.
In the example above, EPSILON is set to 10E-6. If the length between two points is smaller to this value, the two points can be considered as an unique point - they stay in the same position).
If you have three vertices, then you have half of the rectangle: a right triangle. First you need to determine which point is at the right angle. You can do this in different ways. A way is to apply Pythagoras theorem: find the two vertices which are the farthest apart. The remaining vertex is at the right angle (Another way could be calculating the dot product between each pair of edges, and the one which closest to zero forms right angle).
Let's call the vertex at the right angle A, and the other two B and C. Now, the vectors of the two shorter edges of the right triangle is B-A and C-A. If you add these edges to A, you'll get the 4th vertex:
D=A+(B-A)-(C-A)=B+C-A
Having the coordinates of three of the four vertices of the rectangle, we can find the 4th vertex coordinates by the given below formula.
x4 = x1 ^ x2 ^ x3;
y4 = y1 ^ y2 ^ y3;
^ = bitwise XOR.
What happens here is that XORing them together causes the pair of coordinates that are the same to cancel.
I hope this helps.

finding the edge connection point between two AABB area

Lets say I have two AABB based areas, each area defined by two coordinates mins{x, y} and maxs{x, y}, I want to find the middle connection point between them.
Since my english is not good, I can't explain all with my words,
see the following picture for easier understanding:
http://i.*.com/WokivEe.png
All I need to find is the red point coordinates.
so If we move this into programming question, actual data structures would look like this:
struct Vec2D {
float x, y;
}
struct Rectangle {
Vec2D min;
Vec2D max;
}
Rectangle obj[2]
Anyone got an idea for an algorithm?
Along either the X or Y axis, sort the coordinates of the sides that touch into order. Then average the 2nd and 3rd ones in that list to find their midpoint. I hope this answers the question sufficiently.
Here is a little algorithm that first find which sides of the objects are closest, and then uses the 4 points along the common side to make a list, sorted along the common axis. The average of the 2 middle points of the sorted list are the answer. This will work for both horizontal and vertical sides. I added accessor functions to the data structures so that they can be indexed; e.g., for a Vec2D, coordinate(0) is the x value and coordinate(1) is the y value.
#include <math.h>
#include <iostream>
#include <limits>
struct Vec2D {
float x, y;
float coordinate(int axis)
{
return (axis & 1) ? y : x;
}
};
struct Rectangle {
Vec2D min;
Vec2D max;
Vec2D corner(int j)
{
return (j & 1) ? max : min;
}
// Get the other corner along the given axis
Vec2D along(int j, int ax)
{
Vec2D p = corner(j);
if (0 == ax)
{
p.x = corner(1-j).x;
}
else
{
p.y = corner(1-j).y;
}
return p;
}
};
using namespace std;
inline Vec2D* vp(const void* p)
{
return (Vec2D*) p;
}
static int compare_x(const void*a, const void*b)
{
if (vp(a)->x < vp(b)->x)
{
return -1;
}
else
if (vp(a)->x > vp(b)->x)
{
return 1;
}
return 0;
}
static int compare_y(const void*a, const void*b)
{
if (vp(a)->y < vp(b)->y)
{
return -1;
}
else
if (vp(a)->y > vp(b)->y)
{
return 1;
}
return 0;
}
int main(void) {
int ax; // axis index
int c0, c1;
float gap = numeric_limits<float>::max();
struct Rectangle obj[2] = {0,2,10,10,10,5,15,20};
struct
{
int ax,c0,c1;
} closest;
// Find out which sides are the closest to each other
for(ax = 0; 2 > ax; ++ax) // Look at x axis and y axis
{
for(c0 = 0; 2 > c0; ++c0) // Look at both corners of obj[0]
{
for(c1 = 0; 2 > c1; ++c1) // Look at both corners of obj[1]
{
float dist = fabs(obj[0].corner(c0).coordinate(ax) - obj[1].corner(c1).coordinate(ax));
if (dist < gap)
{
gap = dist;
closest.ax = ax;
closest.c0 = c0;
closest.c1 = c1;
}
}
}
}
int other = 1 - closest.ax; // The other axis
cout << "The closest gap is along the " << (closest.ax ? 'y' : 'x') << " axis\n";
cout << "The common side is along the " << (other ? 'y' : 'x') << " direction\n";
// Make a list of the 4 points along the common side
Vec2D list[4];
list[0] = obj[0].corner(closest.c0);
list[1] = obj[0].along(closest.c0, other);
list[2] = obj[1].corner(closest.c1);
list[3] = obj[1].along(closest.c1, other);
// Sort them into order along the common axis
qsort(list, 4, sizeof(Vec2D), closest.ax ? compare_x : compare_y);
// Get the average of the 2 middle points along the common axis.
Vec2D answer = {
(list[1].x + list[2].x) / 2,
(list[1].y + list[2].y) / 2
};
cout << "(" << answer.x << "," << answer.y << ")\n";
}

Find all points of a grid within a circle, ordered by norm

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);

Memory comparison, which is faster?

I have a 3D vector class. The private variables are defined:
union {
struct {
double x;
double y;
double z;
};
double data[3];
};
In implementing operator==, which is faster?
return this->x == v.x && this->y == v.y && this->z == v.z;
OR
return memcmp(this->data, v.data) == 0;
Unfortunately the two aren't equivalent. (Specifically NaNs and signed zeros don't use bitwise comparison inside the FPU).
So you should make your choice based on correctness, not speed.