Calculate intersection of two lines using integers only - c++

I can quite easily calculate the point of intersection given two lines. If I start with two vertices:
(x1,y1)
(x2,y2)
I can calculate the slope by doing (y1-y2)/(x1-x2), and then calculating the intercept
y1 - slope * x1
Then do that again, so I have to sets of slope and intercept, then just do:
x = (intercept2 - intercept1) / (slope1 - slope2)
y = slope1 * x + intercept1
(disclaimer: this might not even work, but i've gotten something very close to it to work, and it illustrates my general technique)
BUT that only works with data types with decimals, or non integral. Say the vertices are:
(0,1)
(10,2)
To calculate the slope would result in (1-2)/(0-10), which is -1/-10 which is not 1/10, it is 0.
How can I get code that yields a valid result using only integers?
Edit: I can't use floats AT ALL!. No casting, no nothing. Also, values are capped at 65535. And everything is unsigned.

In high school when subtracting fractions, our teachers taught us to find a common denominator
So 1/4 - 1/6 = 3/12 - 2/12 = 1/12
So do the same with your slopes.
int slope1 = n1 / d1; // numerator / denominator
int slope2 = n2 / d2;
// All divisions below should have 0 for remainder
int g = gcd( d1, d2 ); // gcd( 4, 6 ) = 2
int d = d1 * d2 / g; // common denominator (12 above)
int n = (d/d1) * n1 - (d/d2) * n2; // (1 in 1/12 above)
// n1/d1 - n2/d2 == n/d
I hope I got that right.

Hm..
(0,1)
(10,2)
and (y1-y2)/(x1-x2). Well, this is the description of one line, not the intersection of two lines.
As far as I remember lines are described in the form of x * v with x an skalar and v be a vector. Then it's
x * (0,1) = v2 and
x * (10, 2) = v2.
therefore the lines only intersect if exactly one solution to both equitions exist, overlap when there are infinitive numbers of solutions and don't intersect when they are parallel.
http://www.gamedev.net/topic/647810-intersection-point-of-two-vectors/
explains the calcuclation based on the dot - product.

Input: line L passing thru (x1, y1) and (x2, y2), and line M passing thru (X1, Y1) and (X2, Y2)
Output: (x, y) of the intersecting point of two lines L and M
Tell Wolfram Alpha to solve y = (y1-y2)/(x1-x2)*(x-x1)+y1 and y = (Y1-Y2)/(X1-X2)*(x-X1)+Y1 for x, y to get this solution:
http://www.wolframalpha.com/share/clip?f=d41d8cd98f00b204e9800998ecf8427e3at5u9evl8
But I have no idea on how to write a program to implement the above solution for your calculator with only uint16_t ALU.

Thanks to Graham Toal's answer, below is a primitive Rust implementation of the linked C code in their answer, modified to return the point of intersection for the complete line, as opposed to the line segment. It doesn't use much Rust-specific magic so should be reasonably easy to port to other languages.
The function returns a Point where the Lines intersect, if at all, and a flag denoting whether the intersection point lies on both intersected lines (true) or not (false).
/// 2D integer point
struct Point {
/// The x coordinate.
pub x: i32,
/// The y coordinate.
pub y: i32,
}
/// Line primitive
struct Line {
/// Start point
pub start: Point,
/// End point
pub end: Point,
}
/// Check signs of two signed numbers
///
/// Fastest ASM output compared to other methods. See: https://godbolt.org/z/zVx9cD
fn same_signs(a: i32, b: i32) -> bool {
a ^ b >= 0
}
/// Integer-only line segment intersection
///
/// If the point lies on both line segments, the second tuple argument will return `true`.
///
/// Inspired from https://stackoverflow.com/a/61485959/383609, which links to
/// https://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsii/xlines.c
fn intersection(l1: &Line, l2: &Line) -> Option<(Point, bool)> {
let Point { x: x1, y: y1 } = l1.start;
let Point { x: x2, y: y2 } = l1.end;
let Point { x: x3, y: y3 } = l2.start;
let Point { x: x4, y: y4 } = l2.end;
// First line coefficients where "a1 x + b1 y + c1 = 0"
let a1 = y2 - y1;
let b1 = x1 - x2;
let c1 = x2 * y1 - x1 * y2;
// Second line coefficients
let a2 = y4 - y3;
let b2 = x3 - x4;
let c2 = x4 * y3 - x3 * y4;
let denom = a1 * b2 - a2 * b1;
// Lines are colinear
if denom == 0 {
return None;
}
// Compute sign values
let r3 = a1 * x3 + b1 * y3 + c1;
let r4 = a1 * x4 + b1 * y4 + c1;
// Sign values for second line
let r1 = a2 * x1 + b2 * y1 + c2;
let r2 = a2 * x2 + b2 * y2 + c2;
// Flag denoting whether intersection point is on passed line segments. If this is false,
// the intersection occurs somewhere along the two mathematical, infinite lines instead.
//
// Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1, the
// line segments do not intersect.
//
// Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line
// segment, the line segments do not intersect.
let is_on_segments = (r3 != 0 && r4 != 0 && same_signs(r3, r4))
|| (r1 != 0 && r2 != 0 && same_signs(r1, r2));
// If we got here, line segments intersect. Compute intersection point using method similar
// to that described here: http://paulbourke.net/geometry/pointlineplane/#i2l
// The denom/2 is to get rounding instead of truncating. It is added or subtracted to the
// numerator, depending upon the sign of the numerator.
let offset = if denom < 0 { -denom / 2 } else { denom / 2 };
let num = b1 * c2 - b2 * c1;
let x = if num < 0 { num - offset } else { num + offset } / denom;
let num = a2 * c1 - a1 * c2;
let y = if num < 0 { num - offset } else { num + offset } / denom;
Some((Point::new(x, y), is_on_segments))
}

Related

Using three points (x, y), How to find whether it is triangle or not

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!

nFinding Xcrossing point using Data Points

I was going through Algorithm which identify crossing point using data points on x axis. I can understand calculation but could not understand purpose of this calculation. As per my understanding, it determine each time new y point and slope and subtract them.
I want to insert Image also but I do not have 10 reputation point.
Please let me know if I need to provide info.
//This function determine the crossing point when the graph is intersecting x axis.
XPoint findXingPoint(Curve & curve, double rfix, double vcc, int type, int pull_up)
{
//curve class contain x and y data point
// rfix is fixed value which is generally 50
// vcc also fix value
// type contain 0 and 1
//pull up to identify graph
XPoint p = { 0.0, 0.0 };
double r_fix = rfix;
double m = -1 / r_fix;
double c = vcc / r_fix;
if(type)
c=0;
double r, s, X1, X2, Y1, Y2, Y3, Y4;
r = (m * curve[0].first) + c;
// r is a kind of y value which determine from x and y point
s = abs(r);
for (Curve::iterator i = curve.begin(); i != curve.end(); i++) {
curve_point p = (*i);
double xcurve = p.first;
double ycurve = p.second;
double yloadline = m * xcurve + c;
double B = ycurve - yloadline;
if (B >= 0 && r >= B) {
r = B;
X1 = xcurve;
Y1 = yloadline;
Y2 = ycurve;
}
if (B <= 0 && r >= abs(B)) {
s = abs(B);
X2 = xcurve;
Y4 = yloadline;
Y3 = ycurve;
}
}
#could not understand purpose of B calculation
if (s == 0)
X1 = X2;
if (r == 0)
X2 = X1;
if (X1 != X2) {
double m1, m2, c1, c2;
m1 = (Y3 - Y2) / (X2 - X1);
m2 = (Y4 - Y1) / (X2 - X1);
c1 = Y3 - (m1 * X2);
c2 = Y4 - (m2 * X2);
// CASE m1==m2 should be handled.
p.x = (c2 - c1) / (m1 - m2);
p.y = (m2 * p.x) + c2;
} else {
p.x = X1;
p.y = Y1;
}
#not able to also understand calculation
if (verbosityValue >= 1)
loginfo<<"found crossing point # " << p.x << " " << p.y << endl;
return p;
}
Output:
first
found crossing point # 7.84541e-08 -1.96135e-09 with type 0
found crossing point # 0.528564 0.0182859 with type 1
second
found crossing point # 0.654357 -0.0163589 with type 0
found crossing point # 1.25827 4.31937e-05 with type 1
This appears to be a straightforward implementation. For a given point x,y on the curve, find the slope, draw a line through the slope, find where that line would cross the x axis, and then find the new y value at that point. For well-behaved functions, the new y value is a lot closer to 0 than the initial y value. You iterate until the approximation is good enough.
If you look at the graph, you see that the middle part is quite straight. Hence, the slope of the line is a locally good approximation of the curve, and your new y value is a lot closer to zero (At least 10x times, probably 100x, looking at the graph.0. If you start on the the steeper slopes on either side, you'll need one extra step. Your second x point will be on the middle part.

How to calculate the point of intersection between two lines

I am attempting to calculate the point of intersection between lines for a Optical Flow algorithm using a Hough Transform. However, I am not getting the points that I should be when I use my algorithm for calculating the intersections.
I save the Lines as an instance of a class that I created called ImageLine. Here is the code for my intersection method.
Point ImageLine::intersectionWith(ImageLine other)
{
float A2 = other.Y2() - other.Y1();
float B2 = other.X2() - other.X1();
float C2 = A2*other.X1() + B2*other.Y1();
float A1 = y2 - y1;
float B1 = x2 - x1;
float C1 = A1 * x1 + B1 * y1;
float det = A1*B2 - A2*B1;
if (det == 0)
{
return Point(-1,-1);
}
Point d = Point((B2 * C1 - B1 * C2) / det, -(A1 * C2 - A2 * C1) / det);
return d;
}
Is this method correct, or did I do something wrong? As far as I can tell, it should work, as it does for a single point that I hard-coded through, however, I have not been able to get a good intersection when using real data.
Considering the maths side: if we have two line equations:
y = m1 * x + c1
y = m2 * x + c2
The point of intersection: (X , Y), of two lines described by the following equations:
Y = m1 * X + c1
Y = m2 * X + c2
is the point which satisfies both equation, i.e.:
m1 * X + c1 = m2 * X + c2
(Y - c1) / m1 = (Y - c2) / m2
thus the point of intersection coordinates are:
intersectionX = (c2 - c1) / (m1 - m2)
intersectionY = (m1*c1 - c2*m2) / m1-m2 or intersectionY = m1 * intersectionX + c1
Note: c1, m1 and c2, m2 are calculated by getting any 2 points of a line and putting them in the line equations.
(det == 0) is unlikely to be true when you're using floating-point arithmetic, because it isn't precise.
Something like (fabs(det) < epsilon) is commonly used, for some suitable value of epsilon (say, 1e-6).
If that doesn't fix it, show some actual numbers, along with the expected result and the actual result.
For detailed formula, please go to this page.
But I love code so, here, check this code (I get it from github, so all credit goes to the author of that code):
///Calculate intersection of two lines.
///\return true if found, false if not found or error
bool LineLineIntersect(double x1, double y1, //Line 1 start
double x2, double y2, //Line 1 end
double x3, double y3, //Line 2 start
double x4, double y4, //Line 2 end
double &ixOut, double &iyOut) //Output
{
//http://mathworld.wolfram.com/Line-LineIntersection.html
double detL1 = Det(x1, y1, x2, y2);
double detL2 = Det(x3, y3, x4, y4);
double x1mx2 = x1 - x2;
double x3mx4 = x3 - x4;
double y1my2 = y1 - y2;
double y3my4 = y3 - y4;
double xnom = Det(detL1, x1mx2, detL2, x3mx4);
double ynom = Det(detL1, y1my2, detL2, y3my4);
double denom = Det(x1mx2, y1my2, x3mx4, y3my4);
if(denom == 0.0)//Lines don't seem to cross
{
ixOut = NAN;
iyOut = NAN;
return false;
}
ixOut = xnom / denom;
iyOut = ynom / denom;
if(!isfinite(ixOut) || !isfinite(iyOut)) //Probably a numerical issue
return false;
return true; //All OK
}
Assuming your formulas are correct, try declaring all your intermediate arguments as 'double'. Taking the difference of nearly parallel lines could result in your products being very close to each other, so 'float' may not preserve enough precision.

Distance between 2 hexagons on hexagon grid

I have a hexagon grid:
with template type coordinates T. How I can calculate distance between two hexagons?
For example:
dist((3,3), (5,5)) = 3
dist((1,2), (1,4)) = 2
First apply the transform (y, x) |-> (u, v) = (x, y + floor(x / 2)).
Now the facial adjacency looks like
0 1 2 3
0*-*-*-*
|\|\|\|
1*-*-*-*
|\|\|\|
2*-*-*-*
Let the points be (u1, v1) and (u2, v2). Let du = u2 - u1 and dv = v2 - v1. The distance is
if du and dv have the same sign: max(|du|, |dv|), by using the diagonals
if du and dv have different signs: |du| + |dv|, because the diagonals are unproductive
In Python:
def dist(p1, p2):
y1, x1 = p1
y2, x2 = p2
du = x2 - x1
dv = (y2 + x2 // 2) - (y1 + x1 // 2)
return max(abs(du), abs(dv)) if ((du >= 0 and dv >= 0) or (du < 0 and dv < 0)) else abs(du) + abs(dv)
Posting here after I saw a blog post of mine had gotten referral traffic from another answer here. It got voted down, rightly so, because it was incorrect; but it was a mischaracterization of the solution put forth in my post.
Your 'squiggly' axis - in terms of your x coordinate being displaced every other row - is going to cause you all sorts of headaches with trying to determine distances or doing pathfinding later on, if this is for a game of some sort. Hexagon grids lend themselves to three axes naturally, and a 'squared off' grid of hexagons will optimally have some negative coordinates, which allows for simpler math around distances.
Here's a grid with (x,y) mapped out, with x increasing to the lower right, and y increasing upwards.
By straightening things out, the third axis becomes obvious.
The neat thing about this, is that the three coordinates become interlinked - the sum of all three coordinates will always be 0.
With such a consistent coordinate system, the atomic distance between any two hexes is the largest change between the three coordinates, or:
d = max( abs(x1 - x2), abs(y1 -y2), abs( (-x1 + -y1) - (-x2 + -y2) )
Pretty straightforward. But you must fix your grid first!
The correct explicit formula for the distance, with your coordinate system, is given by:
d((x1,y1),(x2,y2)) = max( abs(x1 - x2),
abs((y1 + floor(x1/2)) - (y2 + floor(x2/2)))
)
Here is what a did:
Taking one cell as center (it is easy to see if you choose 0,0), cells at distance dY form a big hexagon (with “radius” dY). One vertices of this hexagon is (dY2,dY). If dX<=dY2 the path is a zig-zag to the ram of the big hexagon with a distance dY. If not, then the path is the “diagonal” to the vertices, plus an vertical path from the vertices to the second cell, with add dX-dY2 cells.
Maybe better to understand: led:
dX = abs(x1 - x2);
dY = abs(y1 - y2);
dY2= floor((abs(y1 - y2) + (y1+1)%2 ) / 2);
Then:
d = d((x1,y1),(x2,y2))
= dX < dY2 ? dY : dY + dX-dY2 + y1%2 * dY%2
First, you need to transform your coordinates to a "mathematical" coordinate system. Every two columns you shift your coordinates by 1 unit in the y-direction. The "mathamatical" coordinates (s, t) can be calculated from your coordinates (u,v) as follows:
s = u + floor(v/2)
t = v
If you call one side of your hexagons a, the basis vectors of your coordinate system are (0, -sqrt(3)a) and (3a/2, sqrt(3)a/2). To find the minimum distance between your points, you need to calculate the manhattan distance in your coordinate system, which is given by |s1-s2|+|t1-t2| where s and t are the coordinates in your system. The manhattan distance only covers walking in the direction of your basis vectors so it only covers walking like that: |/ but not walking like that: |\. You need to transform your vectors into another coordinate system with basis vectors (0, -sqrt(3)a) and (3a/2, -sqrt(3)a/2). The coordinates in this system are given by s'=s-t and t'=t so the manhattan distance in this coordinate system is given by |s1'-s2'|+|t1'-t2'|. The distance you are looking for is the minimum of the two calculated manhattan distances. Your code would look like this:
struct point
{
int u;
int v;
}
int dist(point const & p, point const & q)
{
int const ps = p.u + (p.v / 2); // integer division!
int const pt = p.v;
int const qs = q.u + (q.v / 2);
int const qt = q.v;
int const dist1 = abs(ps - qs) + abs(pt - qt);
int const dist2 = abs((ps - pt) - (qs - qt)) + abs(pt - qt);
return std::min(dist1, dist2);
}
(odd-r)(without z, only x,y)
I saw some problems with realizations above. Sorry, I didn't check it all but. But maybe my solution will be helpful for someone and maybe it's a bad and not optimized solution.
The main idea to go by diagonal and then by horizontal. But for that we need to note:
1) For example, we have 0;3 (x1=0;y1=3) and to go to the y2=6 we can handle within 6 steps to each point (0-6;6)
so: 0-left_border , 6-right_border
2)Calculate some offsets
#include <iostream>
#include <cmath>
int main()
{
//while(true){
int x1,y1,x2,y2;
std::cin>>x1>>y1;
std::cin>>x2>>y2;
int diff_y=y2-y1; //only up-> bottom no need abs
int left_x,right_x;
int path;
if( y1>y2 ) { // if Down->Up then swap
int temp_y=y1;
y1=y2;
y2=temp_y;
//
int temp_x=x1;
x1=x2;
x2=temp_x;
} // so now we have Up->Down
// Note that it's odd-r horizontal layout
//OF - Offset Line (y%2==1)
//NOF -Not Offset Line (y%2==0)
if( y1%2==1 && y2%2==0 ){ //OF ->NOF
left_x = x1 - ( (y2 - y1 + 1)/2 -1 ); //UP->DOWN no need abs
right_x = x1 + (y2 - y1 + 1)/2; //UP->DOWN no need abs
}
else if( y1%2==0 && y2%2==1 ){ // OF->NOF
left_x = x1 - (y2 - y1 + 1)/2; //UP->DOWN no need abs
right_x = x1 + ( (y2 - y1 + 1)/2 -1 ); //UP->DOWN no need abs
}
else{
left_x = x1 - (y2 - y1 + 1)/2; //UP->DOWN no need abs
right_x = x1 + (y2 - y1 + 1)/2; //UP->DOWN no need abs
}
/////////////////////////////////////////////////////////////
if( x2>=left_x && x2<=right_x ){
path = y2 - y1;
}
else {
int min_1 = std::abs( left_x - x2 );
int min_2 = std::abs( right_x - x2 );
path = y2 - y1 + std::min(min_1, min_2);
}
std::cout<<"Path: "<<path<<"\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n";
//}
return 0;
}
I believe the answer you seek is:
d((x1,y1),(x2,y2))=max(abs(x1-x2),abs(y1-y2));
You can find a good explanation on hexagonal grid coordinate-system/distances here:
http://keekerdc.com/2011/03/hexagon-grids-coordinate-systems-and-distance-calculations/

Given two points, find a third point on the line

I have two points A (x1,y1) and B (x2,y2) that are given as an input to the program. I have to find a third point C that lies on the line AB and is at a distance 10 away from the point A.
I can easily get the slope of the line but that doesn't give me the full equation for the line. Even if I get the full equation, I am not sure using this equation, how would I find out a point that is x distance away from A.
Any suggestions on how to approach this?
There are always two points on each line:
get the vector from A to B (subtract the coordinates)
normalize the vector (divide by its length; pythagorean theorem)
multiply the vector by 10 or -10
add the vector to A to get C
Note that if A==B, the line is not defined, and this algorithm causes a division by zero. You may want to add a test for equality at the beginning.
You can use the sine or the cosine (times 10) of the angle of the line to get the horizontal or vertical distance of the point that is a distance of 10 from a given point. A shortcut is to use the horizontal or vertical distance divided by the direct distance between the points to get the sine or cosine.
You can do it using vectors like this:
Let D = the difference between B and A (D = B - A)
Then any point on the line can be described by this formula:
point = A + Dt
where t is a real number.
So just plug in any value for t to get another point. For example if you let t == 1 then the equation above reduces to point = B. If you let t = 0 then it reduces to point = A. So you can see that you can use this to find a point between A and B simply by let t range from 0 to 1. Additionally if you let t > 1, you will find a point past B.
You can see from the image that your given points are x1,y1 and x2,y2. You need to find an intermediate point at a distance 'R' from point x1,y1.
All you need to do is to find θ using
Tan θ = (y2-y1)/(x2-x1)
Then you can get the intermediate point as (R * cos θ),(R * Sin θ)
I have drawn this assuming positive slope.
Going on similar lines you can seek a solution for other special cases lile:
i. Horizontal line
ii. Vertical line
iii. Negative slope
Hope it clarifies.
I have done the calculation in Andengine using a Sprite object. I have two Array List x coordinates and y coordinates. Here i am just calculating using the last two values from these two array list to calculate the third point 800 pixel distant from Your point B. you can modify it using different values other than 800. Hope it will work.The coordinate system here is a little different where (0,0) on the top left corner of the screen. Thanks
private void addExtraCoordinate(CarSprite s) {
int x0, y0, x1, y1;
float x = 0f, y = 0f;
x0 = Math.round(xCoordinates.get(xCoordinates.size() - 2));
x1 = Math.round(xCoordinates.get(xCoordinates.size() - 1));
y0 = Math.round(yCoordinates.get(yCoordinates.size() - 2)) * (-1);
y1 = Math.round(yCoordinates.get(yCoordinates.size() - 1)) * (-1);
if (x1 == x0 && y1 == y0) {
return;
} else if (y1 == y0 && x1 != x0) {
if (x1 > x0) {
x = (float) x1 + 800f;
} else
x = (float) x1 - 800f;
y = Math.round(yCoordinates.get(yCoordinates.size() - 1));
} else if (y1 != y0 && x1 == x0) {
if (y1 > y0) {
y = (float) Math.abs(y1) - 800f;
} else
y = (float) Math.abs(y1) + 800f;
x = Math.round(xCoordinates.get(xCoordinates.size() - 1));
} else {
float m = (float) (yCoordinates.get(yCoordinates.size() - 1) * (-1) - yCoordinates
.get(yCoordinates.size() - 2) * (-1))
/ (float) (xCoordinates.get(xCoordinates.size() - 1) - xCoordinates
.get(xCoordinates.size() - 2));
if (x1 > x0) {
x = (float) ((float) x1 + 800f / (float) Math
.sqrt((double) ((double) 1f + (double) (m * m))));
} else
x = (float) ((float) x1 - 800f / (float) Math
.sqrt((double) ((double) 1f + (double) (m * m))));
if (y0 > y1) {
y = (float) ((float) Math.abs(y1) + 800f / (float) Math
.sqrt((double) (((double) 1f / (double) (m * m)) + (double) 1f)));
} else
y = (float) ((float) Math.abs(y1) - 800f / (float) Math
.sqrt((double) (((double) 1f / (double) (m * m)) + (double) 1f)));
}
xCoordinates.add(x);
yCoordinates.add(y);
}