Finding coordinate of rectangle in n-dimension - c++

What is the best way in C++ to calculate the coordinate of a rectangle (hyper-rectangle) in n-dimension?
I have dimensions definition of the rectangle in a 1d vector like:
[min1, max1, min2, max2, ...., minN, maxN]
For example, in 2d the dimensions, the vector is
[min1, max1, min2, max2]
And the corner coordinates I am looking for are
[min1, min2], [min1, max2], [max1, min2], [max1, max2]
How do we do this for a hyper-rectangle in n-dimension?

That hyper-rectangle has 2^N vertices.
To compute the coordinates of i-th vertex where i in [ 0 .. 2^N-1 ] interval, loop over bits in the i from 0 (lowest one) to N-1. If the bit is set, use maximum coordinate for that dimension, if that bit is 0, use minimum coordinate for that dimension.
For example, for cube N=3, it has 8 vertices.
The first one has index 0, 0b000, you’ll get minimum values for all 3 coordinates.
The last one has index 7, 0b111, you’ll get maximum values for all 3 coordinates.
The rest of the vertices are in between, you’ll get some combination of min and max coordinates.

Related

How to get the smallest texel that wraps a triangle

Assume I have the UVs of the three vertices of a triangle. What is the fastest way to get the smallest texel that wraps this triangle? That is, the mip level and the UV coordinates of this texel.
Let us use the following notation:
Let p be the index of your points in the triangle, so p in {0,1,2}
Let n(p) be a 2D vector function representing the normalized texcoords in [0,1] (per component), assigned to point index p
Let t(p,l) nbe the unnormalized tex coords assiged to point p for mipmap level l
This means t(p,l) = n(p) * vec2(width(l), height(l)).
If we want to find the mipmap level, we can do this by calculating the size of the triangle in the base level t(p,0):
Let:
a = t(1,0) - t(0,0)
b = t(2,0) - t(0,0)
a and b represent the vectors of the edges of the triangle in texture space, at the base level. So let's find the maximum individually for each dimension:
x_max = max(a.x,b.x)
y_max = max(a.y,b.y)
These two basically describe the size of an axis-aligned bounding-box around our triangle. So we can use the longest side to find the mipmap level:
m = max(x_max,y_max).
Finding the right mipmap level means finding the level l for which the size m would be <= 1 texel. By going up one mip level, the value of m would be halved. so we get (with the appropriate rounding):
l = floor(log2(ceil(m)))
What we have now is the level where the size of the triangle would fit in one texel. This is the lower bound of the actual level that fullfills your criteria. The triangle might intersect up to 2x2 texels at level n. However, just going up one more level might not do the trick, as it might still intersect different texel in the upper-next level. In the worst case, your triangle encloses the center point of your texture, in which case, only the upmost mip level sized 1x1 will ever completely enclose your triangle completely.
So a naive algorithm could be
start at level l as calculated above above
calculate floor(t(p,l)) for all three points
Compare them. If the are all identical, you are finished, l is the result. If not all three are identical, increase l by one and repeat at step 2.
The resulting l will be the level you searched for.
and the UV coordinates of this texel
A texel doesn't have one UV coordinate, but represents a rectangle in UV space. So it is not clear what you want, but you might want some of the following
the unnormalized integer texel coords, which are just thefloor(t(p,l)) you already calculated
the unnormalized coordinates of the texel center, which is just floor(t(p,l)) + vec2(0.5)
the unnormalized coordinates of the barycenter of the triangle, which is just (t(0,l) + t(1,l) + t(2,l))/3.0
the normalized variant of any of the above, which is just the value divided by the size of level l

Creation of a compression algorithm so I can access the data to interpolate later?

The following is a more elaborative conjecture on what i wish to achieve; here is how far I reached;
A 3d grid, about 303030, or a 3d array, so i can define a function of R3 -> R f(x, y, z) = v More precisely, where x, y, z € [0, N] of float values so for f(0.5, 0.5, 0.5) the result would be the trilinear interpolation for the points (0,0,0), (0,0,1), (0,1,0), (0,1,1), (1,0,0), (1,0,1), (1,1,0) and (1,1,1). With v is equal to the value stored in the array if x, y, and z are integer values, or the trilinear interpolation of the closest points in the array where N_i is the number of points - 1 in the i dimension of the array; x € [0, N_x], y € [0, N_y], and z € [0, N_z]. Now let's Imagine a 1d array(which does not exist, only integer indices), one can make up a value by interpolation between closest actual values, and can extend this to 2d, though if you try to get a value for the position 0.3864 for positions 0 and 1 you need the 4 closest points in the end you can extend to any number of dimensions. Providing the values at (0,0), (0,1), (1,0) and (1,1). n is the number of dimensions which have a non-integer coordinate, but you get the point with a bilinear interpolation, and you'll need exactly 2n points where n is the number of dimensions.
Simplified;
I have a 3d grid of floats which via I wish to access this values in parallel by the thousands In random positions. To which then I want to convert this memory bound process into cpu bound; by flattening the 3d array, and approximate it with a finite Fourier expansion or something similar. Then calculate the values at the required positions of this flattened data and use the calculated values to do the trilinear interpolation. Conclusively, the original code would just access the values by their array indices, one by one. as the values are being accessed randomly and they are far away from each other in memory; which i'm looking for a suitable strategy to access (or calculate if possible) the values based on an index.

Find 2 points in X-Y Plane

I have X-Y plane and points (xi, yi) where x, y and i are integers. Now if I draw infinite lines of slope 1 and -1, I have to find those 2 points which either will lie on the same line or if none of them lie then should output:
Case : If atmost 1 point lies on a line the 2nd point should be the point which has minimum distance from the line. In such cases we can draw the line exactly between those 2 points to minimize the distance.
I am not able to find the solution to this problem. My approach was to look at the points in opposite quadrants but I did not get any solution better than O(n^2).
First, I would transform the points into a different coordinate system that is rotated by 45°:
u = x + y
v = x - y
If the original points lie on a line with slope 1, their v coordinate will be equal. If they lie on a line with slope -1, their u coordinate will be equal.
Now, create two lists of points. One sorted by u, the other sorted by v. Then iterate all the points. To find the point that is closest to the corresponding line, you just have to check the neighbors in the sorted order. If there are neighbors with the same u/v coordinate, you are done. If not, find the neighbor with the smallest u/v difference and remember it. Do this for all the points and report the pair with the smallest distance.

How to calculate coordinate system based on normal vector and center coordinates?

I want to calculate the X direction vector that is determined by the normal vector (Z direction vector) and center coordinates.
For example, given Z direction vector Z(2, 5, 8) , center coordinates point P(5, 10, 14)
Since I have no idea how to do it, any other plain could anybody give me any hint as to what should I do now?
There is infinite number of possible X/Y directions.
If you want to get arbitrary vector perpendicular to given Z, you can apply the next approach:
Compare magnitudes of Z vector components. Exchange the largest and the next components, negate the largest, make the smallest component zero.
For example, if Abs(Z.z)>=Abs(Z.x)>=Abs(Z.y), then vector X = (-Z.z, 0, Z.y) is perpendicular (check that scalar product is zero). For your example:
Z(2, 5, 8)
X(0, -8, 5)
Y = Z x X (vector product)

Create continuous matrix of rectangles from set of rectangles

I have a set of objects(each object contains a rectangle and a value assigned to it) which is kept in a vector container.
See picture below:
I need to create a matrix by drawing horizontal and vertical lines at each y/x lower left (LL) / upper right(UR) coordinate like below:
And I need to assign value = 0 to each new empty rectangle, and to other rectangles which are inside of initial rectangles, I need to assign their old values.
I've implemented this with some naive algorithm but it works too slow when I have huge number of rectangles. My algorithm basically does the following:
- Stores all rectangles in a map container. Each element of the map contains set of rectangles with the same LL Y coordinate and they are sorted by LL X coordinate, i.e. key is LL Y coordinate.
- Stores all X/Y coordinates in set containers.
- Iterates over Y/X coordinate containers, and for each new rectangle finds out if it exists in map or not, if exists-assigns existing value to it, otherwise-assigns 0 value. I.e, for each new rectangle it looks for its LL Y coordinate in map, if such Y exists, then searches through the corresponding value(set of rectangles), otherwise-it searches in a whole map.
Is there an effective algorithm to get needed results?
For n rectangles this can be solved easily in O(n^3) time (or just O(n^2) time if at most a bounded number of rectangles intersect) by looking at the problem a different way. This should be adequate for handling up to thousands of rectangles in a few seconds.
Also, unless some other constraints are added to the problem, the latter time bound is optimal: that is, there exist inputs consisting of n non-intersecting rectangles for which O(n^2) smaller grid rectangles will need to be output (which of course requires O(n^2) time). An example such input is n width-1 rectangles, all having equal bottommost y co-ord and having heights 1, 2, ..., n.
Grid size bounds
First of all, notice that there can be at most 2n vertical lines, and at most 2n horizontal lines, since each input rectangle introduces at most 2 of each kind (it may introduce less if one or both vertical lines are also the edge(s) for some already-considered rectangle, and likewise for horizontal lines). So there can be at most (2*n - 1)^2 = O(n^2) cells in the grid defined by these lines.
The grid cell co-ordinate system
We can invent a co-ordinate system for grid cells in which each cell is identified by its lower-left corner, and the co-ordinates of an intersection of two grid lines is given simply by the number of horizontal grid lines below it and the number of vertical grid lines to its left (so that the bottommost, leftmost grid cell has co-ords (0, 0), the cell to its right has co-ords (1, 0), the cell two cells above that cell has co-ords (1, 2), etc.)
The algorithm
For each input rectangle having LL co-ords (x1, y1) and UR co-ords (x2, y2), we determine the horizontal and vertical intervals that it occupies within the new grid co-ordinate system, and then simply iterate through every cell (i, j) belonging to this rectangular region (i.e., every grid cell (i, j) such that toGridX(x1) <= i < toGridX(x2) and toGridY(y1) <= j < toGridY(y2)) with a nested for loop, recording in a hashtable that the ID (colour?) for the cell at (i, j) should be the colour of the current input rectangle. Input rectangles should be processed in decreasing z-order (implicitly at least there seems to be such an order, from your example) so that for any cell covered by more than one input rectangle, the hashtable will wind up recording whatever the "nearest" rectangle's colour is. Finally, iterate through the hash table, converting each grid co-ord pair (i, j) back to the LL and UR co-ords of the input-space rectangle that corresponds to this grid cell, and output this rectangle with the ID given by the value for this hash key.
Preprocessing
In order to accomplish the above, we need two things: a way to map input-space co-ordinates to grid co-ordinates (to determine the horizontal and vertical grid intervals for a given input rectangle), and a way to map grid co-ordinates back to input-space co-ordinates (to generate the output rectangles in the final step). Both operations are easy to do via that old workhorse, sorting.
Given any corner (x, y) of some input rectangle, the grid x co-ordinate corresponding to x, toGridX(x), is simply the rank position of x within the sorted list of all distinct x positions of vertical edges that are present among the input rectangles. Similarly, toGridY(y) is just the rank position of y within the sorted list of all distinct y positions of horizontal edges that are present among the input rectangles. In the other direction, for any grid co-ordinate (i, j), the corresponding input-space x co-ordinate, fromGridX(i), is simply the i-th smallest x co-ord (ignoring duplicates) of any vertical edge among the input rectangles, and similarly for fromGridY(j). These can all be computed as follows (all array indices start at 0, and I show only how to do it for x co-ords; y co-ords are similar):
For each rectangle i in the input having LL co-ords (x1, y1) and (x2, y2):
Append the two-element array [x1, i] to the list-of-arrays VERT.
Append the two-element array [x2, i] to the list-of-arrays VERT.
Sort the list VERT in increasing order by its first item.
Combine elements in VERT having identical x co-ords. Specifically:
Set j = 0.
For i from 1 to n-1:
If VERT[i][0] == VERT[j][0] then append VERT[i][1] to VERT[j] (thereby forming an array of length 3 or more at position j), otherwise set j = j + 1 and overwrite VERT[j] with the two-element array VERT[i].
Delete VERT[j+1] and all later elements from VERT.
By this time, for any i, VERT[i] is an array that contains (in its second and subsequent positions) the IDs of every input rectangle that uses, as either its left or right edge, the ith-leftmost distinct vertical line used by any input rectangle -- or in other words, the rank-i vertical line. We now "invert" this:
For i from 0 to n-1:
For j from 1 to length(VERT[i])-1:
Set toGridX[VERT[i][j]] = i.
For i from 0 to length(VERT)-1:
Set fromGridX[i] = VERT[i][0].
Running time
As previously established, there are at most O(n^2) grid cells. Each of the n input rectangles can occupy at most all of these cells, each of which is visited once per input rectangle, for a time bound of O(n^3). Note that this is an extremely pessimistic time bound, and for example if none (or none but a bounded number) of your rectangles overlap, then it drops to O(n^2) since no grid cell will ever be visited more than once.
I suspect the lookups and iterations are not fast enough. Things like 'otherwise it searches the whole map' point out that you do very heavy computations.
What I think you need is to use a 2d datastructure. A k-d tree or a BSP would work but the easiest to understand and implement would be a quad tree.
In a quad tree each node represents a rectangle in your space. Each node can be split into 4 children by selecting the mid point along the 2 dimensions and having the children represent the 4 resulting rectangles. Each node also holds the value that you want to assign to the area and an extra flag if the value is uniform.
To mark a rectangle with some value, you start from the root and recursively:
If the input rectangle covers the node rectangle you set the value to that node, mark it as uniform and return.
If the input rectangle and the node rectangle don't touch just return.
If the node is marked as uniform, copy the value to it's children and mark the node not uniform.
Recursively call for the 4 children (you might have to create them).
On the way back, check if the 4 children have the same value and are all marked as uniform and if so mark the node as uniform and set the same value as the children.
The main advantage of this approach is that you get to mark large areas of your map quickly. You can also prove that marking a area is O(logN) where N is the size of your map (with a larger constant than the usual tree).
You can find a more detailed explanation and some helpful images on wikipedia.
Assuming you know the top- and bottom-most y and the left- and right-most x, extend the four vectors belonging to each rectangle to the respective max and min x and y points. Keep a set of extended vertical vectors and a set of extended horizontal ones. Whenever an extended vector is added, it will necessarily intersect with each vector in the perpendicular list - the intersections are the cell coordinates of the matrix.
Once the list of cell coordinates is made, iterate over them and assign values appropriately, looking up if they are in or out of an original rectangle. I'm not too versed in data structures for rectangles, but it seems to me that two interval trees, one for horizontal, the other for vertical could find that answer in O(log n) time per query, where n is the number of intervals in the tree.
All together, this method seems to be O(n * log m) time, where n is the number of cell coordinates in the resultant matrix and m is the number of original rectangles.