Find a line connecting two faces of a cubic volume - algorithm

Imagine a volumetric cube of N³ resolution that is filled with occluding voxels. The cube could be completely filled, or contain curvy "tunnels", or walls - or just a few stray voxels; We now pick any two of the six faces of the bounding cube and attempt to find a line that connects those two faces without hitting any voxel inside it. If such a line exists, the faces can see each other, otherwise, they're completely occluded.
My question is: does an O(n) (or better) algorithm exist to quickly discern if such a line can be drawn? The exact parameters of the line do not matter.

I'm somewhat unclear on the exact parameters of being a straight line in this (continuous? discrete?) space, but I wonder if you're looking for a dynamic programming solution?
Perhaps lets restrict to 2-D left to right case to build the algorithm and then generalize:
Loop over first column of the array,
for each opaque square, mark that it is impossible to build a ray which reaches this square
for each non opaque square, mark that it is possible to reach this square -AND- track ranges of slopes can reach this square. You may restrict the set of slopes in this initialization by the set of slopes that could potentially reach the opposite end of your voxel volume.
Then loop over the next column
Each square is potentially able to be reached by any square in the previous column, but only if the range of slopes that can reach the square in the previous column intersects the range of slopes necessary to reach the current square from the square in the previous column.
You thus set the valid range of slopes in the current square to the union of the intersections of the valid ranges from previous squares with valid ranges to current square.
You continue looping over columns until you hit the far end, and any reachable entries on the far end will report the ranges of slopes of vectors that allow hitting that square.
The speed of the algorithm is heavily dependent on how quickly you can union and intersect ranges of slopes (or in the 3D case, arbitrary ranges of UV coordinates). In 2D continuous space this operation can be done quickly by sorting, in a 3D discrete space, you can use a set of possible vector slopes in X,Y dependent on dimensions of your voxel space. In a 3D continuous space, some type of quadtree would probably approach what can be achieved by sorting in 2D.
The algorithm loops once over each cell in your input (Do you consider this O(n) or O(n^3)?), and takes time that will be bounded by the union of intersections call times the number of elements in your space (Worst case O(n^2) in discrete case I believe, but will shrink dramatically in the initialization step if the opposite end of the volume is far away, and may shrink quickly in the case of many opaque cells and proper data structures)
As far as I can tell, processing order of slices of the volume doesn't actually matter, so if you know that certain spots are very opaque (by sum of opaque cells or whatever), you might use a heuristic to reorder intersection operations.

A Voxel cube would look like a Rubik Cube, voxel structure is a 3D matrix of blocks, so to draw a line from one side to the other, we need to draw within each related block the line that connects to the next, together the lines form one continuous line through the cube.
The following algorithm works fine if implemented well, since you're going to work on local coordinates within the cube, any transformations of the cube itself will be applied automatically by the 3D engine when it translate it into world coordinates.
Time Complexity
MATRIX.MAX_Z * (
Time(MATRIX.GET_VOXEL(x,y,z))
+ Time(VOXEL.DRAW-LINE(0,0,0, 0,0,VOXEL_DEPTH))
)
Algorithm
FUNCTION DRAW (INTEGER X, INTEGER Y)
INTEGER VOXEL_X = X / MATRIX.VOXEL_WIDTH
INTEGER VOXEL_Y = Y / MATRIX.VOXEL_HEIGHT
FOR i = 0 .. (MATRIX.MAX_Z-1)
VOXEL V = MATRIX.GET_VOXEL(VOXEL_X, VOXEL_Y, i)
INTEGER X_0 = X % MATRIX.VOXEL_WIDTH
INTEGER Y_0 = Y % MATRIX.VOXEL_HEIGHT
INTEGER Z_0 = 0
INTEGER X_1 = X_0
INTEGER Y_1 = Y_0
INTEGER Z_1 = (MATRIX.VOXEL_DEPTH-1)
V.DRAW-LINE(X_0,Y_0,Z_0, X_1,Y_1,Z_1)
END-FOR
END-FUNCTION

So one easy way to do this test is to render the view (orthographic) from the source to the target cube at arbitrary resolution. If there is any background pixel left, there exists a line between the two rectangles. So the complexity comes down to two things:
The resolution at which you render
How fast can you render an orthographic, binary view
Now for that binary rendering the only thing you need to know is covered/not covered. That comes down to two octrees, one for minimum and one for maximum. The minimum tree tracks "is there any open child node (or)" the maximum tracks "is there any closed child node (and)". Building those trees is n log(n), but the query is only log(n).
For the target resolution, m, it should be only log(m). Even if you go up to m=2^23 for float size.

Breaking the problem down to two dimensions, it is clear that some voxel configurations are obviously impenetrable from, say, left to right:
+-+-+-+ +-+-+-+-+-+
| |#| | |#| | | | |
+-+-+-+ +-+-+-+-+-+
| |#| | |#| | |#| |
+-+-+-+ +-+-+-+-+-+
| |#| | |#| | |#| |
+-+-+-+ +-+-+-+-+-+
|#| | |#| |
+-+-+-+-+-+
| | | |#| |
+-+-+-+-+-+
... but this might not be impenetrable, depending on how you handle your corners:
+-+-+-+-+-+
|#| | | |/|
+-+-+-+-+-+
|#| | |/| |
+-+-+-+-+-+
|#| |/|#| |
+-+-+-+-+-+
|#|/| |#| |
+-+-+-+-+-+
|/| | |#| |
+-+-+-+-+-+
... and this is definitely possible:
+-+-+-+-+-+
|#| | | | |
+-+-+-+-+-+
|#| | | | |
+-+-+-+-+-+
|#| | | | |
+-+-+-+-+-+
| | | |#| |
+-+-+-+-+-+
| | | |#| |
+-+-+-+-+-+
Now, if you can think of any trick that can tell the upper 2D-cubes from the lower one, that might eliminate at least some impossible pixel/voxel configurations -- but I'm afraid you need to test every pixel on your target side for light coming through from your source side from any angle, which sounds awfully like an n-squared problem (2D), or n^4 in 3D.
In 2D, I'd start at the top of the left side and check if the line connecting my voxel centre to the top right hits an occluding pixel: if not, we're done; if it does, you advance your angle so that the ray passes the lower left corner of the occlusion and continue checking until you either find a passage or get to the end of the right side.
Continue with every pixel on your source side, until you are done -- one way or the other.
But that's brute-force, and I'd be interested to see a more elegant solution, perhaps by G. Bach ...?

Related

Finding all the rectangles within a given rectangle that do not intersect with an arbitrary shape

I need to find an algorithm to find the least number of overlapping rectangles within a given rectangle R that do not intersect with the union of a set of other rectangles contained within R. These inner rectangles can overlap. Here's a terrible ASCII drawing of an example R:
A-----------------B-------------------------+
| |
| |
| |
| |
| +--------+ |
| |........| |
| |........| |
C +---D........| |
| |.........+--+ |
| |.........| |
| ++........+------+ |
| |...............| |
G +---H...........| |
| |...........| |
| |...........| |
| |...........| |
| +-----------+ |
| |
| |
| |
E-------------I----F------------------------+
The rectangles here would include (A, D), (A, I), (G, F). This seems like a problem for which the solution is well-understood, but for which I simply lack the vocabulary. Any answers, pointers, RTFMs cheerfully and gratefully accepted. Thanks!
EDIT: As per #Paul's observation below, what I'm trying to do is find a set of rectangles that cover the space in R without covering any of polygon comprised of the union of the inner set. If that makes sense.
I believe this is one possible way to solve.
I will refer to the overlapping rectangles as "white", and the ones in the solution as "black"
First of all, let's assume we have a data structure suitable for search on intersection. One possible data structure is an Interval Tree, using points on one of the coordinates as intervals (for example, if a rectangle is defined by two points (x0,y0) and (x1, y1), use (x0, y1) as interval. The link also explain how to extend to higher dimensions (in your case you need 2).
I won't go in the detail of an implementation of such data structure, but let's assume we have one called Rectangles, with the following API defined:
void add(Rectangle r)
void remove(Rectangle r)
Rectangle[] getIntersecting(Rectangle r)
Rectangle[] getAdjacent(Rectangle r)
Ok, now create two instances of Rectangles called black and white. Initialize white with all the white rectangles. Initializie black with the R rectangle (the whole domain).
For each rectangle rw in white get the array arr of intersecting rectangles from black.
For each rectangle rb in black, determine the result of rw-rb. This is a set set of 0, 1, 2, 3 or 4 rectangles, depending on how the two rectangles intersect.
remove rw from white, and add the content of set to it. This may require merging rectangles from set with rectangle already in white, if such rectangles together form a larger rectangle (they're adjacent sharing one side)
remove rb from black
repeat from 1 until there are no more rectangles in black
Using some basic math, we could say the solution to your problem would be the decomposition of the rectilinear polygon R \ union(rs), where union(rs) represents the polygon inside R. Calculating R \ union(rs) can be done using the Greiner-Hormann-algorithm. Note that this step will result in a polygon with holes and - only if the inner polygon contains holes - multiple other polygons. The decomposition is described here (this is only an approximation, but i wasn't able to find a precise algorithm so far).

computing cost in optimum way in high dimensional space

how to find contours of equal function value on a high dimensional space in optimal way provided function values is monotonically non-decreasing along all dimensions.
As your function is monotonic in both X and Y this becomes straight forward to find the contour. Lets find the solutions of f(x,y)-K = 0.
Step 1. Calculate the function at the four corners. This will tell you which edges the contour intersects.
Step 2. Pick one of the edges with a solution. Use a subdivision algorithm to find a solution on this edge. First find the mid-point and calculate the value there. This splits the edge in two, exactly one will have sign change, pick that edge and repeat. This process will give the unique solution on the edge.
Step 3. Starting at the end point use a zero following technique. We start with a square with a solution on one edge, and known values at two corners. Evaluate the function at the other two corners. Compare signs and find the other edge with a solution on it. Get the adjacent square and repeat.
This will follow the curve until we reach the other solution on the boundary. Being monotonic means there are no tricky cases to deal with.
More on step 3: We have a rectangle with two know points
+ ____ -
| |
| |
? ____ ?
there are three possibilities
+ ____ -
| |
| | take the right hand side
+ ____ +
+ ____ -
| | take the bottom side
| |
+ ____ -
+ ____ -
| |
| | take the left hand side
- ____ -
One option can't occur as the function is monotonic
+ ____ -
| | impossible
| |
- ____ +
If you evaluate the function at four corners of a square, the four values will tell you if the square is crossed by the iso-K curve.
Now subdivide the square in four sub-squares and check the function values at the new corners (this costs 5 function evaluations). Thanks to the monotonicity property, you are ensured that at least one of the squares can be discarded.
If you continue this process recursively, the number of points is reduced by at least 25% on every stage, and 32 stages will suffice to reduce from 10000 to 1 (0.75^32 = 0.000100...), requiring in total no more than 32 x 5 = 160 function evaluations.

Direction that is perpendicular to a collection of 3D points?

I have a collection of 3D points which form an imperfect circle and are stored in the order in which they appear in the circle. I'm positioning an object in the centre of the ring by calculating the mean position of all of the points, which works fine. Now, what I want is for the object in the centre to be facing up/down relative to the rest of the points (i.e perpendicular to the ring).
I've included an image to help clarify what I mean. Does anyone know of an algorithm that would be suitable for this?
You have to compute the plane that your points form and get its normal.
If the points are perfectly coplanar, just get three of them, a, b, and c, and compute two vectors. The normal vector n is the cross product of them:
v1 = b - a;
v2 = c - a;
n = v1 x v2;
If the points are not perfectly coplanar, you can get the plane that best fits the points and then, its normal. You can get the plane by solving a linear equation system of the form Ax=0. Since the general equation of a plane is Ax + By + Cz + D = 0, you get one equation per 3D point, obtaining this system:
| x1 y1 z1 1 | | A | | 0 |
| x2 y2 z2 1 | x | B | = | 0 |
| x3 y3 z3 1 | | C | | 0 |
| ... | | D | | ... |
| xn yn zn 1 | | 0 |
The normal vector is (A, B, C).
Elaborating on a previous answer, you get a system of n equations in 4 unknowns when you solve for the best hyperplane normal vector with n points. You need to set one of the unknown coefficients (say D) to a constant like 1 and move the corresponding data column to the right hand side so that you don't get the trivial solution A=B=C=D=0. You can safely set one coefficient to 1 if it is non-zero because the solution A,B,C,D is still a solution if you scale it. So you get a system of n equations in 3 unknowns where the right hand side is a vector of all -1 instead of the zero vector, and your data matrix is simply your matrix of points and your unknown coefficients are A,B,C. In general such a system is overdetermined if you have more than 3 points so you need to solve it using linear regression. See http://en.wikipedia.org/wiki/Linear_regression to get the matrix formula for solving for the 3 coefficients using least squares best fit.

how to simulate a rectangle union starting with a rectangle intersection

Given rectangle_A intersecting rectangle_B, which has a union defined such that it is the rectangle containing both rectangles, I want to determine the coordinates of the (not overlapping) rectangles required to add to rectangle_A to create the union of rectangle_A and rectangle_B:
Note: this is just one configuration of the solution set of rectangles. the white rectangles above could be configured differently, as long as they don't overlap.
Is there a simple algorithm for every case of rectangle intersection? I've done a first pass and I miss some corners. Evidently not my forté.
Why? When panning in a UI, I only want to (i) update the new parts of the canvas (ii) keep track of what has been painted as a rectangle (the union of rectangle_A and rectangle_B).
If you are not concerned with minimizing the number of rectangles returned, you can simplify the thought process to one that always returns no more than 8 rectangles:
U
+----------+----+-------+
| | | |
| 1 | 2 | 3 |
+----------+----+-------+
| | | |
| 4 | A | 5 |
| | | |
+----------+----+-------+
| 6 | 7 | 8 |
+----------+----+-------+
U.x1 = min(A.x1,B.x1)
U.x2 = max(A.x2,B.x2)
U.y1 = min(A.y1,B.y1)
U.y2 = max(A.y2,B.y2)
R1.x1 = R4.x1 = R6.x1 = U.x1
R2.x1 = R7.x1 = R1.x2 = R4.x2 = R6.x2 = A.x1
R2.x2 = R7.x2 = R3.x1 = R5.x1 = R8.x1 = A.x2
R3.x2 = R5.x2 = R8.x2 = U.x2
R1.y1 = R2.y1 = R3.y1 = U.y1
R1.y2 = R2.y2 = R3.y2 = R4.y1 = R5.y1 = A.y1
R4.y2 = R5.y2 = R6.y1 = R7.y1 = R8.y1 = A.y2
R6.y2 = R7.y2 = R8.y2 = U.y2
If you wanted, you could then quickly check each rectangle to see if r.x1 == r.x2 || r.y1 == r.y2 (i.e. if it has zero area), and throw it out if so. In most cases, over half of the rectangles can be thrown out this way.
For example, in your three examples, this solution would return 3, 1, and 5 rectangles, and would return 0 in the best case (when B is contained in A) and 8 in the worst case (when A is contained in B).
Say we represent rectangles by a pair of x,y coordinate pairs: x1,y1 for the top-left and x2,y2 for the bottom left corner. Let's also assume y coordinate increase downwards and x coordinates increase left to right.
Now, suppose the rectangle formed by the union of A and B (according to your definition of union) is the rectangle is U.
So,
U.x1=min(A.x1,B.x1), U.y1=min(A.y1,B.y2) --- top-left corner, take the lowest values
U.x2=max(A.x2,B.x2), U.y2=max(A.y2,B.y2) --- bottom-right corner, take the highest values
Now that we have the larger rectangle U, we can use that to compute the smaller right and bottom rectangles that have to be added to A (the left/top rectangle) to make it U. Lets call them Rt and Bot.
(This time I'm assuming A is the top-left rectangle, if it isn't swap A and B. Also assuming the layout to be similar to that of your picture. If that isn't the case you can adapt this easily).
Rt.x1=A.x2, Rt.y1=A.y1
Rt.x2=A.x2, Rt.y2=B.y2
Bot.x1=A.x1, Bot.y1=A.y2
Bot.x2=A.x2, Bot.y2=B.y2
I'm sorry i cant give a working solution, but...
At first I would try to draw such nice images for every different case that you can imagine. There will be a lot cases, where you need more than 2 rectangles, or just one, right?
I think getting the rect containing the others is trivial-but at this time I can't think of how to proceed. :)
Edit: At this time i'm thinking of a flood fill algorith, just fill up your larger rect. But there are 2 problems with this I can imagine: How to use the flood fill output to generate rects from it? Will it be the right way, or is there a linear algebra solution or something?

Positioning squares on a circle with minimum diameter

Given n squares with edge length l, how can I determine the minimum radius r of the circle so that I can distribute all squares evenly along the perimeter of the circle without them overlapping? (Constraint: the first square will always be positioned at 12 o'clock.)
Followup question: how can I place n identical rectangles with height h and width w?
(source: n3rd.org)
There may be a mathematically clever way to do this, but I wouldn't know.
I think it's complicated a bit by the fact that the geometry is different for every different number of squares; for 4 it's a rhombus, for 5 it's a pentagon and so on.
What I'd do is place those squares on a 1 unit circle (much too small, I know, bear with me) distributed equally on it. That's easy enough, just subtend (divide) your 360 degrees by the number of squares. Then just test all your squares for overlap against their neighbors; if they overlap, increase the radius.
You can make this procedure less stupid than it sounds by using an intelligent algorithm to approach the right size. I'm thinking of something like Newton's algorithm: Given two successive guesses, of which one is too small and one is too big, your next guess needs to be the average of those two.
You can iterate down to any precision you like. Stop whenever the distance between guesses is smaller than some arbitrary small margin of error.
EDIT I have a better solution:
I was thinking about what to tell you if you asked "how will I know if squares overlap?" This gave me an idea on how to calculate the circle size exactly, in one step:
Place your squares on a much-too-small circle. You know how: Calculate the points on the circle where your 360/n angles intersect it, and put the center of the square there. Actually, you don't need to place squares yet, the next steps only require midpoints.
To calculate the minimum distance of a square to its neighbor: Calculate the difference in X and the difference in Y of the midpoints, and take the minimum of those. The X's and Y's are actually just cosines and sines on the circle.
You'll want the minimum of any square against its neighbor (clockwise, say). So you need to work your way around the circle to find the very smallest one.
The minimum (X or Y) distance between the squares needs to become 1.0 . So just take the reciprocal of the minimum distance and multiply the circle's size by that. Presto, your circle is the right size.
EDIT
Without losing generality, I think it's possible to nail my solution down a bit so it's close to coding. Here's a refinement:
Assume the squares have size 1, i.e. each side has a length of 1 unit. In the end, your boxes will surely be larger than 1 pixel but it's just a matter of scaling.
Get rid of the corner cases:
if (n < 2) throw new IllegalArgumentException();
if (n == 2) return 0.5; // 2 squares will fit exactly on a circle of radius 0.5
Start with a circle size r of 0.5, which will surely be too small for any number of squares > 2.
r = 0.5;
dmin = 1.0; // start assuming minimum distance is fine
a = 2 * PI / n;
for (p1 = 0.0; p1 <= PI; p1+=a) { // starting with angle 0, try all points till halfway around
// (yeah, we're starting east, not north. doesn't matter)
p2 = p1 + a; // next point on the circle
dx = abs(r * cos(p2) - r * cos(p1))
dy = abs(r * sin(p2) - r * sin(p1))
dmin = min(dmin, dx, dy)
}
r = r / dmin;
EDIT
I turned this into real Java code and got something quite similar to this to run. Code and results here: http://ideone.com/r9aiu
I created graphical output using GnuPlot. I was able to create simple diagrams of boxes arranged in a circle by cut-and-pasting the point sets from the output into a data file and then running
plot '5.dat' with boxxyerrorbars
The .5's in the file serve to size the boxes... lazy but working solution. The .5 is applied to both sides of the center, so the boxes end up being exactly 1.0 in size.
Alas, my algorithm doesn't work. It makes the radii far too large, thus placing the boxes much further apart than necessary. Even scaling down by a factor of 2 (could have been a mistake to use 0.5 in some places) didn't help.
Sorry, I give up. Maybe my approach can be salvaged, but it doesn't work the way I had though it would. :(
EDIT
I hate giving up. I was about to leave my PC when I thought of a way to salvage my algorithm:
The algorithm was adjusting the smaller of the X or Y distances to be at least 1. It's easy to demonstrate that's just plain silly. When you have a lot of boxes then at the eastern and western edges of the circle you have boxes stacked almost directly on top of each other, with their X's very close to one another but they are saved from touching by having just enough Y distance between them.
So... to make this work, you must scale the maximum of dx and dy to be (for all cases) at least the radius (or was it double the radius?).
Corrected code is here: http://ideone.com/EQ03g http://ideone.com/VRyyo
Tested again in GnuPlot, it produces beautiful little circles of boxes where sometimes just 1 or 2 boxes are exactly touching. Problem solved! :)
(These images are wider than they are tall because GnuPlot didn't know I wanted proportional layout. Just imagine the whole works squeezed into a square shape :) )
I would calculate an upper bound of the minimum radius, by working with circles enclosing the squares instead of with the squares themselves.
My calculation results in:
Rmin <= X / (sqrt(2) * sin (180/N) )
Where:
X is the square side length, and N is the required number of squares.
I assume that the circles are positioned such that their centers fall on the big circle's circumference.
-- EDIT --
Using the idea of Dave in the comment below, we can also calculate a nice lower bound, by considering the circles to be inside the squares (thus having radius X/2). This bound is:
Rmin >= X / (2 * sin (180/N) )
As already noted, the problem of positioning n points equally spaced round the circumference of a circle is trivial. The (not-terribly) difficult part of the problem is to figure out the radius of the circle needed to give a pleasing layout of the squares. I suggest you follow one of the other answers and think of the squares being inside a circular 'buffer' big enough to contain the square and enough space to satisfy your aesthetic requirements. Then check the formula for the chord length between the centres of neighbouring squares. Now you have the angle, at the centre of the circle, subtended by the chord between square centres, and can easily compute the radius of the circle from the trigonometry of a triangle.
And, as to your follow up question: I suggest that you work out the problem for squares of side length min(h,w) on a circle, then transform the squares to rectangles and the circle to an ellipse with eccentricity h/w (or w/h).
I would solve it like this:
To find the relation between the radius r and length l let's analyze dimensionless representation
get the centres on a circle (x1,y1)..(xn,yn)
from each center get lower right corner of the i-th square and upper left corner of the i+1-th square
the two points should either have equal x or equal y, whichever yields smaller l
procedure should be repeated for each center and the one that yields smallest l is the final solution.
This is the optimal solution and can be solved it terms of r = f(l).
The solution can be adapted to rectangles by adjusting the formula for xLR[i] and yUL[i+1].
Will try to give some pseudo code.
EDIT:
There's a bug in the procedure, lower right and upper left are not necessary closest points for two neighbouring squares/rectangles.
Let's assume you solved the problem for 3 or 4 squares.
If you have n >= 5 squares, and position one square at the top of the circle, you'll have another square fall into the first quadrant of a cartesian plane concentric with your circle.
The problem is then to find a radius r for the circle such that the left side of the circle next to the top one, and the right side of the top circle do not 'cross' each other.
The x coordinate of the right side of the top circle is x1 = L/2, where L is the side of a square. The x coordinate of the left side of the circle next to the top one is x2 = r cos a - L/2, where r is the radius and a is the angle between each pair of square centres (a = 360/n degrees).
So we need to solve x1 <= x2, which leads to
r >= L / cos a.
L and a are known, so we're done :-)
You start with an arbitrary circle (e.g., with a diameter of (* n l)) and position the squares evenly on the circumference. Then you go through each pair of adjacent squares and:
calculate the straight line connecting their mid points,
calculate the intersection of this line with the intervening square sides (M1 and M2 are the mid points, S1 and S2 the corresponding intersections with the square side:
S2 S1
M1--------------*----------*---------------M2
------------------------
| |
| |
| |
| |
| M1 |
| \ |
| \ |
| -------*------- +--------
| | \ | |
| | \ | |
-------+---------*------ |
| \ |
| M2 |
| |
| |
| |
| |
-------------------------
calculate the scale factor you would need to make S1 and S2 fall together (simply the ratio of the sum of M1-S1 and S2-M2 to M1-M2), and
finally scale the circle by the maximum of the found scale factors.
Edit: This is the exact solution. However, a little thought can optimize this further for speed:
You only need to do this for the squares closest to 45° (if n is even) resp. 45° and 135° (if n is odd; actually, you might prove that only one of these is necessary).
For large n, the optimal spacing of the squares on the circle will quickly approach the length of a diagonal of a square. You could thus precompute the scaling factors for a few small n (up to a dozen or so), and then have a good enough approximation with the diagonal.

Resources