i have this code to find the status of 2 lines there are 3 cases:
1- the lines are intersect in one point
2- they are parallel
3- special case of parallel they are identical[same line]
and here is my code but i still can't understand this two parts of code
if(!D && (Dx || Dy))
puts("NONE"); // the lines are parallel
if(!D && !Dx && !Dy)
puts("LINE"); // they are the same lime
why when the determinater is zero and dx = 0 or dy = 0 then they are parallel and when d = 0 and dx = 0 and dy = 0 then they are the same line
i know when determinater equal to zero then there is no unique solution but can't understand the part of !DX and !DY and DX || DY
Here is the full code
#include <iostream>
using namespace std;
struct point{
int x , y;
};
struct segment{
point s , e;
};
int main(){
int n;
scanf("%d" , &n);
puts("INTERSECTING LINES OUTPUT");
while(n--){
segment a , b;
scanf("%d%d%d%d" , &a.s.x , &a.s.y , &a.e.x , &a.e.y);
scanf("%d%d%d%d" , &b.s.x , &b.s.y , &b.e.x , &b.e.y);
double a1 , b1 , c1 , a2 , b2 , c2 , D , Dx , Dy;
a1 = a.e.y - a.s.y;
b1 = a.s.x - a.e.x;
c1 = a1 * (a.s.x) + b1 * (a.s.y);
a2 = b.e.y - b.s.y;
b2 = b.s.x - b.e.x;
c2 = a2 * (b.s.x) + b2 * (b.s.y);
D = a1 * b2 - a2 * b1;
Dx = c1 * b2 - c2 * b1;
Dy = a1 * c2 - a2 * c1;
if(!D && (Dx || Dy))
puts("NONE"); // the lines are parallel
if(!D && !Dx && !Dy)
puts("LINE"); // they are the same line
else printf("POINT %.2f %.2f\n" , (double)Dx / D , (double) Dy / D);
}
return 0;
}
One way to think about this, roughly speaking, is that when D==0 and Dx==0 and Dy==0, then the "coordinates of the intersection point" Dx/D and Dy/D are indeterminate forms 0/0 which could be any number. That means that the lines intersect in a whole bunch of points, which is only possible if they are the same line.
On the other hand, if D==0 and Dx!=0 or Dy!=0 (or both), then the value of Dx/D or Dy/D (or both) is infinity. In other words, the lines intersect at infinity (only), which is another way of saying that the lines are parallel and not coincident.
Testing if(D) for a double is a bad idea, for a couple of reasons. 1) It's not clear. Understanding that expression requires some fairly detailed knowledge of type conversions in the language that frankly not every programmer has. 2) Rounding errors and other numerical instability issues could interfere with the calculation and instead of D==0 you have some tiny D not equal to 0. Then !D is considered true, even though it should be false without the rounding error. Instead you should compare whether abs(D) < some tolerance which is slightly bigger than 0.
Finally your program is vulnerable to overflow issues: if the two lines are close in slope, but otherwise completely reasonable, the intersection point may be extremely large. This is a situation that makes sense in a purely mathematical context, but not so much sense on a computer. Instead, a better question to ask would be whether the intersection lies within the line segments defined by the points. There is a discussion of that problem on the Wikipedia page.
The feedback that worries about floating point arithmetic is on point (Ha!). Since the input is integral, though, I might suggest doing the math with integer types.
The questions you are asking boil down to seeing if two fractions are equivalent. I suggest the following helper class:
struct ratio {
int dx;
int dy;
ratio(int dxIn, int dyIn) :
dx(dxIn), dy(dyIn) {
}
bool isEquivalent(ratio rhs) const {
if ((dx == 0 && dy == 0) || (rhs.dx == 0 && rhs.dy == 0))
return (dx == 0 && dy == 0) && (rhs.dx == 0 && rhs.dy == 0);
return dx * rhs.dy == dy * rhs.dx;
}
};
Each line segment is converted into (a,b,c) coordinates for the extended line which form the line equation a*x+b*y+c=0. What you need to know, is that the vector (a,b) is orthogonal to the line.
The quantity D = a1*b2 - a2*b1 is the cross product between the two orthogonal vectors. As you know the cross product of two parallel vectors is 0. So if that is true, the two lines are either coincident or parallel.
The intersection point is defined as (Dx/D,Dy/D) where Dx=b1*c2-b2*c1 and Dy=a2*c1-a1*c2, so when all equals zero Dx=Dy=D=0 the intersection point is undefined, meaning the lines are coincident. Otherwise if only D=0 the intersection point is at infinity and the lines are parallel.
The rest is just typical confusing C syntax.
Related
I have an assignment in codeforces which says:
Like all problem solvers, Ebram loves eating crepe! As we all know, crepe usually served in a triangular shape. Now Ebram wants to know how large can a crepe side be! So he tries to draw a triangle on a plane using three points and calculate the maximum length of the three sides of the triangle. But sometimes he falls asleep as he has been busy with the team preparing the training problems! As a result, the three points he uses may not form a triangle that could represent a piece of crepe! A triangle can represent a piece of crepe only if it has a positive area. So you are here to help Ebram! Given the coordinates Ebram used, determine whether they form a triangle that could represent a piece of crepe or not.
Input:
Three integer coordinates (X,Y) that represent the three points Ebram used. Each point on a separate line.
Output: If the points form a triangle that can represent a piece of crepe, print the square of the maximum length of the three sides of the triangle. Otherwise print "Poor boy"
Examples
input
1 1
3 1
3 9
output
68
input
-10 8
9 100
3 8
output
8825
input
7 3
3 3
19 3
output
Poor boy
Here is my code that I used:
#include <iostream>
#include <cmath>
using namespace std;
int main () {
double x1,y1,x2,y2,x3,y3;
double area;
double s1,s2,s3;
double slope1, slope2;
cin >> x1 >> y1;
cin >> x2 >> y2;
cin >> x3 >> y3;
slope1 =((y2-y1)/(x2-x1));
slope2 =((y3-y2)/(x3-x2));
area = 0.5*abs(((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)));
if (slope1!=slope2 && (area)!=0){
s1 = sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
s2 = sqrt(((x2-x3)*(x2-x3))+((y2-y3)*(y2-y3)));
s3 = sqrt(((x1-x3)*(x1-x3))+((y1-y3)*(y1-y3)));
if (s1 > s2 && s1 > s3)
cout<<s1*s1<<endl;
if (s2 > s1 && s2 > s3)
cout<<s2*s2<<endl;
if (s3 > s1 && s3 > s2)
cout <<s3*s3<<endl;
}
else
cout <<"Poor boy";
return 0;
}
First I find the slope1 and slope2 to check if the three points aren't at the same line. So If they're not equal it forms a triangle (crepe).
Using this:
slope1 =((y2-y1)/(x2-x1));
slope2 =((y3-y2)/(x3-x2));
Then I wrote a relation to find the area of triangle using this formula:
area = 0.5*abs(((x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)));
Finally I put the if statements to find if it is a triangle or not and find the length of each side of the triangle then find the maximum length and print the square of it.
if (slope1!=slope2 && (area)!=0){
s1 = sqrt(((x1-x2)*(x1-x2))+((y1-y2)*(y1-y2)));
s2 = sqrt(((x2-x3)*(x2-x3))+((y2-y3)*(y2-y3)));
s3 = sqrt(((x1-x3)*(x1-x3))+((y1-y3)*(y1-y3)));
if (s1 > s2 && s1 > s3)
cout<<s1*s1<<endl;
if (s2 > s1 && s2 > s3)
cout<<s2*s2<<endl;
if (s3 > s1 && s3 > s2)
cout <<s3*s3<<endl;
}
else
cout <<"Poor boy";
return 0;
}
I tested the code in my compiler and it runs the i/o shown in the example perfectly fine. I submitted the code on codeforces but I stuck wrong answer at test 8 I don't know why?, and my code runs inputs and outputs fine. I will be very pleased if you help guys.
As in Sani's answer, I recommend calculating the rise and run between each pair of points:
rise1 = y2 - y1
rise2 = y3 - y2
rise3 = y1 - y3
run1 = x2 - x1
run2 = x3 - x2
run3 = x1 - x3
Also the same, I recommend checking whether any two points are coincident. Note that this is equivalent to what Sani's code is checking:
if (rise1 = run1 = 0) or (rise2 = run2 = 0) or (rise3 = run3 = 0) then
print "Poor Boy"
return 0
Now, similar to Sani, we move on to checking whether the points are on a line. However, we can simplify the conditions to check somewhat. Note that, if no two points are on a vertical line, then the three points are on one line if the slopes between any two points are equal. That is, m1 = m2, m2 = m3, or m3 = m1, equivalently. We can check whether m1 = m2. This is true when rise1/run1 = rise2/run2, which is safe since we assume no points are on a vertical line. We can rearrange this to rise1 * run2 = rise2 * run1, again safely. If no two points are on a vertical line, this is the only check we need.
What if two points are on a vertical line? Then at least one of run1 and run2 will be zero. However, because we have already guaranteed no two points are coincident, we can be absolutely sure that if either of these is zero, the corresponding rise is non-zero. There are two other cases (besides no two points being on a vertical line):
Exactly two points are on a vertical line. Then either run1 or run2, but not both, are zero. Without loss of generality, assume run1 is zero. Then the condition rise1 * run2 = rise2 * run1 simplifies to rise1 * run2 = 0. Because we know rise1 is not zero, this is satisfied only if run2 = 0, which contradicts our assumed case. This means that, in this case, the condition we derived earlier will produce the correct result and identify the points as not being on the same line.
Three points are on a vertical line. Then both run1 and run2 are zero. Then the condition rise1 * run2 = rise2 * run1 simplifies to 0 = 0, which is always true. In this case, the condition will produce the correct result and identify three points as being on the same line.
Because the condition we derived for the case of no two points on a vertical line happens to produce the correct result for all other possible cases, we can use it in all cases (under the assumption no two points are coincident). Therefore, we don't need to check anything except rise1 * run2 = rise2 * run1:
if rise1 * run2 = rise2 * run1 then
print "Poor Boy"
return 0
Now we know we have a triangle and need to return the largest of the three sides. We need the sum of squared differences of respective coordinates. Luckily, we already have the coordinate differences, so:
d1 = (rise1 * rise1) + (run1 * run1)
d2 = (rise2 * rise2) + (run2 * run2)
d3 = (rise3 * rise3) + (run3 * run3)
return max(d1, d2, d3)
Your biggest problem is that you keep getting division by 0 on inputs where the denominator is 0 when calculating the slope. I.e. Points (3, 4), (3, 5) and (5, 6) will yield -1/0.
Another thing is that you are "over-complicating" things.
This is a step by step example for clarity how to approach this (I.e. not optimal code):
// Check if any two points are the same. I.e. no triangle
if (x1 == x2 && y1 == y2 || x1 == x3 && y1 == y3 || x2 == x3 && y2 == y3) {
cout << "Poor boy";
return 0;
}
// Check if all points are on the same horizontal or vertical line
if (x1 == x2 && x1 == x3 || y1 == y2 && y1 == y3) {
cout << "Poor boy";
return 0;
}
// Calculate the nominators and denominators
nominator1 = y2-y1;
denominator1 = x2-x1;
nominator2 = y3-y2;
denominator2 = x3-x2;
nominator3 = y1-y3;
denominator3 = x1-x3;
// Calculate the slopes, if possible.
if (denominator1 == 0) slope1 = 0;
else slope1 = nominator1 / denominator1;
if (denominator2 == 0) slope2 = 0;
else slope2 = nominator2 / denominator2;
if (denominator3 == 0) slope3 = 0;
else slope3 = nominator3 / denominator3;
// Check if the three points form a triangle or a straight line.
// I.e. if all slopes are the same, it is a line.
if ((slope1 == slope2 && slope1 == slope3)) {
cout << "Poor boy";
return 0;
}
// Calculate the square of the length of each side
// (No abs is needed since a square of negative numbers is positive.)
// (Also no sqrt is needed since we're only interrested in the square of the longest side.)
side1 = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
side2 = (x3-x2)*(x3-x2) + (y3-y2)*(y3-y2);
side3 = (x1-x3)*(x1-x3) + (y1-y3)*(y1-y3);
// Note: This can be used instead which is the same calculation:
// side1 = denominator1 * denominator1 + nominator1 * nominator1;
// side2 = denominator2 * denominator2 + nominator2 * nominator2;
// side3 = denominator3 * denominator3 + nominator3 * nominator3;
// Get the longest side squared.
maxSide = side1 > side2 ? side1 > side3 ? side1 : side2 > side3 ? side2 : side3;
cout << maxSide;
Disclaimer: Code not tested!
I know there are many sites which explain how to check for an intersection of two lines, but I find it utterly boring to just copy and paste code for such a simple mathematical task. The more it frustrates me that I cannot get my code to work. I know questions with "What is wrong in my code?" are stupid, but I don't know what the hell is wrong with my mathematics / code, also my code is documented nicely (except of admittedly bad variable naming), so I guess there should be someone who is interested in the math behind it:
bool segment::checkforIntersection(QPointF a, QPointF b) { //line 1: a+bx, line 2: c+dx, note that a and c are called offset and bx and dx are called gradients in this code
QPointF bx = b-a;
double firstGradient = bx.y() / bx.x(); //gradient of line 1
//now we have to calculate the offset of line 1: we have b from a+bx. Since QPointF a is on that line, it is:
//a + b * a.x = a.y with a as free variable, which yields a = a.y - b*a.x.
//One could also use the second point b for this calculation.
double firstOffset = a.y() - firstGradient * a.x();
double secondGradient, secondOffset;
for (int i = 0; i < poscount-3; i++) { //we dont check with the last line, because that could be the same line, as the one that emited intersection checking
QPointF c = pos[i];
QPointF d = pos[i+1];
QPointF dx = d-c;
secondGradient = dx.y() / dx.x(); //same formula as above
secondOffset = c.y() - secondGradient * c.x();
//a+bx=c+dx <=> a-c = (d-b)x <=> (a-c)/(d-b) = x
double x = (firstOffset - secondOffset) / (secondGradient - firstGradient);
//we have to check, if those lines intersect with a x \in [a.x,b.x] and x \in [c.x,d.x]. If this is the case, we have a collision
if (x >= a.x() && x <= b.x() && x >= c.x() && x <= d.x()) {
return true;
}
}
return false;
}
So what this does, it has 4 points a, b, c, d (line 1: a--b, line 2: c--d) (ignore the for loop) which have an absolute x and y value. First it calculates the gradient of the lines by calculating deltay/deltax. Then it calculates the offset by using the fact that point a (or c respectively) are on the lines. This way we transformed the 4 points into mathematical representation of these lines as equation a+bx, whereas a x of 0 means that we are at the first point (a / c) and a x of 1 means that we are on the second point (b/d). Next we calculate the intersection of those two lines (basic algebra). After that we check if the intersection's x value is valid. To my understanding this is all correct. Does anyone see the error?
This was empirically checked to be incorrect. The code does not give any false Positives (says there is an intersection, when there isn't), but it gives false Negatives (says there is no intersection, when there actually is). So when it says there is an Intersection it is correct, however if it says there is no intersection, you cannot always believe my algorithm.
Again, I checked online, but the algorithms are different (with some orientation tricks and something), I just wanted to come up with my own algorithm, I would be so glad if someone could help. :)
Edit: Here is a minimal reproducable not working example, this time without Qt but with C++ only:
#include <iostream>
#include <math.h>
using namespace std;
class Point {
private:
double xval, yval;
public:
// Constructor uses default arguments to allow calling with zero, one,
// or two values.
Point(double x = 0.0, double y = 0.0) {
xval = x;
yval = y;
}
// Extractors.
double x() { return xval; }
double y() { return yval; }
Point sub(Point b)
{
return Point(xval - b.xval, yval - b.yval);
}
};
bool checkforIntersection(Point a, Point b, Point c, Point d) { //line 1: a+bx, line 2: c+dx, note that a and c are called offset and bx and dx are called gradients in this code
Point bx = b.sub(a);
double firstGradient = bx.y() / bx.x(); //gradient of line 1
//now we have to calculate the offset of line 1: we have b from a+bx. Since Point a is on that line, it is:
//a + b * a.x = a.y with a as free variable, which yields a = a.y - b*a.x.
//One could also use the second point b for this calculation.
double firstOffset = a.y() - firstGradient * a.x();
double secondGradient, secondOffset;
Point dx = d.sub(c);
secondGradient = dx.y() / dx.x(); //same formula as above
secondOffset = c.y() - secondGradient * c.x();
//a+bx=c+dx <=> a-c = (d-b)x <=> (a-c)/(d-b) = x
double x = (firstOffset - secondOffset) / (secondGradient - firstGradient);
//we have to check, if those lines intersect with a x \in [a.x,b.x] and x \in [c.x,d.x]. If this is the case, we have a collision
if (x >= a.x() && x <= b.x() && x >= c.x() && x <= d.x()) {
return true;
}
return false;
}
int main(int argc, char const *argv[]) {
if (checkforIntersection(Point(310.374,835.171),Point(290.434,802.354), Point(333.847,807.232), Point(301.03,827.172)) == true) {
cout << "These lines do intersect so I should be printed out\n";
} else {
cout << "The algorithm does not work, so instead I do get printed out\n";
}
return 0;
}
So as example I took the points ~ (310,835) -- (290,802), and (333,807) -- (301,827). These lines do intersect:
\documentclass[crop,tikz]{standalone}
\begin{document}
\begin{tikzpicture}[x=.1cm,y=.1cm]
\draw (310,835) -- (290,802);
\draw (333,807) -- (301,827);
\end{tikzpicture}
\end{document}
Proof of intersection
However when running the above C++ code, it says that they do not intersect
(you may call me a pedant, but the terminology is important)
If you want to see if the line segments intersect, then rely on the parametric representation of your two segments, solve the system in the two parameters and see if both of the solution for both of the parameters falls into [0,1] range.
Parametric representation for segment [a, b], component-wise
{x, y}(t) = {(1-t)*ax+t*bx, (1-t)*ay+t*by} with t in the [0,1] range
Quick check - at t=0 you get a, at t=1 you get b, the expression is linear in t, so there you have it.
So, your (a,b) (c,d) intersection problem becomes:
// for some t1 and t2, the x coordinate is the same
(1-t1)*ax+t*bx=(1-t2)*cx+t2*dx;
(1-t1)*ay+t*by=(1-t2)*cy+t2*dy; // and so is the y coordinate
Solve the system in t1 and t2. If t1 is in the [0,1] range, then the intersection lies between a and b, the same goes for t2 in respect with c and d.
It is left as an exercise for the reader the study of what effects will have on the system above the following conditions and what checks should be implemented for a robust algorithm:
segment degeneracy - coincident ends for one or both segments
collinear segments with non-void overlap. Particular case when there's a single point of overlap (necessary, that point will be one of the ends)
collinear segments with no overlap
parallel segments
First it calculates the gradient of the lines by calculating deltay/deltax.
And what happens when deltax is very close to zero?
Look, what you are doing is exposing yourself to ill-conditioned situations - always fear divisions and straight comparison with 0.0 when it comes to computational geometry.
Alternative:
two lines will intersect if they are not parallel
two distinct lines will be parallel if their definition vectors will have a zero cross-product.
Cross-product of your (a,b) x (c,d) = (ax-bx)*(cy-dy)-(ay-by)*(cx-dx) - if this is close enough to zero, for all practical purposes there's no intersection between your lines (the intersection is so far away it doesn't matter).
Now, what remains to be said:
there will need to be a "are those line distinct?" test before going into computing the cross-product. Even more, you will need to treat degenerate cases (one or both of the lines are reduced to a point by coincident ends - like a==b and/or c==d)
the "close enough to zero" test is ambiguous if you don't normalize your definition vectors - imagine a 1 lightsecond-length vector defining the first line and a 1 parsec-length vector for the other (What test for 'proximity to zero' should you use in this case?) To normalize the two vectors, just apply a division ... (a division you say? I'm already shaking with fear) ... mmm.. I was saying to divide the resulted cross-product with hypot(ax-bx, ay-by)*hypot(cx-dx,cy-dy) (do you see why the degeneracy cases need to be treated in advance?)
after the normalization, once again, what would be a good 'proximity to zero' test for the resulted cross-product? Well, I think I can go on with the analysis for another hour or so (e.g. how far the intersection would be when compared with the extent of your {a,b,c,d} polygon), but... since the cross-product of two unitary vectors (after normalization) is sin(angle-between-versors), you may use your common sense and say 'if the angle is less that 1 degree, will this be good enough to consider the two lines parallel? No? What about 1 arcsecond?"
I have currently the following line in my program. I have two other whole number variables, x and y.
I wish to see if this new point(x, y) is on this line. I have been looking at the following thread:
Given a start and end point, and a distance, calculate a point along a line
I've come up with the following:
if(x >= x1 && x <= x2 && (y >= y1 && y <= y2 || y <= y1 && y >= y2))
{
float vx = x2 - x1;
float vy = y2 - y1;
float mag = sqrt(vx*vx + vy*vy);
// need to get the unit vector (direction)
float dvx = vx/mag; // this would be the unit vector (direction) x for the line
float dvy = vy/mag; // this would be the unit vector (direction) y for the line
float vcx = x - x1;
float vcy = y - y1;
float magc = sqrt(vcx*vcx + vcy*vcy);
// need to get the unit vector (direction)
float dvcx = vcx/magc; // this would be the unit vector (direction) x for the point
float dvcy = vcy/magc; // this would be the unit vector (direction) y for the point
// I was thinking of comparing the direction of the two vectors, if they are the same then the point must lie on the line?
if(dvcx == dvx && dvcy == dvy)
{
// the point is on the line!
}
}
It doesn't seem to be working, or is this idea whack?
Floating point numbers have a limited precision, so you'll get rounding errors from the calculations, with the result that values that should mathematically be equal will end up slightly different.
You'll need to compare with a small tolerance for error:
if (std::abs(dvcx-dvx) < tolerance && std::abs(dvcy-dvy) < tolerance)
{
// the point is (more or less) on the line!
}
The hard part is choosing that tolerance. If you can't accept any errors, then you'll need to use something other than fixed-precision floating point values - perhaps integers, with the calculations rearranged to avoid division and other inexact operations.
In any case, you can do this more simply, without anything like a square root. You want to find out if the two vectors are parallel; they are if the vector product is zero or, equivalently, if they have equal tangents. So you just need
if (vx * vcy == vy * vcx) // might still need a tolerance for floating-point
{
// the point is on the line!
}
If your inputs are integers, small enough that the multiplication won't overflow, then there's no need for floating-point arithmetic at all.
An efficient way to solve this problem is to use the signed area of a triangle. When the signed area of the triangle created by points {x1,y1}, {x2,y2}, and {x,y} is near-zero, you can consider {x,y} to be on the line. As others have mentioned, picking a good tolerance value is an important part of this if you are using floating point values.
bool isPointOnLine (xy p1, xy p2, xy p3) // returns true if p3 is on line p1, p2
{
xy va = p1 - p2;
xy vb = p3 - p2;
area = va.x * vb.y - va.y * vb.x;
if (abs (area) < tolerance)
return true;
return false;
}
This will let you know if {x,y} lies on the line, but it will not determine if {x,y} is contained by the line segment. To do that, you would also need to check {x,y} against the bounds of the line segment.
First you need to calculate the equation of your line. Then see if this equation holds true for the values of x and y that you have. To calculate the equation of your line, you need to work out where it croses the y-axis and what its gradient is. The equation will be of the form y=mx+c where m is the gradient and c is the 'intercept' (where the line crosses the y-axis).
For float values, don't use == but instead test for small difference:
if (fabs(dvcx-dvx) < delta && fabs(dvcy-dvy) < delta)
Also, you don't really need the unit vector, just the tangent:
float originalTangent = (y2 - y1) / (x2 - x1);
float newTangent = (y - y1) / (x - x1);
if (fabs(newTangent - originalTangent) < delta) { ... }
(delta should be some small number that depends on the accuracy you are expecting.)
Given that (x, y) is actually a point, the job seems a bit simpler than you're making it.
You probably want to start by checking for a perfectly horizontal or vertical line. In those cases, you just check whether x falls between x1 and x2 (or y between y1 and y2 for vertical).
Otherwise you can use linear interpolation on x and see if it gives you the correct value for y (within some possible tolerance for rounding). For this, you'd do something like:
slope = (y2-y1)/(x2-x1);
if (abs(slope * (x - x1) - y) < tolerance)
// (x,y) is on the line
else
// (x,y) isn't on the line
I have problem with precision. I have to make my c++ code to have same precision as matlab. In matlab i have script which do some stuff with numbers etc. I got code in c++ which do the same as that script. Output on the same input is diffrent :( I found that in my script when i try 104 >= 104 it returns false. I tried to use format long but it did not help me to find out why its false. Both numbers are type of double. i thought that maybe matlab stores somewhere the real value of 104 and its for real like 103.9999... So i leveled up my precision in c++. It also didnt help because when matlab returns me value of 50.000 in c++ i got value of 50.050 with high precision. Those 2 values are from few calculations like + or *. Is there any way to make my c++ and matlab scrips have same precision?
for i = 1:neighbors
y = spoints(i,1)+origy;
x = spoints(i,2)+origx;
% Calculate floors, ceils and rounds for the x and y.
fy = floor(y); cy = ceil(y); ry = round(y);
fx = floor(x); cx = ceil(x); rx = round(x);
% Check if interpolation is needed.
if (abs(x - rx) < 1e-6) && (abs(y - ry) < 1e-6)
% Interpolation is not needed, use original datatypes
N = image(ry:ry+dy,rx:rx+dx);
D = N >= C;
else
% Interpolation needed, use double type images
ty = y - fy;
tx = x - fx;
% Calculate the interpolation weights.
w1 = (1 - tx) * (1 - ty);
w2 = tx * (1 - ty);
w3 = (1 - tx) * ty ;
w4 = tx * ty ;
%Compute interpolated pixel values
N = w1*d_image(fy:fy+dy,fx:fx+dx) + w2*d_image(fy:fy+dy,cx:cx+dx) + ...
w3*d_image(cy:cy+dy,fx:fx+dx) + w4*d_image(cy:cy+dy,cx:cx+dx);
D = N >= d_C;
end
I got problems in else which is in line 12. tx and ty eqauls 0.707106781186547 or 1 - 0.707106781186547. Values from d_image are in range 0 and 255. N is value 0..255 of interpolating 4 pixels from image. d_C is value 0.255. Still dunno why matlab shows that when i have in N vlaues like: x x x 140.0000 140.0000 and in d_C: x x x 140 x. D gives me 0 on 4th position so 140.0000 != 140. I Debugged it trying more precision but it still says that its 140.00000000000000 and it is still not 140.
int Codes::Interpolation( Point_<int> point, Point_<int> center , Mat *mat)
{
int x = center.x-point.x;
int y = center.y-point.y;
Point_<double> my;
if(x<0)
{
if(y<0)
{
my.x=center.x+LEN;
my.y=center.y+LEN;
}
else
{
my.x=center.x+LEN;
my.y=center.y-LEN;
}
}
else
{
if(y<0)
{
my.x=center.x-LEN;
my.y=center.y+LEN;
}
else
{
my.x=center.x-LEN;
my.y=center.y-LEN;
}
}
int a=my.x;
int b=my.y;
double tx = my.x - a;
double ty = my.y - b;
double wage[4];
wage[0] = (1 - tx) * (1 - ty);
wage[1] = tx * (1 - ty);
wage[2] = (1 - tx) * ty ;
wage[3] = tx * ty ;
int values[4];
//wpisanie do tablicy 4 pixeli ktore wchodza do interpolacji
for(int i=0;i<4;i++)
{
int val = mat->at<uchar>(Point_<int>(a+help[i].x,a+help[i].y));
values[i]=val;
}
double moze = (wage[0]) * (values[0]) + (wage[1]) * (values[1]) + (wage[2]) * (values[2]) + (wage[3]) * (values[3]);
return moze;
}
LEN = 0.707106781186547 Values in array values are 100% same as matlab values.
Matlab uses double precision. You can use C++'s double type. That should make most things similar, but not 100%.
As someone else noted, this is probably not the source of your problem. Either there is a difference in the algorithms, or it might be something like a library function defined differently in Matlab and in C++. For example, Matlab's std() divides by (n-1) and your code may divide by n.
First, as a rule of thumb, it is never a good idea to compare floating point variables directly. Instead of, for example instead of if (nr >= 104) you should use if (nr >= 104-e), where e is a small number, like 0.00001.
However, there must be some serious undersampling or rounding error somewhere in your script, because getting 50050 instead of 50000 is not in the limit of common floating point imprecision. For example, Matlab can have a step of as small as 15 digits!
I guess there are some casting problems in your code, for example
int i;
double d;
// ...
d = i/3 * d;
will will give a very inaccurate result, because you have an integer division. d = (double)i/3 * d or d = i/3. * d would give a much more accurate result.
The above example would NOT cause any problems in Matlab, because there everything is already a floating-point number by default, so a similar problem might be behind the differences in the results of the c++ and Matlab code.
Seeing your calculations would help a lot in finding what went wrong.
EDIT:
In c and c++, if you compare a double with an integer of the same value, you have a very high chance that they will not be equal. It's the same with two doubles, but you might get lucky if you perform the exact same computations on them. Even in Matlab it's dangerous, and maybe you were just lucky that as both are doubles, both got truncated the same way.
By you recent edit it seems, that the problem is where you evaluate your array. You should never use == or != when comparing floats or doubles in c++ (or in any languages when you use floating-point variables). The proper way to do a comparison is to check whether they are within a small distance of each other.
An example: using == or != to compare two doubles is like comparing the weight of two objects by counting the number of atoms in them, and deciding that they are not equal even if there is one single atom difference between them.
MATLAB uses double precision unless you say otherwise. Any differences you see with an identical implementation in C++ will be due to floating-point errors.
Suppose you have have a rectangle, bottom-left point 0,0 and upper-right point is 100,100.
Now two line intersects the rectangle. I have to find out the coordinate of the intersection point. I have done that. Now the problem is I can't tell whether it is inside the rectangle or not. I used double comparison. But I think it is giving me wrong answer. Suppose the intersection point is ( x , y ). I used this checking for comparison : if( x >= 0.0 && x <= 100.0 && y >= 0.0 && y <= 100.0 ). What should I do?
//this function generates line
line genline( int x1 , int y1 , int x2 , int y2 ){
line l ;
l.A = y2 - y1 ;
l.B = x1 - x2 ;
l.C = l.A * x1 + l.B * y1 ;
return l ;
}
//this function checks intersection
bool intersect( line m ,line n ) {
int det = m.A * n.B - m.B * n.A ;
if( det == 0 ){
return false ;
}
else {
double x = ( n.B * m.C - m.B * n.C ) / ( det * 1.0 ) ;
double y = ( m.A * n.C - n.A * m.C ) / ( det * 1.0 ) ;
if( x >= 0.0 && x <= L && y >= 0.0 && y <= W ) { return true ; }
else{ return false ; }
}
}
EDIT:
Both the line are stretched to infinity.
Your math looks like it's right. By the way, If a line intersects something, it is always inside that something.
Checking to see if a point is inside a rectangle is relatively easy. However, the challenge is to find the intersection between two line segments. There are a large number of corner cases to that problem and limited accuracy of floating point numbers play a huge roll here.
Your algorithm seems to be overly simplistic. For a deeper discussion about this topic you can look at this and this. This two parts article investigates the problem of finding the intersection of two lines using floating point numbers. Notice that they are about MATLAB not C++ though that does not change the problem and the algorithms are easily translatable to any language.
Depending on application, even with clever tricks floating point representation might not simply cut it for some geometry problems. CGAL is a C++ library dedicated to computational geometry that deals with these kind problems. When necessary it uses arbitrary precision arithmetic to handle degenerate cases.
When you're dealing with floating point (or double), testing for equality is naïve and will fail in edge cases. Every comparison you make should be in reference to "epsilon", an extremely small quantity that doesn't matter. If two numbers are within epsilon for each other, then they are considered equal.
For example, instead of "if(a == b)", you need:
bool isEqual(double a, double b, double epsilon = 1.E-10)
{ return fabs(a - b) <= epsilon;
}
Pick a suitable value for epsilon depending on your problem domain.