Point inside or in boundary of polygon - c++

I'm using the algorithm in http://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html,
but when the input point is in boundary, that algorithm gives wrong for me. Can anyone help me with point in boundary case?
Any help is appreciated.
This is the main function
#include <iostream>
#include <Polygon.h>
using namespace std;
int main()
{
vector<Point> v;
//v.push_back(make_pair(3.0,3.0));
v.push_back(make_pair(1.0,1.0));
v.push_back(make_pair(1.0,5.0));
v.push_back(make_pair(5.0,5.0));
v.push_back(make_pair(5.0,1.0));
Polygon *p = new Polygon(v);
cout << "A: " << p->IsInside(make_pair(1.0,3.0)) << endl;
cout << "B: " << p->IsInside(make_pair(3.0,1.0)) << endl;
cout << "C: " << p->IsInside(make_pair(5.0,3.0)) << endl;
cout << "D: " << p->IsInside(make_pair(3.0,5.0)) << endl;
delete p;
return 0;
}
This is the checking function
bool Polygon::IsInside(Point p)
{
/*determine whether a point is inside a polygon or not
* polygon's vertices need to be sorted counterclockwise
* source :
* http://www.ecse.rpi.edu/~wrf/Research/Short_Notes/pnpoly.html
*/
bool ans = false;
for(size_t c=0,d=this->vertices.size()-1; c<this->vertices.size(); d=c++)
{
if( ((this->vertices[c].y > p.y) != (this->vertices[d].y > p.y)) &&
(p.x < (this->vertices[d].x - this->vertices[c].x) * (p.y - this->vertices[c].y) /
(this->vertices[d].y - this->vertices[c].y) + this->vertices[c].x) )
ans = !ans;
}
return ans;
}

From the website documentation:
"PNPOLY partitions the plane into points inside the polygon and points outside the polygon. Points that are on the boundary are classified as either inside or outside. ..."
Please read the documentation available on the site again.It answers your question.
In the end, you will probably have to to live with the ambiguity of floating point calculations.

Related

Specific right-angled Triangles are not being recognized as right-angled in Cpp

I have to take the coordinates of the vertices of a triangle from the user and tell if it is a right-angled triangle or not. I'm using Pythagoras Theorem to Find out i.e. h * h = b * b + p * p
But surprisingly this doesn't work for some specific right-angled triangles.
Here is one such Triangle:
Vertex A: (x, y) = (1, 3)
Vertex B: (x, y) = (1, 1)
Vertex C: (x, y) = (5, 1)
It calculates perfectly, which I figured out by printing the calculation, but still doesn't work.
Then I tried by using sqrt() function from the cmath library this way:
h = sqrt(b * b + p * p)
Logically it is the same, but it worked.
I want to understand, why the earlier method is not working?
Here is a simplified version of My Code:
#include <iostream>
#include <cmath>
using namespace std;
class Vertex {
double x, y;
public:
void take_input(char obj) {
cout << endl << " Taking Coordinates of Vertex " << obj << ": " << endl;
cout << " Enter the x component: ";
cin >> x;
cout << " Enter the y component: ";
cin >> y;
}
double distance(Vertex p) {
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
return dist;
}
};
class Triangle {
Vertex a, b, c;
public:
void take_inp(string obj) {
cout << endl << "Taking Vertices of the Triangle " << obj << ": " << endl;
cout << " Verteces should be in a counter clockwise order (as per convention)." << endl;
a.take_input('A');
b.take_input('B');
c.take_input('C');
}
void is_rt_ang() {
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
/*
// Strangely this attempt works which is logically the same:
double h = a.distance(c);
double bp = sqrt(a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c));
*/
if (h == bp) {
cout << "Angle is 90" << endl;
cout << h << " = " << bp << endl;
cout << "It is Right-Angled" << endl;
}
else {
cout << "Angle is not 90!" << endl;
cout << h << " != " << bp << endl;
cout << "It is Not a Right-Angled" << endl;
}
}
};
int main()
{
Triangle tri1, tri2;
tri1.take_inp("tri1");
tri1.is_rt_ang();
return 0;
}
The line
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
in the Vertex::distance method gives you an approximation of a square root which is rarely going to coincide with an exact answer. This is because most real numbers can't be represented in floating point arithmetic.
But in given code sample you can make do without sqrt. Replace Vertex::distance method with a method
double distance_square(Vertex p) {
double dist_square = (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y);
return dist_square;
}
and call it like this in Triangle::is_rt_ang:
double h = a.distance_square(c);
double bp = a.distance_square(b) + b.distance_square(c);
This solution is still flawed because floating-point multiplication is also a subject to rounding errors. But if it is guaranteed that you are going to work only with integer coordinates, you can replace all doubles in your code with ints and for them there is no problem with multiplication (besides possibly going out of bounds for large numbers).
EDIT: Also a comment on printing
It calculates perfectly, which I figured out by printing the
calculation, but still doesn't work.
When you print doubles you need to set precision manually in order to avoid rounding. If in your code I replace a line
cout << h << " != " << bp << endl;
with
cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed << h << " != " << bp << endl;
then for example triangle from the question I get the output
Angle is not 90!
20.000000000000004 != 20.000000000000000
It is Not a Right-Angled
For this to compile you will need to add #include <limits> and #include <iomanip>.
In your is_rt_ang function you're assuming that your hypotenuse is always going to be the edge AC, but it doesn't seem like you're doing anything to verify this.
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
You could try getting the squares of all your distances first, (AC)^2, (AB)^2, and (BC)^2, then finding the candidate for hypotenuse by taking the max value out of the three, then do something like:
bool isRightTriangle = max == (min1 + min2)
You may also be running into some kind of round-off error with floating point numbers. It is common to use a an epsilon value when comparing floating point numbers because of the inherent round-off errors with them. If you don't need floating point values maybe use an integer, or if you do need floating point values try using an epsilon value in your equalities like:
abs(h - bp) <= epsilon
You should be able to find more information about floating point values, round-off errors, and machine epsilons on the web.
Here is a link to a SO Q/A that talks about floating point math that may be a good resource for you: Is floating point math broken?

Interval for bisection method

I've been assigned a project to determine the square root of a number without using division or the math.h library. Upon doing my own research I've decided to tackle the problem by using the bisection method. I used the pseudo code portion from the Bisection Wikipedia page:
https://en.wikipedia.org/wiki/Bisection_method#Example:_Finding_the_root_of_a_polynomial
to setup the algorithm.
My Code
#include <iostream>
#include <cmath>
#include <stdlib.h>
using namespace std;
void __attribute__((weak)) check(double alt_sqrt(double));
//default check function - definition may be changed - will not be graded
void __attribute__((weak)) check(double alt_sqrt(double))
{
if(alt_sqrt(123456789.0) == sqrt(123456789.0))cout << "PASS\n";
else cout << "FAIL\n";
return;
}
//change this definition - will be graded by a different check function
double my_sqrt(double x)
{
int i = 0;
double a = 0.0; // Lower Bound
double b = x + 1; // Upper Bound
double c = 0.0; // Guess for square root
double error = 0.00001;
double fc = 0.0;
while(i < 10000)
{
c = (a+b)*0.5;
fc = c * c - x;
if(abs(fc) < error || (b-a)*0.5 < error) // Check for solution
{
cout << "Square root is: " << c << endl;
break;
}
if(fc < 0) // Setup new interval
{
a = c;
cout << "a is: " << a << endl;
}
else b = c;
cout << "b is: " << b << endl;
i++;
}
return c;
}
//Do not change this function
int main()
{
check(my_sqrt);
return 0;
}
The output I am currently getting for my professor's test case in main is
Square root is: 1.23457e+08
FAIL
When the correct output should be
Square root is: 11,111.11106
PASS
I believe that I am going wrong in the way that I setup my new intervals. My thinking is that if the difference between the two values is negative, then I need to push the lower bound up, and if the difference is positive, then I need to bump the upper bound down.
I would appreciate any advice y'all could give me. Thank you for your time.
The condition fb - fa < 0 is wrong because ignoring floating-point errors, fa < fb, which is a * a - x < b * b < x will be always true for 0 <= a < b.
Changing the condition to fc < 0 improved the accuracy, but unfortunately this improvement coundl't make the program print "PASS". To improve the accuracy to have the program print "PASS", delete the harmful breaking part
if(abs(fc) < error || (b-a)*0.5 < error) // Check for solution
{
cout << "Square root is: " << c << endl;
break;
}
Removing this harmful breaking and adding the line
cout << "Square root is: " << c << endl;
just before
return c;
gave me
Square root is: 11111.1
PASS
but unfortunately this is not what you want.
To have what you want printed,
#include <iomanip>
should be added and the printing part should be
std::cout.imbue(std::locale(""));
cout << fixed << setprecision(5) << "Square root is: " << c << endl;

Gas Particle simulation Collision calculation C++

This I feel is a rather complicated problem, I hope I can fit it in to small enough of a space to make it understandable. I'm presently writing code to
simulate Ideal gas particles inside a box. I'm calculating if two particles will collide having calculated the time taken for them to reach their closest point. (using an example where they have head on collision).
In this section of code I need to find if they will collide at all for two particles, before then calculating at what time and how they collide etc.
Thus for my two paricles:
Main.cpp
Vector vp1(0,0,0);
Vector vv1(1,0,0);
Vector vp2(12,0,0);
Vector vv2(-1,0,0);
Particle Particle1(1, vp1, vv1);
Particle Particle2(1, vp2, vv2);
Particle1.timeToCollision(Particle2);
Within my program I define a particle to be:
Header File
class Particle {
private:
Vector p; //position
Vector v; //velocity
double radius; //radius
public:
Particle();
Particle(double r, const Vector Vecp, const Vector Vecv);
void setPosition(Vector);
void setVelocity(Vector);
Vector getPosition() const;
Vector getVelocity() const;
double getRadius() const;
void move(double t);
double timeToCollision(const Particle particle);
void collideParticles(Particle);
~Particle();
};
Vector is another class that in short gives x, y, z values. It also contains multiple functions for manipulating these.
And the part that I need help with, within the .cpp (Ignore the cout start and letters etc, they are simple checks where my code exits for tests.)
Given the equations:
I have already written code to do the dot product and modulus for me and:
where
s is distance travelled in time tac.
double Particle::timeToCollision(const Particle particle){
Vector r2 = particle.getPosition();
Vector r1 = p;
Vector v2 = particle.getVelocity();
Vector v1 = v;
Vector r0 = r2 - r1;
Vector v = v2 - v1;
double modv;
double tca;
double result = 0;
double bsqr;
modv = getVelocity().modulus();
cout << "start" << endl;
if(modv < 0.0000001){
cout << "a" << endl;
result = FLT_MAX;
}else{
cout << "b" << endl;
tca = ((--r0).dot(v)) / v.modulusSqr();
// -- is an overridden operator that gives the negation ( eg (2, 3, 4) to (-2, -3, -4) )
if (tca < 0) {
cout << "c" << endl;
result = FLT_MAX;
}else{
cout << "d" << endl;
Vector s(v.GetX(), v.GetY(), v.GetZ());
s.Scale(tca);
cout << getVelocity().GetX() << endl;
cout << getVelocity().GetY() << endl;
cout << getVelocity().GetZ() << endl;
double radsqr = radius * radius;
double bx = (r0.GetX() * r0.GetX() - (((r0).dot(v)) *((r0).dot(v)) / v.modulusSqr()));
double by = (r0.GetY() * r0.GetY() - (((r0).dot(v)) *((r0).dot(v)) / v.modulusSqr()));
double bz=(r0.GetZ() * r0.GetZ() - (((r0).dot(v)) * ((r0).dot(v)) / v.modulusSqr()));
if (bsqr < 4 * radsqr) {
cout << "e" << endl;
result = FLT_MAX;
} else {
}
cout << "tca: " << tca << endl;
}
}
cout << "fin" << endl;
return result;
}
I have equations for calculating several aspects, tca refers to Time of closest approach.
As written in the code I need to check if b > 4 r^2, I Have made some attempts and written the X, Y and Z components of b out. But I'm getting rubbish answers.
I just need help to establish if I've already made mistakes or the sort of direction I should be heading.
All my code prior to this works as expected and I've written multiple tests for each to check.
Please inform me in a comment for any information you feel I've left out etc.
Any help greatly appreciated.
You had several mistakes in your code. You never set result to a value different from 0 or FLT_MAX. You also never calculate bsqr. And I guess the collision happens if bsqr < 4r^2 and not the other way round. (well i do not understand why 4r^2 instead of r^2 but okay). Since you hide your vector implementation I used a common vector library. I also recommend to not use handcrafted stuff anyway. Take a look into armadillo or Eigen.
Here you go with a try in Eigen.
#include <iostream>
#include <limits>
#include <type_traits>
#include "Eigen/Dense"
struct Particle {
double radius;
Eigen::Vector3d p;
Eigen::Vector3d v;
};
template <class FloatingPoint>
std::enable_if_t<std::is_floating_point<FloatingPoint>::value, bool>
almost_equal(FloatingPoint x, FloatingPoint y, unsigned ulp=1)
{
FloatingPoint max = std::max(std::abs(x), std::abs(y));
return std::abs(x-y) <= std::numeric_limits<FloatingPoint>::epsilon()*max*ulp;
}
double timeToCollision(const Particle& left, const Particle& right){
Eigen::Vector3d r0 = right.p - left.p;
Eigen::Vector3d v = right.v - left.v;
double result = std::numeric_limits<double>::infinity();
double vv = v.dot(v);
if (!almost_equal(vv, 0.)) {
double tca = (-r0).dot(v) / vv;
if (tca >= 0) {
Eigen::Vector3d s = tca*v;
double bb = r0.dot(r0) - s.dot(s);
double radius = std::max(left.radius, right.radius);
if (bb < 4*radius*radius)
result = tca;
}
}
return result;
}
int main()
{
Eigen::Vector3d vp1 {0,0,0};
Eigen::Vector3d vv1 {1,0,0};
Eigen::Vector3d vp2 {12,0,0};
Eigen::Vector3d vv2 {-1,0,0};
Particle p1 {1, vp1, vv1};
Particle p2 {1, vp2, vv2};
std::cout << timeToCollision(p1, p2) << '\n';
}
My apologies for a very poorly worded question that was to long and bulky to make much sense of. Luckily I have found my own answer to be much easier then initially anticipated.
double Particle::timeToCollision(const Particle particle){
Vector r2=particle.getPosition();
Vector r1=p;
Vector v2=particle.getVelocity();
Vector v1=v;
Vector r0=r2-r1;
Vector v=v2-v1;
double modv;
double tca = ((--r0).dot(v)) / v.modulusSqr();
double bsqr;
double result=0;
double rColTestx=r0.GetX()+v.GetX()*tca;
double rColTesty=r0.GetY()+v.GetY()*tca;
double rColTestz=r0.GetZ()+v.GetZ()*tca;
Vector rtColTest(rColTestx, rColTesty, rColTestz);
modv=getVelocity().modulus();
cout << "start " << endl;
if(modv<0.0000001){
cout << "a" << endl;
result=FLT_MAX;
}else{
cout << "b" << endl;
if (tca < 0) {
cout << "c" << endl;
result=FLT_MAX;
}else{
cout << "d" << endl;
Vector s(v.GetX(), v.GetY(), v.GetZ());
s.Scale(tca);
cout << getVelocity().GetX() << endl;
cout << getVelocity().GetY() << endl;
cout << getVelocity().GetZ() << endl;
double radsqr= radius*radius;
bsqr=rtColTest.modulusSqr();
if (bsqr < 4*radsqr) {
cout << "e" << endl;
cout << "collision occurs" << endl;
result = FLT_MAX;
} else {
cout << "collision does not occurs" << endl;
}
}
}
cout << "fin" << endl;
return result;
}
Sorry its a large section of code. Also FLT_MAX is from the cfloat lib. I didn't stat this in my question. I found this to work for several examples I calculated on paper to check.
To be Clear, the return resultand result=0 were arbitrary. I later edit to return time but for this part didn't need or want that.

This predefined function slowing down my program's performance

I am working on a PCL (Point Cloud Library) project. One part of it requires me to clip point clouds, for which I need to know the minimum and maximum coordinates of given point cloud.
PCL provides a predefined function called getminmax3d(). I tried and It works well, The only problem is, It takes a lot of time when I input a large point cloud file. I made my own definition of getminmax3d() and it takes lesser time. I am not understanding why these two behave like this.
I tried with 5 point cloud data files. In all cases, program that uses predefined function takes long time as compare to the program for which I defined the definition.
Here is the code:
First implementation - It uses predefined function getminmax3d()
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/common.h>
int main (int, char**)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
cloud = pcl::PointCloud<pcl::PointXYZ>::Ptr (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ> ("your_pcd_file.pcd", *cloud);
pcl::PointXYZ minPt, maxPt;
pcl::getMinMax3D (*cloud, minPt, maxPt);
std::cout << "Max x: " << maxPt.x << std::endl;
std::cout << "Max y: " << maxPt.y << std::endl;
std::cout << "Max z: " << maxPt.z << std::endl;
std::cout << "Min x: " << minPt.x << std::endl;
std::cout << "Min y: " << minPt.y << std::endl;
std::cout << "Min z: " << minPt.z << std::endl;
return (0);
}
Second implementation - This source code uses a user-defined function definition to replace functionality of getminmax3d()
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/time.h>
int main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ> ("rhino.pcd", *cloud) == -1) //* load the file
{
PCL_ERROR ("Couldn't read file rhino.pcd \n");
return (-1);
}
float min_x = cloud->points[0].x, min_y = cloud->points[0].y, min_z = cloud->points[0].z, max_x = cloud->points[0].x, max_y = cloud->points[0].y, max_z = cloud->points[0].z;
pcl::StopWatch watch;
for (size_t i = 1; i < cloud->points.size (); ++i){
if(cloud->points[i].x <= min_x )
min_x = cloud->points[i].x;
else if(cloud->points[i].y <= min_y )
min_y = cloud->points[i].y;
else if(cloud->points[i].z <= min_z )
min_z = cloud->points[i].z;
else if(cloud->points[i].x >= max_x )
max_x = cloud->points[i].x;
else if(cloud->points[i].y >= max_y )
max_y = cloud->points[i].y;
else if(cloud->points[i].z >= max_z )
max_z = cloud->points[i].z;
}
pcl::console::print_highlight ("Time taken: %f\n", watch.getTimeSeconds());
std::cout << "Min x: " << min_x <<"\t";
std::cout << "Max x: " << max_x << std::endl;
std::cout << "Min y: " << min_y <<"\t";
std::cout << "Max y: " << max_y << std::endl;
std::cout << "Min z: " << min_z <<"\t";
std::cout << "Max z: " << max_z << std::endl;
return (0);
}
I tried both programs on following 5 point cloud files.
Result obtained:
ttf : Time taken factor
ttf = 15 means user definition is about 15 times faster than predefined functions. ttf value is measured by taking average of 10 trials for both implementations.
PCD file Filetype File size ttf
Rhino.pcd XYZ 2.57 MB 15.260
Bun_zipper XYZCI 1.75 MB 17.422
Armadillo XYZ 5.26 MB 15.847
Dragon_vrip XYZ 14.7 MB 17.013
Happy_vrip XYZ 18.0 MB 14.981
I am wondering why predefined function is taking more time? I want to reduce my program source code lines. I've always believed that using standard header files and their function gives you best performance, But in this case it seems to fail.
This is where you can find standard definition.
Would anyone please help me to find out why second implementation takes less times(approx 15 times), even the standard definition of getminmax3d() is similar to mine.
pcl::getMinMax3D has a very inefficient implementation. To search for the minimum and max point it does the following:
Eigen::Array4f min_p, max_p;
min_p.setConstant (FLT_MAX);
max_p.setConstant (-FLT_MAX);
for (size_t i = 0; i < cloud.points.size (); ++i)
{
// ... (check the validity of the point if it is not a dense cloud)
pcl::Array4fMapConst pt = cloud.points[i].getArray4fMap ();
min_p = min_p.min (pt);
max_p = max_p.max (pt);
}
And if you check for the getArray4fMap() function:
typedef Eigen::Map<Eigen::Array4f, Eigen::Aligned> Array4fMap;
inline pcl::Array4fMap getArray4fMap() const {
return (pcl::Array4fMap(data));
}
For each point in the cloud it is constructing an Eigen::Map and then comparing it against the current minimum and maximum points. This is VERY inefficient.
The predefined function pcl::getMinMax3D is able to be faster with optimization flags set and in Release. Since if SSE intrinsics are used by Eigen, then the operations happen on 4 aligned bytes.
More information at
https://gitter.im/PointCloudLibrary/pcl?at=5e3899d06f9d3d34981c0687

Boundary value analysis in C++ with CppUnit

I'm trying to implement boundary tests in CppUnit. I want to check the limit value itself as well as the boundaries around this limit.
For the upper boundary I wanted to add the smallest inkrement possible. For double this increment can be accessed with
numeric_limits<double>::epsilon()
However, if I add epsilon to my limit I get Not-a-Number (NaN) as result:
#include <stdio.h>
#include <iostream>
#include <limits>
#include <math.h>
using namespace std;
const double WARNING_LIMIT = 8000.0;
int main(void) {
double warningLowerLimit = WARNING_LIMIT - numeric_limits<double>::epsilon();
if(warningLowerLimit < WARNING_LIMIT ) {
cout << "lower" << endl;
}
else if (warningLowerLimit > WARNING_LIMIT) {
cout << "upper" << endl;
}
else if ( fabs(warningLowerLimit) < 0.001) {
cout << "same" << endl;
}
else {
cout << "NaN" << endl; // <-- result
}
}
Can somebody please explain me, why the result is not lower that the limit?
Best regards
else if ( fabs(warningLowerLimit) < 0.001) {
cout << "same" << endl;
}
That should be
fabs(warningLowerLimit - WARNING_LIMIT)
there. Without checking the difference, you get to the cout << "NaN" if warningLowerLimit == WARNING_LIMIT for example.