Displaying a subset of longitude/latitude points? - algorithm

I have an array of coordinates (latitude and longitude) maded in this way:
[0] = "45.01234,9.12345"
[1] = "46.11111,9.12345"
[2] = "47.22222,9.98765"
[...] etc
In a loop, convert these coordinates in meters (UTM northing / UTM easting) and after that I convert these coords in pixel (X / Y) on screen (the output device is an iPhone) to draw a route line on a custom map.
[0] = "512335.00000,502333.666666"
[...] etc
The returning pixel are passed to a method that draw a line on screen (simulating a route calculation).
[0] = "20,30"
[1] = "21,31"
[2] = "25,40"
[...] etc
As coordinate (lat/lon) are too many, I need to truncate lat/lon array eliminating the values that doesn't fill in the map bound (the visible part of map on screen).
Map bounds are 2 couple of coords lat/lon, upper left, and lower right.
Now, what is the best way to loop on this array (NOT SORTED) and check if a value is or not in bound and after remove the value that is outside?
To return a clean array that contains only the coords visible on screen?
Note: the coords array is a very big array. 4000/5000 Couple of items.
This is a method that should be looped every drag or zoom.
How can I optimize search and controls in this array?

I'd suggest breaking this into several steps:
Convert each longitude/latitude pair into a pair of meters in your new coordinate system.
Create a kd-tree data structure holding all the points in the set. This allows you to efficiently query which points lie in a given rectangular range very efficiently.
Whenever the viewport changes, find all points in the kd-tree that will be displayed in that rectangle.
To display the points, iterate over the set of points that will be displayed and display each of them.

Related

Error while converting a 3d matrix into an animated gif in Matlab

I am attempting to make a movie from a 3d matrix, which is made multiple 2d matrices and the third dimension is time.
I have read the following question witch is pretty much the same and I have attempted to do the same.
How to make a video from a 3d matrix in matlab
The 3d matrix I want to play is stored in a object instanced A.
a.movie; % 3D matrix
X = permute(a.movie,[1 2 4 3]); % 4D matrix
movie = immovie(X,map); % map is the colormap you want to use
implay(movie);
I would like to know why should a.movie be permuted? And what is the map referred?
How can I define 0 as blue and 100 as red?
The post you linked us to exactly answers that. immovie expects a m x n x 1 x k matrix where m and n are the rows and columns of 1 slice from your 3D matrix, and k is the number of slices. You currently have your 3D matrix set up to be m x n x k. Therefore, by permuting, you are artificially creating a 4D matrix from your 3D original matrix. Simply put, you can think of your 3D matrix as having a singleton 4D dimension: m x n x k x 1. The job of permute here is to swap the 3rd and 4th dimension - that's why you see the [1 2 4 3] vector in the permute call. The first and second dimensions represent the rows and columns, and you leave those empty.
Now that answers the permute question. The map is defined as a colour map. This maps each value in your 3D matrix to a unique colour. Basically, the colour map is a M x 3 matrix where row in this matrix corresponds to a unique colour. Each column represents a colour channel. Therefore, the first column represents the proportion of red you want, the second channel is the proportion of green and the last is the proportion of blue. Keep in mind that these colours should be normalized between [0,1].
The goal of the colour map is to take each value in your 3D matrix, and figure out which colour that value maps to. The way to do this is to use each value in your 3D matrix exactly as it is and use this to access the row of the colour map. This row gives you the colours you want. Now, I'm assuming that your values in the 3D matrix span from 0 to 100.
If you want the colours to span between blue and red. The blue colour has an exact colour of RGB = (0,0,1) assuming normalized coordinates and similarly, the red represents the exact colour of RGB = (1,0,0). Therefore, start off with RGB = (0,0,1), then start linearly increasing the red component while linearly decreasing the blue component until the red is 1 and the blue is 0.
What we can do is figure out how many unique values there are in your matrix, then we can create our colour map that way so we can ensure that each value in your matrix gets assigned to one colour. However, this will require that a.movie be redefined to ensure that we can assign a value to a colour.
Therefore, I'd create your colour map like this:
[unq,~,id] = unique(a.movie);
movie_IDs = reshape(id, size(a.movie));
M = numel(unq);
map = [linspace(1,0,M).', zeros(M,1), linspace(0,1,M).'];
Now, go ahead and use map with the above code to create your movie.
X = permute(movie_IDs,[1 2 4 3]); % 4D matrix
movie = immovie(X,map); % map is the colormap you want to use
implay(movie);
However, the colour map you're looking at is the jet colour map. Therefore, you can simply just create a jet colour map:
map = jet(M);
However, you must make sure you run through each value in a.movie and assign a unique integer to each value to ensure that there are no gaps in your data and every value gets assigned to a new value that goes up from 1 to M in order for the movie to properly access the right colour.
MATLAB has a bunch of built-in colour maps for you to use if you don't feel like designing your own colour map. http://www.mathworks.com/help/matlab/ref/colormap.html#inputarg_map - However, from what I see in your post, making the colour map is what you want to do.

Algorithm to find the smallest box containing a set of 3D objects

This is a problem that I meet on Unity3D, but it's actually a request for help for a general graphical algorithm.
I have a set of 3D objects/meshes that form a map. To generalize let's say that they are arrays of 6 numbers: position and size.
I need to create a box that contains all these objects. The box must have the minimum possible volume. To generalize, we can say that also the box will end to be an array of 9 numbers: position, size and rotation.
So at the end I'm talking about a function that takes a set of array[6] and returns an array[9].
The box can be obviously rotated in 3 directions as needed, so it's not just "take the smallest and the biggest x, y and z values".
Probably this question can some how easily resolved with a few trigonometrical functions, but i don't have any idea of how to do it! I only could create something that does that iteratively, but that's not what I want.
A particular case of this problem could be to find the minimum box containing a set of points. Probably this question is easier and some how can be extended to the main problem. Anyway... I can't solve neither this one! :)
Thanks for the help.
You can find the 3d convex hull of all the vertex. Using the points of the convex hull you can form the faces of the convex hull. Then incline one by one all the faces parallel to x-axis. Then find the min x/y/z and max x/y/z along each face rotation.Calculate the volume using min x/y/z and max x/y/z. Find the index corresponding to the minimum volume. Rotate back this volume using the rotation you used for the corresponding face. This problem is similar to the 2d problem of minimum area rectangle. For minimum area rectangle the reference is https://gis.stackexchange.com/questions/22895/how-to-find-the-minimum-area-rectangle-for-given-points
Quick easy way to get the bottom left rear corner of your new box, and the top right forward corner.
Either:
List<GameObjects> gameObjects; // <-- your game objects here
List<Bounds> objectsBounds = gameObjects.Select(item => item.GetComponent<MeshRenderer>().bounds);
Vector3 min = objectsBounds.Min(item => item.min);
Vector3 max = objectsBounds.Max(item => item.max);
Or:
List<GameObjects> gameObjects; // <-- your game objects here
List<Bounds> objectsBounds = gameObjects.Select(item => item.GetComponent<MeshRenderer>().bounds);
Vector3 min = Vector3.one * Single.MaxValue;
Vector3 max = Vector3.one * Single.MinValue;
foreach(Bounds bounds in objectsBounds)
if(bounds.min < min) min = bounds.min;
foreach(Bounds bounds in objectsBounds)
if(bounds.max > max) max = bounds.max;

Folding a selection of points on a 3D cube

I am trying to find an effective algorithm for the following 3D Cube Selection problem:
Imagine a 2D array of Points (lets make it square of size x size) and call it a side.
For ease of calculations lets declare max as size-1
Create a Cube of six sides, keeping 0,0 at the lower left hand side and max,max at top right.
Using z to track the side a single cube is located, y as up and x as right
public class Point3D {
public int x,y,z;
public Point3D(){}
public Point3D(int X, int Y, int Z) {
x = X;
y = Y;
z = Z;
}
}
Point3D[,,] CreateCube(int size)
{
Point3D[,,] Cube = new Point3D[6, size, size];
for(int z=0;z<6;z++)
{
for(int y=0;y<size;y++)
{
for(int x=0;x<size;x++)
{
Cube[z,y,x] = new Point3D(x,y,z);
}
}
}
return Cube;
}
Now to select a random single point, we can just use three random numbers such that:
Point3D point = new Point(
Random(0,size), // 0 and max
Random(0,size), // 0 and max
Random(0,6)); // 0 and 5
To select a plus we could detect if a given direction would fit inside the current side.
Otherwise we find the cube located on the side touching the center point.
Using 4 functions with something like:
private T GetUpFrom<T>(T[,,] dataSet, Point3D point) where T : class {
if(point.y < max)
return dataSet[point.z, point.y + 1, point.x];
else {
switch(point.z) {
case 0: return dataSet[1, point.x, max]; // x+
case 1: return dataSet[5, max, max - point.x];// y+
case 2: return dataSet[1, 0, point.x]; // z+
case 3: return dataSet[1, max - point.x, 0]; // x-
case 4: return dataSet[2, max, point.x]; // y-
case 5: return dataSet[1, max, max - point.x];// z-
}
}
return null;
}
Now I would like to find a way to select arbitrary shapes (like predefined random blobs) at a random point.
But would settle for adjusting it to either a Square or jagged Circle.
The actual surface area would be warped and folded onto itself on corners, which is fine and does not need compensating ( imagine putting a sticker on the corner on a cube, if the corner matches the center of the sticker one fourth of the sticker would need to be removed for it to stick and fold on the corner). Again this is the desired effect.
No duplicate selections are allowed, thus cubes that would be selected twice would need to be filtered somehow (or calculated in such a way that duplicates do not occur). Which could be a simple as using a HashSet or a List and using a helper function to check if the entry is unique (which is fine as selections will always be far below 1000 cubes max).
The delegate for this function in the class containing the Sides of the Cube looks like:
delegate T[] SelectShape(Point3D point, int size);
Currently I'm thinking of checking each side of the Cube to see which part of the selection is located on that side.
Calculating which part of the selection is on the same side of the selected Point3D, would be trivial as we don't need to translate the positions, just the boundary.
Next would be 5 translations, followed by checking the other 5 sides to see if part of the selected area is on that side.
I'm getting rusty in solving problems like this, so was wondering if anyone has a better solution for this problem.
#arghbleargh Requested a further explanation:
We will use a Cube of 6 sides and use a size of 16. Each side is 16x16 points.
Stored as a three dimensional array I used z for side, y, x such that the array would be initiated with: new Point3D[z, y, x], it would work almost identical for jagged arrays, which are serializable by default (so that would be nice too) [z][y][x] but would require seperate initialization of each subarray.
Let's select a square with the size of 5x5, centered around a selected point.
To find such a 5x5 square substract and add 2 to the axis in question: x-2 to x+2 and y-2 to y+2.
Randomly selectubg a side, the point we select is z = 0 (the x+ side of the Cube), y = 6, x = 6.
Both 6-2 and 6+2 are well within the limits of 16 x 16 array of the side and easy to select.
Shifting the selection point to x=0 and y=6 however would prove a little more challenging.
As x - 2 would require a look up of the side to the left of the side we selected.
Luckily we selected side 0 or x+, because as long as we are not on the top or bottom side and not going to the top or bottom side of the cube, all axis are x+ = right, y+ = up.
So to get the coordinates on the side to the left would only require a subtraction of max (size - 1) - x. Remember size = 16, max = 15, x = 0-2 = -2, max - x = 13.
The subsection on this side would thus be x = 13 to 15, y = 4 to 8.
Adding this to the part we could select on the original side would give the entire selection.
Shifting the selection to 0,6 would prove more complicated, as now we cannot hide behind the safety of knowing all axis align easily. Some rotation might be required. There are only 4 possible translations, so it is still manageable.
Shifting to 0,0 is where the problems really start to appear.
As now both left and down require to wrap around to other sides. Further more, as even the subdivided part would have an area fall outside.
The only salve on this wound is that we do not care about the overlapping parts of the selection.
So we can either skip them when possible or filter them from the results later.
Now that we move from a 'normal axis' side to the bottom one, we would need to rotate and match the correct coordinates so that the points wrap around the edge correctly.
As the axis of each side are folded in a cube, some axis might need to flip or rotate to select the right points.
The question remains if there are better solutions available of selecting all points on a cube which are inside an area. Perhaps I could give each side a translation matrix and test coordinates in world space?
Found a pretty good solution that requires little effort to implement.
Create a storage for a Hollow Cube with a size of n + 2, where n is the size of the cube contained in the data. This satisfies the : sides are touching but do not overlap or share certain points.
This will simplify calculations and translations by creating a lookup array that uses Cartesian coordinates.
With a single translation function to take the coordinates of a selected point, get the 'world position'.
Using that function we can store each point into the cartesian lookup array.
When selecting a point, we can again use the same function (or use stored data) and subtract (to get AA or min position) and add (to get BB or max position).
Then we can just lookup each entry between the AA.xyz and BB.xyz coordinates.
Each null entry should be skipped.
Optimize if required by using a type of array that return null if z is not 0 or size-1 and thus does not need to store null references of the 'hollow cube' in the middle.
Now that the cube can select 3D cubes, the other shapes are trivial, given a 3D point, define a 3D shape and test each part in the shape with the lookup array, if not null add it to selection.
Each point is only selected once as we only check each position once.
A little calculation overhead due to testing against the empty inside and outside of the cube, but array access is so fast that this solution is fine for my current project.

create 3D image from coordinates and intensity values

I am trying to create a 3D array of size 1000x1000x1000 with all the elements (corresponding to voxels) being zero and then assign a random value in the 2000 to 2001 range instead of 0 to some specific elements in the array and finally store it as a binary file.
The array named "coord" is the Nx3 matrix coordinates (x,y,z) of the points that I need them to be assigned the random value in the 3D array.))
I should mention that all the x,y,z values of the coordinate matrix are floating point numbers with: 0<=x<=1000 0<=y<=1000 0<=z<=1000
My aim is to export the 3D matrix in a binary format (other than MATLAB's default binary format) so that I can use it with other programs.
Here is what I've been up to so far:
load coord;
a=coord(:,1);
b=coord(:,2);
c=coord(:,3);
d=rand(1000,1)*2000;
dd = 0:2:1000;
[xq,yq,zq] = meshgrid(dd,dd,dd);
vq = griddata3(a,b,c,d,xq,yq,zq,'nearest');
h=figure;
plot3(a,b,c,'ro')
%=========================================%
fid=fopen('data.bin','w');
fwrite(fid,vq,'single');
fclose(fid);
In the above code a, b and c are the coordinates of each point and d is the corresponding intensity values for the desired range. While it is possible to create a 3D mesh (using meshgrid) and then interpolate the intensity values for mesh points (using griddata3), the final result (vq) would not be the actual points (ai,bi,ci) and corresponding intensities , but rather an interpolated set of points which is pretty useful for visualization purposes (for instance if you like to fit a 3D surface which fits through actual data).
I am simply trying to find a way to store the actual data-points and their intensities into a file and export it.
Any help is highly appreciated.
If you want to save to files that will allow importing into a visualization software, a series of Tiff files will most likely be convenient, i.e.
maxValue = 2000; % this is the maximum signal that can possibly occur
% according to your code
for z = 1:size(vq,3)
%# convert slice z to 16 bit
currentSlice = vq(:,:,z);
currentSlice = uint16(round(currentSlice/maxValue))
%# save to file
imwrite(currentSlice, sprintf('testImg_z%04i.tif',z),'tif');
end
Note that if you create a double array of dimensions 1000x1000x1000, you'll need 8GB of contiguous RAM.
How about something like:
%# 3D array
voxels = zeros([1000 1000 1000]);
%# round points coordinates, and clamp to valid range [1,1000]
load coords
coords = round(coords);
coords = min(max(coords,1),1000);
%# convert to linear indices
idx = sub2ind(size(voxels), coords(:,1), coords(:,2), coords(:,3));
%# random values in the 2000 to 2001 range
v = rand(size(idx)) + 2000;
%# assign those values to the chosen points
voxels(idx) = v;

MatLab - Best way of finding the closest value

I'm working with Matlab's image toolbox. In particular, after binarizing and labeling an image, I run
props = regionprops(labeledImage, 'Centroid');
to get the centroid of all the connected objects. Now, I would like to find the one closer to a pair of coordinates (namely the center of the image). Of course I know I could use a for loop checking each props[i].Centroid pair of coordinates, but that's slow and there must be a matlaby way of doing it...
which is...?
Thanks in advance
The output from REGIONPROPS will be an N-by-1 structure array with one field 'Centroid' that contains a 1-by-2 array. You can first concatenate all these arrays into an N-by-2 array using the function VERTCAT. Then you can replicate your image center coordinates (assumed to be in a 1-by-2 array) using the function REPMAT so that it becomes an N-by-2 array. Now you can compute the distances using vectorized operations and find the index of the value with the minimum distance using the function MIN:
props = regionprops(labeledImage, 'Centroid');
centers = vertcat(props.Centroid); %# Vertically concatenate the centroids
imageCenter = [x y]; %# Your image center coordinates
origin = repmat(imageCenter,numel(props),1); %# Replicate the coordinates
squaredDistance = sum(abs(centers-origin).^2,2); %# Compute the squared distance
[~,minIndex] = min(squaredDistance); %# Find index of the minimum
Note that since you just want the minimum distance, you can just use the squared distances and avoid a needless call to SQRT. Also note that the function BSXFUN could be used as an alternative to replicating the image center coordinates to subtract them from the object centroids.

Resources