Z-Index with out of bound restrictions - z-order-curve

I need to calculate the Z-Index (Morton) of a point on a plane from its 2 coordinates x, y.
Traditionally this is just solved by the bit interleaving.
However I have boundaries, and I want the z-index of the point to only increase the morton count when it's inside the active area, and skip the count when outside.
To be clear, the typical z order in a 4x4 square is:
| 0 1 4 5 |
| 2 3 6 7 |
| 8 9 12 13 |
| 10 11 14 15 |
However if I have a 3x3 active area, I want the index to be calculated like this:
| 0 1 4 x |
| 2 3 5 x |
| 6 7 8 x |
| x x x x |
As you can see the 00-11 quad is full, the 02-13 is skipping the count for the 2 points that fall outside of the active area, same for 20-31, and for 22-33.
Important: I want to do this without iterating.
Is there a known solution for this problem?

I was able to get answer for the question on https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes/
To handle rectangular regions, round up all dimensions to the nearest power of 2 and pack major axis linearly.
For example, endcoding point (2,3) in 5x4 rectangle as follows,
Rounding up 5x4 to nearest power of 2 results in 8x4 i.e. 3 and 2 bits
Encoding point 2,3
First interleave 2bits of 0b010, 0b11 we get 0b1110, and 3rd bit from x dimension becomes 5th bit of result.
Encoding 4,2,
0b100, 0b11 becomes 0b11010
In order to find z-order of 3x3 region, find inverse mapping for 4x4 region using above reverse of above method
while generating map skip any points that fall outside 3x3 region.
mapping would look like
(0,0) -> (0,0)
(0,1) -> (1,0)
(0,2) -> (0,1)
(0,3) -> (1,1)
(1,0) -> (2,0)
(1,2) -> (2,1)
(2,0) -> (0,2)
(2,1) -> (1,2)
(3,0) -> (2,2)
python code might be useful, https://gist.github.com/kannaiah/4eb936b047a987b32555b2642a0979f7

Related

breeze Copy lower triangle not working?

Using breeze 0.13, Scala 2.12.3
I would like to create a symmetric matrix by copying the lower triangle to the upper one. Following the instructions in Linear Algebra Cheat Sheet. May be I use the function incorrectly but it seems like the lowerTriangular function is not working correctly. The copy just
val myMtx = breeze.linalg.DenseMatrix((1,-8,-9) , (2,1,-7), (3,5,1))
//myMtx: breeze.linalg.DenseMatrix[Int] =
// 1 -8 -9
// 2 1 -7
// 3 5 1
Copy lower triangle (seems not working)
breeze.linalg.lowerTriangular(myMtx)
// 1 0 0
// 2 1 0
// 3 5 1
Copy upper triangle (not working either)
breeze.linalg.upperTriangular(myMtx)
// 1 -8 -9
// 0 1 -7
// 0 0 1
In this context, "copy" means returns the matrix in a newly allocated memory. This is contrast with a "view" that indexes into the same backing memory.
With that in mind, both lowerTriangular and upperTriangular seem to be working properly in that it returns a new matrix that has the same elements copied from the original matrix.
The task is now to create a new symmetric matrix that is the copy of the lower triangular. One possible way is to compute the element-wise sum of the lower and lower diagonal transpose, and then subtract the extra copy of the diagonal that was computed. The inner diag() returns a view, as described above, as a vector and that vector is then used to create a diagonal matrix with the second diag().
# val sym = lowerTriangular(myMtx) + lowerTriangular(myMtx).t - diag(diag(myMtx))
sym: DenseMatrix[Int] =
1 2 3
2 1 5
3 5 1

Postgresql Geometric Line - Finding the Y intercept

I have an model that can be represented by multiple linear segments as below:
Y
| _/_________\_
| / \
| / \
| / \
|/ \
|
|________________________ X
I would need to find the value of Y for a given value of X
My initial though was to store each segment as a relational line type {A, B, C}. However I'm not sure what would that buy me in terms of finding a proper query to retrieve the Y value.
Since you are working with linear segments, you should use the lseg data type (the line data type represents a line of infinite length). Once you have your data in that format you can find the intersection of the segments with a vertical line of infinite length at the desired value of X and extract the Y value of the intersection.
CREATE TABLE segments (id int, seg lseg);
INSERT INTO segments VALUES
(1, '[(4,3), (12,15)]'), -- positively inclined line segment
(2, '[(2,19), (24,-4)]'), -- negatively inclined line segment
(3, '[(4,3), (12,3)]'), -- horizontal line segment
(4, '[(5,3), (5,15)]'), -- vertical line segment, collinear at X=5
(5, '[(4,3), (4,15)]'); -- vertical line segment, no intersection at X=5
and then:
test=# SELECT id, 5 AS x, (seg # '((5,-999999999), (5,999999999))'::lseg)[1] AS y
test-# FROM segments;
id | x | y
----+---+------------------
1 | 5 | 4.5
2 | 5 | 15.8636363636364
3 | 5 | 3
4 | 5 |
5 | 5 |
(5 rows)
As is obvious from the above, collinear line segments (i.e. vertical line segments with the same value for X) and segments without intersection return NULL for Y.

Matlab: How to output a matrix which is sorted by distance

I have a cluster of points in 3D point clouds, says
A = [ 1 4 3;
1 2 3;
1 6 3;
1 5 3];
The distance matrix then was found:
D= pdist(A);
Z= squareform(D);
Z =
0 2 2 1
2 0 4 3
2 4 0 1
1 3 1 0
I would like to sort the points so that the sum of the distance travelled through the points will be the smallest, and output in another matrix. This is similar to TSP problem but in a 3D model. Is there any function can do this?
Your help is really appreciated in advance.
This could be one approach and must be efficient enough for a wide range of datasizes -
D = pdist(A);
Z = squareform(D); %// Get distance matrix
N = size(A,1); %// Store the size of the input array for later usage
Z(1:N+1:end) = Inf; %// Set diagonals as Infinites as we intend to find
%// minimum along each row
%// Starting point and initialize an array to store the indices according
%// to the sorted requirements set in the question
idx = 1;
out_idx = zeros(N,1);
out_idx(1) = idx;
%// Perform an iterative search to look for nearest one starting from point-1
for k = 2:N
start_ind = idx;
[~,idx] = min(Z(start_ind,:));
Z(:,start_ind) = Inf;
out_idx(k) = idx;
end
%// Now that you have the list of indices based on the next closest one,
%// sort the input array based on those indices and have the desired output
out = A(out_idx,:)
Sample run for given input -
A =
1 4 3
1 2 3
1 6 3
1 5 3
1 2 3
out =
1 4 3
1 5 3
1 6 3
1 2 3
1 2 3
The only way I can see you do this is by brute force. Also bear in mind that because this is brute force, this will scale very badly as the total number of points increases. This is fine for just 4 points, but if you want to scale this up, the total number of permutations for N points would be N! so be mindful of this before using this approach. If the number of points increases, then you may get to a point where you run out of memory. For example, for 10 points, 10! = 3628800, so this probably won't bode well with memory if you try and go beyond 10 points.
What I can suggest is to generate all possible permutations of visiting the 4 points, then for each pair of points (pt. 1 -> pt. 2, pt. 2 -> pt. 3, pt. 3 -> pt. 4), determine and accumulate the distances, then find the minimum distance accumulated. Whichever distance is the minimum will give you the sequence of nodes you need to visit.
Start with perms to generate all possible ways to visit four points exactly once, then for each pair of points, figure out the distances between the pairs and accumulate the distances. Keep considering pairs of points along each unique permutation until we reach the end. Once we're done, find the smallest distance that was generated, and return the sequence of points to generate this sequence.
Something like:
%// Your code
A = [ 1 4 3;
1 2 3;
1 6 3;
1 5 3];
D = pdist(A);
Z = squareform(D);
%// Generate all possible permutations to visit for our points
V = perms(1:size(A,1));
%// Used to accumulate our distances per point pair
dists = zeros(size(V,1), 1);
%// For each point pair
for idx = 1 : size(V,2)-1
%// Get the point pair in the sequence
p1 = V(:,idx);
p2 = V(:,idx+1);
%// Figure out the distance between the two points and add them up
dists = dists + Z(sub2ind(size(Z), p1, p2));
end
%// Find which sequence gave the minimum distance travelled
[~,min_idx] = min(dists);
%// Find the sequence of points to generate the minimum
seq = V(min_idx,:);
%// Give the actual points themselves
out = A(seq,:);
seq and out give the actual sequence of points we need to visit, followed by the actual points themselves. Note that we find one such possible combination. There may be a chance that there is more than one possible way to get the minimum distance travelled. This code just returns one possible combination. As such, what I get with the above is:
>> seq
seq =
3 4 1 2
>> out
out =
1 6 3
1 5 3
1 4 3
1 2 3
What the above is saying is that we need to start at point 3, then move to point 4, point 1, then end at point 2. Also, the sequence of pairs of points we need to visit is points 3 and 4, then points 4 and 1 and finally points 1 and 2. The distances are:
Pt. 3 - Pt. 4 - 1
Pt. 4 - Pt. 1 - 1
Pt. 1 - Pt. 2 - 2
Total distance = 4
If you take a look at this particular problem, the minimum possible distance would be 4 but there is certainly more than one way to get the distance 4. This code just gives you one such possible traversal.

Plotting a normpdf in 3D over scatter plot/linear regression

I have a set of data x(1000,2),
2 18.1199158925616
3 9.56472607516328
7 34.3629828698699
4 30.9865760010538
7 54.4869549747429
8 54.7696742935546
2 1.45832407805944
3 15.4231700658276
8 57.0479651194063
1 5.34909555648445
2 11.5593766410445
2 17.4392978010484
6 25.4072607558367
4 15.1248062077068
2 13.2035176450795
7 33.2507069131440
5 21.6859046133920
3 18.4458236149053
1 0.824962982951128
8 46.6322862041701
8 43.6889420657037
2 17.0930689315346
3 13.9754117410459
2 1.99260423380962
11 86.3172411757665
8 50.6244869641866
1 1.16602336459361
2 12.6604166373800
2 17.4519078987572
5 27.4799515521804
which I have plotted plot(x(:,1),x(:,2),'*r');in scatter form:
but would like to have something like below using normpdf for selected values of x(:,1):
To find values in x(:,2) column corresponding to x(:,1)==3:
[x3]=x(find(x(:,1)==3),2);
mu=mean(x3);
sig=std(x3);
Y=normpdf(x3,mu,sig);
figure('color',[1,1,1]);
hhh=plot3(3*ones(length(xi)),x(find(x(:,1)==3),2),Y,'-r')
p = polyfit(x(:,1),x(:,2),1);
plin=plot(x(:,1),polyval(p,x(:,1)),'-b');
but how do I get the red dotted pdf to be a smooth curve as '-r' gives me zig-zag lines. Do I have to order the data in some way?
Also how do I get the red dots in the center of the normal curve down to the blue line?
And perhaps most importantly, as a well informed reader would you like to see this type of plot or perhaps something else less fancy?
Yes, a sorting of the x-values should get you the red curve. Also you do not need find() here. I have not tested the code, but these changes should work:
[x3]=sort(x(x(:,1)==3,2));
mu=mean(x3);
sig=std(x3);
Y=normpdf(x3,mu,sig);
figure('color',[1,1,1]);
hhh=plot3(3*ones(length(xi)),x3,Y,'-r')
p = polyfit(x(:,1),x(:,2),1);
plin=plot(x(:,1),polyval(p,x(:,1)),'-b');
As for the value of such a plot, I would guess that it will be quite cluttered. But I guess it could be used to give a general view of the distribution of the data.

how to plot with vectical lines with gnuplot?

I study for sometime but didn't get the answer yet.
The data is like:
#X0, Y0_0, Y0_1
1 1 2
3 2 4
7 1 3
....
I need to draw vectical line from (X0, Y0_0) to (X0, Y0_1). gnuplot has financebar and candlesticks but they are too much.
I just want a single vectical line for each record.
Appreciate for any help.
If I understand correctly what you are after, the following script should do the job:
set offsets 1, 1, 1, 1
set key off
plot "-" u 1:2:(0):($3) w vectors nohead
1 1 2
3 2 4
7 1 3
e
What it does:
It sets the offset, so that you can see the left and right vector, so that it is not hidden by the axis.
Remove the label, since it has no use in this example
Plots vectors with no head (a single vertical line). The "parameters" are as stated here the x y dx dy. The (0) stands for dx=0 and the brackets are important. Otherwise the column 0 would be used which in gnuplot is the index of the data (line number).
Below the plot you will get with the script above: