views:

5765

answers:

17

I can't solve it:

You are given 8 integers:

  • A, B, C representing a line on a plane with equation A*x + B*y = C
  • a, b, c representing another line
  • x, y representing a point on a plane

The two lines are not parallel therefore divide plane into 4 pieces. Point (x, y) lies inside of one these pieces.

Problem:
Write a fast algorithm that will find a point with integer coordinates in the same piece as (x,y) that is closest to the cross point of the two given lines.

Note:
This is not a homework, this is old Euler-type task that I have absolutely no idea how to approach.

Update: You can assume that the 8 numbers on input are 32-bit signed integers. But you cannot assume that the solution will be 32 bit.

Update 2: Difficult case - when lines are almost parallel - is the heart of the problem

Update 3: Author of the problem states that the solution is linear O(n) algorithm. Where n is the size of the input (in bits). Ie: n = log(A) + log(B) + ... + log(y)
But I still can't solve it.

Please state complexities of published algorithms (even if they are exponential).

A: 

I think there are 3 pieces to this.

  1. calculate the intersection of the 2 lines, and hold on to the X and Y coordinates of that point

  2. find the section that the given point is in. This should be easy enough, because you have the slope of the 2 lines, and the slope of the line created by the given point and the point of intersection. Call them m_line1, m_line2 and m_intersect. If m_intersect There's a formula to figure out the section using these values and the location of the given point.

  3. find the closest integer. There is also a straightforward calculation of this once you know the values from #1 above, and the slopes from #2. You can brute-force it, but there is an elegant mathematical solution.

These are the steps I took, at least.

Updated to add more substance

OK, I'll start us off with a discussion on #2.

If you calculate the slope of the given point and the intersection point, then you arrive at m_intersection. This is the slope of a line that passes through the intersection point. Let's assume that m_line1 is the greater of the 2 slopes, so that line1 is "above" line2 as x increases after the intersection. It makes it easier to think about for section names. We'll call section A the section given by the sliver between line1 and line2 for x larger than the intersection coordinate x, and then we'll name the other 3 sections clockwise, so that A and C are opposite each other.

If m_intersection is between m_line1 and m_lin2, then it must be in one of the 2 sections A or C. Which section is a simple test of the x coordinate value against the intersection's x coordinate. We defined A to be the section with greater value. A similar calculation can be made if the slope is outside m_line1 or m_line2.

This gives you the section that your point lies in. All you did was calculate 1 intersection (5 multiplications, 2 divisions and a handful of subtractions if you do it the traditional way), 3 slopes, and then a couple integer comparisons.

Edit #3 - back by (un)popular demand!

So here is how I calculated #3, the closest integer point to the intersection. It may not be the best, but it uses binary search, so it's O(log n) where n is related to the inverse of the difference of the line slopes. The closer they are together, the larger n is.

First, take the difference between the slopes of the two lines. Say it's 1/8. This means that from the point of intersection, you have to go out 8 units along the x axis before you are guaranteed that there is a whole integer on the y axis in between the two lines (it may be on one of the lines). Now, if the intersection itself is not on an integer x coordinate, then you'll need to step out further to guarantee that your starting point is on an integer x coordinate, but it is bounded. If the intersection is at x = 1.2, then in the above example, at worst you'd start at x = 41, then move down ~5 units along the y axis. Choose either the ceil or floor of the y value that you get. It's not terribly critical.

Now that you have a starting point, the closest point can be approximated by binary search. Your new line segment is between the intersection and the starting point, and your units of movement are multiples of that line segment's slope. Calculate the midpoint of the line segment and see if it lies in between the two lines. Add or subtract 1 to it if it is not a direct hit, and if either of those hits, cut the remaining distance in half and do it again. Otherwise search the further half of the segment.

If you don't have a slope difference < 1, I think the problem may be simpler (brute force the space around the intersection). But it's just a special case of the search above, where you don't need to step out that far to find a starting point.

Phil
I didn't downvote because I don't know if this method has potential or not, but your answer is not very helpful. Just saying "there's a way to do this" on every important step is really not helping anyone.
IVlad
@IVlad, this method is as helpful as Fermat's proof of his Last Theorem :-)
Pavel Shved
Sorry for the terseness. I've given homework answers accidentally before. Also, I was in the middle of cooking and didn't have time to fully flesh out everything.
Phil
@Phil, I am VERY intrigued about #3. Please post the elegant mathematical solution here.
Hamish Grubijan
You're method of finding an outside bound to the solution seems valid, but I can't agree with the validity of your logic regarding binary search. The problem is only interesting when the rate of divergence is very low, so the point at which the lines have diverged by more than 1 will be very far from the intersection. Any closer satisfying point won't necessarily have any special relation to your starting place. It seems like your binary jumps won't be converging on a solution.
Alan
"Otherwise search the further half of the segment.", but given that "otherwise" the closest integer point may *still* be closer to the intersection than your current half-point.
Pavel Shved
@Pavel, thanks, I see that issue now too. I'll try to find an example and work it through.Also, I mispoke when detailing the calculation of the slope - it should be the average of the two slopes, not the difference.
Phil
A: 

Well, it depends on what is considered as fast enough.

Let's name the point [x,y] P. Also I'll call points with integer coordinates 'integer points'.

Algorithm I propose:

  1. Find the point Q where these two lines intersect. (Q=[x_q, y_q])

  2. Get the function of the line between Q and P, y=f(x) or inverse x=g(y);

  3. Determine if QP more vertical or horizontal according to its angle. Let's say it's vertical to simplify following solution (if it's horizontal, the axes would simply invert and where I write x it'd be y and vice versa).

  4. Take the first integer coordinate y_1 we get going along the line from Q to P.

  5. Calculate second coordinate of that point: x_1=f(y_1). That point is in our segment.

  6. Find if the surrounding integer points with coordinates [floor(x_1);y_1] and [floor(x_1+1);y1] are in the segment we're interested in.

6.1 If yes, then we iterate through horizontal line x_3=f(y_1) to find the integer point which is still in our segment and has (x_3-x_q) -> min. That point is our answer.

6.2 If not, then increment y_1 by one and repeat from step 5.

buratinas
The OP required to write a "fast" algorithm; your one doesn't qualify as such.
Pavel Shved
@Pavel, it's forum for programming questions; your question does not qualify as such. My algorithm would solve the worst case in less than 2 seconds on 32 bit precision.
buratinas
@~buratinas, so it will take 2 billion seconds (60 years) on 64 bits precision. It is not "fast".
Pavel Shved
@~buratinas: that doesn't mean anything. You don't get to pick the cases your algorithm does well on and say the algorithm is good while ignoring the cases that it's terrible at.
IVlad
A: 

Of those four pieces of the plane, one is to the left of both lines, one is to the right of both lines, one is to the right of one and to the left of the other line, and the last one is to the left of one and to the right of the other line. It's easier to see if you draw it.

The relative position of a point from a line depends on the result of this determinant:

[1 p1x p1y; 1 p2x p2y; 1 p3x p3y], where p1 and p2 are two arbitrary points in the line and p3 is the given point.

If it equals zero, the point is in the line, if it's greater of lower than zero, it's to a side, the side depends on the relative position of p1 and p2 in the line and what you consider left and right on the plane.

The problem is choosing two points that follow the same criteria in both lines, so that results are consistent, maybe p1 always has lower value of x coordinate than p2 (y coordinate if the line is vertical).

When you have both points for each line, calculate both determinants and you are done.

EDIT

Ups, this solves the problem partially. Anyway you can calculate the side the XY point is in with this, calculate the intersection, and then calucate the relative position of all valid points (floor(x), floor(y)), (floor(x), ciel(y)), ...

XenF
+10  A: 

alt text

Diagram

After you find intersection of lines L1:Ax+By=C and L2:ax+by=c i.e. point A(x1,y1).

Define two more lines y = ceil(y1) and y = floor(y1) parallel to X-axis and find their intersection with L1 and L2 i.e. Points B(x2,y2) and C(x3,y3).

Then point you require is D or E whichever is closer to point A. Similar procedure applies to other parts of the plane.

D ( ceil(x2), ceil(y1)  )
E ( ceil(x3), floor(y1) )
TheMachineCharmer
What if both D and E are not in the segment where X is? And what if on the next iteration of whatever you propose these points are also out of segment?
Pavel Shved
Those are the four closest integer points to the intersection. The case that makes this a challenging question is when none of those four are in the specified piece. This will happen when the two lines are very close to parallel, meeting at a very very small angle. The solution may be millions of units away from the intersection.
Alan
@Pavel Shved,segment? I have shown segments in the dia. but I mean lines. They go till infinity.
TheMachineCharmer
@Alan Though intersection is millions of units away all we need to solve is system of linear equations in two variables.
TheMachineCharmer
What if the 2 initial lines are almost parallel and don't enclose any integer points near the calculated intersection? Imagine the "ax+by=c" line on the diagram going just above D.
fgb
Cool. @fgb Thanks that is a very good question! :D+1
TheMachineCharmer
"Thanks that is a very good question" that's exactly what I asked, btw :-) By "segment" I meant "part", one of those four two lines divide the plane into.
Pavel Shved
@Pavel Shved: Thanks. :) It made sense after @fgb gave example. And I confused "segment" with something else.
TheMachineCharmer
This depends on the line y=y1 (or x=x1), lying within the selected piece (with x1,y1 as the point of intersection). If we're focusing on the only difficult case where the angle of intersection is very small, then this is only a very minor special-case of the general problem space.
Alan
I think this doesn't work when the slope of the two lines has the same sign. In that case, the space defined by your two parallel lines lies outside of the target quadrant.
Marvin
The approach is "obvious" is a sense that this is the first thing that comes to mind. But it immediately gets discarded because it doesn't offer any solution for the situation when both lines have slopes with the same sign. *This* is specifically the problem. Otherwise, it would be too easy.
AndreyT
This is not a good solution.
Łukasz Lew
A: 

A possible approach to the problem would be:

1) find the point of intersection (P). This may well have to be expressed as a floating point of some form.

2) Move in a straight line from x to near that point, and find a near point (A) (distance A to P < root 2) with integer co-ordinates.

3) This is reasonably likely to be your point, but, better, it leaves you with a few points around A to check (which can likely be optimised!). If none of these points is successful, then you can iterate back towards x, but there is no need to go further.

This approach could be improved by reducing the areas you check somehow, and possibly examining the lines programatically to find an estimate of where an integer may fall, although that is beyond my intelligence.

penguat
Could I ask why I have been downvoted? I am interested in learning why this approach is unhelpful or wrong.
penguat
A: 

An alternative approach would be:

Find the quadrant x is in. (easy)

Find the line down the middle of that quadrant (tricky? I'm not sure. May even be worthy of a SO question in its own right.)

iterate along that line from the intersection of the lines, at each stage checking the points around it (may be four points, may be two or only one. If the point you have moved to is an integer, and you have failed all points from each closer point, it is the closest point). These iterations may be variable up do a distance of 2, or you may choose to check every 1 along the line. (relatively easy, again)

penguat
+5  A: 

I have researched the problem in the past (both because it's fun and because I ran into something related at a place where I worked).

To my knowledge, there is no efficient (FPTIME) algorithm for this problem.

The only known (to me) solution is to basically enumerate integer coordinates (starting from around the intersection) until you find the one you want. This is of course not at all efficient when the angle between the two lines is very small. You can do some pruning to improve efficiency and, when the slope is small, efficiency is decent.

A generalization of this (ILP - integer linear programming) is known to be NP-complete.

As I noted on Alan's answer, this problem isn't linear (minimize x^2 + y^2), so it isn't strictly ILP, but rather Integer Convex Optimization. But it too is NP-complete, since ILP is a special case.
Eric Burnett
The fact that generalization is NP-complete doesn't imply that the original problem is NP-complete.
Łukasz Lew
@Eric, you're right about the non-linearity (but maybe something can be done to accommodate for this and still obtain an ILP).
There are answers here (particularly the one by @Eric Bainville), that indicate the problem is anything but NP-complete. Nobody has even ruled out O(1).
brainjam
+5  A: 

The more I think about this, the more it seems like it turns into Integer Linear Programming, which is NP-complete in the general case. http://en.wikipedia.org/wiki/Linear_programming#Integer_unknowns

My line of reasoning started out like TheMachineCharmer's answer until I reached that point. The problem there is that the approach of examining the lines along the ceil/floor of the point of intersection only works if the section is aligned with the vertical or horizontal axis though the intersection point. More likely, the thin section will be inclined at some angle away from the axis and the ceil/floor neighbors will not intersect the section on integer coordinates.

At that point we're looking for some integer combination of the natural unit vectors that satisfies the inequalities that define our selected section and also minimizes the distance to the point of intersection. To me, that seems like an integer linear programming problem.

There are special cases of integer linear programming that are easier than NP-hard and this problem could easily be one of them since it seems like its more constrained than the general linear programming case. The Wikipedia article links to a few methods, but that's beyond my math level to apply.

Alan
It isn't quite ILP, however; finding the closest point requires minimizing x^2 + y^2, which isn't a linear equation. It is convex, however, so it falls into the general category of convex optimization. I haven't looked closely, but I would wager that the techniques for solving ILP by adding constraints can be generalized for solving Integer Convex Optimization as well.
Eric Burnett
True enough about the non-linearity of the problem. I had been thinking that the manhattan distance would be a sufficient approximation, but after thinking about it some more that clearly isn't right.
Alan
Well, it would give you an upper bound for distance in x and y, at any rate.
Eric Burnett
It is easy to generate a linear objective function. We can easily find a candidate point where the lines are distance 1 apart, so any closer integer points must have different x values (assuming our candidate region is horizontal-ish). So x is a fine objective function. (For vertical-ish regions, use y instead.)
Keith Randall
+5  A: 

I show here how a "difficult" instance of this problem can be solved. I think this method can be generalized. I have put another simpler instance in the comments of the original post.

Consider the two lines:

10000019 * X - 10000015 * Y + 909093 >= 0    (L1)
-10000022 * X + 10000018 * Y + 1428574 >= 0  (L2)
A = 10000019, B = -10000015, C = -909093

The intersection point is H:

Hx = -5844176948071/3, Hy = -5844179285738/3

For a point M(X,Y), the squared distance HM^2 is:

HM^2 = (9*X^2+35065061688426*X
    +68308835724213587680825685
    +9*Y^2+35065075714428*Y)/9

g = gcd(A,B) = 1: the equation of L1 A*X+B*Y+909093 can take any integer value.

Bezout coefficients, U=2500004 and V=2500005 verify:

A * U + B * V = 1

We now rewrite the problem in the "dual" basis (K,T) defined by:

X = T*U - K*B
Y = T*V + K*A

After substitution, we get:

T+909093 >= 0
2*T+12*K+1428574 >= 0
minimize 112500405000369*T^2
   +900003150002790*T*K
   +1800006120005274*K^2
   +175325659092760325844*T
   +701302566240903900522*K
   +Constant

After further translating (first on T, then on K to minimize the constant in the second equation), T=T1-909093, K=K1+32468:

T1 >= 0
2*T1+4+12*K1 >= 0
minimize 112500405000369*T1^2
    +300001050000930*T1
    +900003150002790*T1*K1
    +1200004080003516*K1
    +1800006120005274*K1^2
    +Constant

The algorithm I proposed is to loop on T1. Actually, we don't need to loop here, since the best result is given by T1=K1=0, corresponding to:

X = -1948055649352, Y = -1948056428573

My initial post below.

Here is another idea of algorithm. It may work, but I did not implement it...

With appropriate change of signs to match the position of (x,y), the problem can be written:

A*X+B*Y>=C  (line D)
a*X+b*Y>=c  (line d)
minimize the distance between M(X,Y) and H, the intersection point
A*b != a*B (intersection is defined)
A,B,C,a,b,c,X,Y all integers

The set of all values reached by (A*X+B*Y) is the set of all multiples of g=gcd(A,B), and there exist integers (u,v) such that A*u+B*v=g (Bezout theorem). From a point with integer coordinates (X0,Y0), all points with integer coordinates and the same value of A*X+B*Y are (X0-K*B/g,Y0+K*A/g), for all integers K.

To solve the problem, we can loop on lines parallel to D at increasing distance from H, and containing points with integer coordinates.

  1. Compute g,u,v, and H (the coordinates of H are probably not needed, we only need the coefficients of the quadratic form corresponding to the distance).

  2. T0 = ceil(C/g)

  3. Loop from T = T0

    a. Find K the smallest (or largest, depending on the sign of a*B-b*A) integer verifying a*(T*u-K*B/g)+b*(T*v+K*A/g)>=c

    b. Keep point (T*u-K*B/g,T*v+K*A/g) if closer to H

    c. Exit the loop when (T-T0) corresponds to a distance from D larger than the best result so far, otherwise continue with T+=1

Eric Bainville
Does `Cst` mean `constant`?. If so, maybe better to write it that way.
brainjam
Awesome. Can you explain the "dual" basis trick? What are you accomplishing? Is it a matter of getting a final equation in K1 and K2 with fairly tame coefficients? Is this a well-known technique, and in what field? And do you still think in the general case you have to loop? Oh, and what tool are you using to wrangle your equations and big numbers?
brainjam
The "dual" formulations usually express the unknowns as a linear combination of the constraints. Here, that would be to express (X,Y) as a combination of (A,B,C) and (a,b,c). Because they are integers, it goes better by using this "pseudo dual". Note that all this stuff may be trivial to regular users of Z bases and lattices (I don't know).
Eric Bainville
About the need to loop, I don't know. Eliminating the K*T term in the quadratic form may be useful. In all cases, when iterating on T and K, we just need to update the value of the form, which is faster than computing it entirely (think circle rasterisation).
Eric Bainville
+1  A: 

Here's a partial idea which may be useful in getting a full solution. Imagine the two lines are very, very close to each other. Then any integral solution between them would also be an integral point which is very close to each line. Let's try to find close integral points to the line ax+by=c. Since y = (c - ax)/b, we need to have y very close to an integer, so b approximately divides c-ax. In other words, c-ax+D == 0 mod b for a small integer D.

We can solve c-ax+D == 0 mod b for x: x = a^-1(c+D) mod b (a^-1 will exist if a and b are relatively prime, not sure if that is the case here).

So the algorithm is to evaluate x = a^-1(c+D) mod b for D=0,+1,-1,+2,-2,... and try the resulting x's to see if they work. If there are close integral points to the intersection of the two lines, they should show up early in this iteration. Of course, you may have to reach D=b-1 in the worst case...

Keith Randall
A: 

line 1 is defined as y1 = m1 * x1 + b1. line 2 is defined as y2 = m2 * x2 + b2.

m1, m2, b1, b2 are all known values [constants].

make sure m1 <> m2.

find point of intersection, ie where y1 == y2 and x1 == x2 , defined as (X,Y).

Y = ((m1*b2)/m2)/(m1/m2-1)

X = (Y-b1)/m1

the nearest point can be found by rounding X and Y to the nearest integers. you decide what to do with .5

stao
A: 

My proposal is this. Assume that the section of the plane which contains our target point spans entirely in lower left quadrant, looking from the cross point of two lines (other quadrants are analogous, and case when section of plane spans more than one quadrant will be considered later).

Let the two given lines be l1 and l2 (l1 is 'less steep' than l2)

  1. find X = (a, b), the cross point of l1 and l2.

  2. let k = 0

  3. let vk be vertical line with the x coordinate xk = floor(a-k)

  4. find cross points of vk with l1 and l2 (points V1 = (x1, y1), V2 = (x2, y2)).

  5. if floor(y1) != floor(y2), target point is (x1, floor(y1)) END.

  6. if floor(y1) == floor(y2), increment k and go to step 3.

Since l1 and l2 are not parallel, abs(y1 - y2) must grow with k. When abs(y1 - y2) gets larger than 1, algorithm will surely stop (it might stop earlier though).

Now let us consider the (easy) case when our section of plane spans more than one quadrant, looking from the cross point of two lines (it may span two or three quadrants).

  1. find X = (a, b), the cross point of l1 and l2.

  2. find A, the set of four closest points to X that have integer coordinates

  3. find B, the set of points from A which are in the target section of the plane.

  4. point from B that is closest to the cross point of l1 and l2 is the target point

(This case runs in constant time.)

celicni
+2  A: 

As a few others have pointed out, this is a problem in integer linear programming (aka linear Diophantine inequalities).

Check out this reference: ABS Algorithm For Solving a Class Of Linear Diophantine Inequalities and Integer LP Problems. The authors claim to be able to solve systems like

max(cTx) for Ax≤b, x∈Zn, where c∈Zn, b∈Zm, A∈Zm,n, m≤n.

In particular, setting m=2, n=2, we get the problem of finding

max(cTx) for Ax ≤ b, x∈Z2, where c∈Z2, b∈Z2, A∈Z2,2.

Here, A is a 2x2 matrix, and b, c and x are 2x1 column vectors.

The problem stated by the OP can be restated in this fashion (if asked, I'll try to spell this out in more detail).

The matrix algorithm presented in the paper may look hairy to the uninitiated, but matrix algorithms are like that. Not that I've gone through it line by line, or understand it, but it looks pretty tame compared to some stuff I've seen.

This seems to be something in the general class of ABS methods, which appear to be gaining traction in several problem domains.

The last sentence of section 2 of the paper also refers to another solution method.

As @Alan points out, whereas the general ILP problem is NP-Hard, the problem stated here may not be. I'm not sure why that is, but it may be because the matrix A is 2x2 (rather than nx2), and because the constraints can be expressed as integers.

Edit1: the complexity of the algorithm appears to be O(1) (It appears to be O(d), where d is the dimension of the lattice. In this case, d=2). My surprise at this is O(!!) and understanding and implementing this is still O(??), although I've gone through it a few times now and it is looking more straightforward than I thought.

brainjam
+5  A: 

This problem falls into the category of Integer Convex Optimization.

Presented here is a mathematical way to approach the problem. I don't expect you to actually use it - a lot of complicated techniques are required, and other algorithmic approaches (such as "searching" for the appropriate point) will likely do just fine. However, interest has been expressed in the "true" solution, so here it is.

It can be solved in three stages:

  1. First, determine which side of each line the answer will be on, as illustrated by TheMachineCharmer's answer.
  2. Once that is known, the problem can be rewritten as a convex optimization problem (see Wikipedia for details). The function to be optimized is minimizing (x - x0)^2 + (y - y0)^2, with x0 and y0 the coordinates of the intersection of the two lines. The two lines each become a linear inequality, e.g. "x+y >= 0", together forming the convex region the answer can be found in. I will note that the solution will be (x=x0, y=y0) - what you need from this stage a way of expressing the problem, analagous to a feasible tableau for the simplex method.
  3. Third, an integer solution can be found by repeatedly adding cuts to further constrain the feasible region until the solution to the convex optimization problem is integral. This stage may take a lot of iterations in the general case, but looking at the problem presented, and in particular the 2D nature of it, I believe it will be solved with at most two cuts.
Eric Burnett
Saying that the problem Integer Convex Optimization is generalization as good as saying it is Search Problem. It is to broad.
Łukasz Lew
I will happily edit it if someone can name a more specific category it falls in. It is certainly not ILP as a lot of people are claiming, so I wanted to be clear. Also, note that convex optimization problems require the objective function to be covex (ie for a given z, the points where f(x, y) <= z is a convex set) not just the feasible region, so it may not be as broad as you are thinking.
Eric Burnett
A: 

I was doing something similar when I had to find a point for labeling of a polygon.

The final result was 70000 polygons in 5 seconds on pentium 3 in Autocad. So that's about 3 seconds if you exclude Autocad.

First you need to find an intersection point. Next thing you have to find where your point (x, y) lies and draw a horizontal or vertical line through it, so that your 2 lines (A, B, C) and (a, b, c) and a new horizontal/verical line form a triangle. How to find if it's vertical or horizontal line: Draw both horizontal and vertical lines through your (x, y) point and then check: -for horizontal: - if intersections for line A,B,C and your horizontal line and line a,b,c make this equation work (intersection with A,B,C).x < x < (intersection with a,b,c).x, then you know your inside. (you can switch A,B,C and a,b,c, just as long x is inside. - similar for y, just check for y and not x.

So now you have a triangle and you know where it is (left, right, up, down). for example if it's a right triangle (like the graph above). You take the x of intersection point and you ceil it (if it's on the left you floor it)..similar for y coordinate if you have up/down triangle. Then you draw a scanline through it, that's paralel to your scanline through your (x,y) point and check if you have a point inside of the intersections (similar to x < x < x above, but with a new line). If you don't have an integer inside, then you have to move your ceil point further away from intersection point. You should calculate apropriate 'step' based on the angle between your two lines (if the lines are paralel and very close to each other then the angle will be small, so you have to increse the step, if the angle is wide, small step is required.

When you find a point, it may not be the closest one. So you'll have to do a bisection between the last not good point (when you're increasing step) and the last point (where you found an integer).

dmonlord
What would be the complexity? The point you find might be veeeery far.
Łukasz Lew
If you want to optimize the last part and remove the bisection, therefore lower the complexity you can use triangle similarity. Draw a hor/vert line on the first possible point where the line is longer than 1 integer. There should be a integer on that line. Floor/ceil (furter away from point, depends on the quadrant) the number on the other axis and you got the point. There may be another point closer to that one, but it shouldn't be very far away from that point in the direction towards the intersection point.
dmonlord
A: 

You guys are missing the point! haha, sorry, couldn't resist.

Hey, let's imagine a slightly simpler situation.

You've got one line emanating from the origin forming an angle of less than 90 degrees with the x axis. Find the nearest integer point.

The problem with just searching lattice points until you hit one that's in the quadrant we want is that one doesn't know how far out to search. In the case of a very, very acute angle, we could consider a bazillion points before we hit one that's in our region.

Solution:

Solve: (Slope of Line) * Delta(x) = 1.

i.e. Delta(x) = 1/(Slope of Line), is where we start searching. Subject to the constraint Delta(x) > 1.

In other words, we go just far out enough that there must have been at least an integer difference between x and y coordinates.

In our problem we'd have to transform appropriately and tweedle the numbers to give an appropriate error range. Delta(x) >= 2, Delta(x) = 2/(Slope of Line) I think will do it off of the top of my head, but I don't have a pencil.

No?

d3f4ult
I'm not sure what you are getting at, but I think your algorithm would find AN integer point in the correct quadrant, but not necessarily the CLOSEST one.
Keith Randall
A: 

The problem of checking whether a point is part of a mathematical cone is fairly simple. Given 2 vectors, v, w, any point in the cone defined by (v, w) will be on the form: z = a*v + b*w, where a,b >= 0. Note, for this to work, you will have to move Origo to the intersection of the 2 lines. Since we cannot assume finite precision of the intersection, you will have to do floating point math and decide whether something is close enough to what you want.

  1. Find vectors defining the 4 cones (there's infinitely many of them, we just need 2 for each cone), that are defined by the 2 lines.
  2. Find out which cone contains our point, call that cone for C.
  3. Take the 2 vectors defining C, and find the median vector (the vector that would split C in 2 identical cones), call it m.
  4. Now is time to initiate the loop. For simplicity sake I'm going to assume that we limit ourself to n-bits on the x and y axis. Note you'll need an integer larger than n-bits for the length of m. Now do a binary search along the length of m, and check the 2 rings around every time (I suspect 1 ring around will be enough). When you've found the smallest length that do contain points C, check which of those points are the closest.

The worst case growth would be O(log(sqrt(2*n^2)), where n is the length we use to represent the x and y axis.

It is possible to do a "reverse binary search" so to speak, if you don't know the length of *m. Just keep doubling the the length you go out until you find points in C. Then you know 2 points on m and you can do a binary search between them.

The main problem with all this is precision, so keep this in mind. Alternative ways to pursue could include the 2 halfplanes that make up a cone. Each cone above are defined by the intersection of 2 halfplanes, and it is possible that checking whether a point is member of a halfplane is simple enough, I'm not sure.

Edit: it is indeed a whole lot easier with the half planes, the 2 lines divide R^2 into 2 half planes each, this gives the 4 combinations that would be the 4 cones. So every time you want to check if a point is member of a cone, you have to check if it's a member of the 2 half planes that make up that particular cone. How to do so are explained here:

http://www.mathsteacher.com.au/year9/ch04_linear_graphs/07_half/planes.htm

and would be easier than moving Origo and fiddling around with precision. Replacing the method of checking membership and keeping everything else the same, you arrive at the same growth.

hvidgaard