Dividing a geographic region - matlab

I have a certain geographic region defined by the bottom left and top right coordinates. How can I divide this region into areas of 20x20km. I mean in practial the shape of the earth is not flat it's round. The bounding box is just an approximation. It's not even rectangular in actual sense. It's just an assumption. Lets say the bottomleft coordinate is given by x1,y1 and the topright coordinate is given by x2,y2, the length of x1 to x2 at y1 is different than that of the length between x1 to x2 at y2. How can I overcome this issue
Actually, I have to create a spatial meshgrid for this region using matlab's meshgrid function. So that the grids are of area 20x20km.
meshgrid(x1:deltaY:x2,y1:deltaX:y2)
As you can see I can have only one deltaX and one deltaY. I want to choose deltaX and deltaY such that the increments create grid of size 20x20km. However this deltaX and deltaY are supposed to vary based upon the location. Any suggestions?
I mean lets say deltaX=del1. Then distance between points (x1,y1) to (x1,y1+del1) is 20km. BUt when I measure the distance between points (x2,y1) to (x2, y1_del1) the distance is < 20km. The meshgrid function above does creates mesh. But the distances are not consistent. Any ideas how to overcome this issue?

Bear in mind that 20km on the surface of the earth is a REALLY short distance, about .01 radians - so the area you're looking at would be approximated as flat for anything non-scientific. Assuming it is scientific...
To get something other than monotonic steps in meshgrid you should create a function which takes as its input your desired (x,y) and maps it relative to (x_0,y_0) and (x_max,y_max) in your units of choice. Here's an inline function demonstrating the idea of using a function for meshgrid steps
step=inline('log10(x)');
[x,y]=meshgrid(step(1:10),step(1:10));
image(255*x.*y)
colormap(gray(255))
So how do you determine what the function should be? That's hard for us to answer exactly without a little more information about what your data set looks like, how you're interacting with it, and what your accuracy requirements are. If you have access to the actual location at every point, you should vary one dimension at a time (if your data grid is aligned with your latitude grid, for example) and use a curve fit with model selection techniques (akaike/bayes criterion) to find the best function for your data.

Related

Moving least squares fitting for point displacements having issues

Explanation of the problem:
I have points with (x,y,z) coordinates at two+ distinct times. For convenience, they can be imagined as irregularly spaced points along the surface of an inverted paraboloid.
There is some minimal thickness to the paraboloid. The paraboloid changes shape slightly as time proceeds (like a balloon inflating) and when it does so, all of the points move.
By substracting the coordinates at time2 - time1, I can get the displacement vectors at each point.
It is important to note (and I suspect this might be the source of the problem) that at the first time point, the x and y coordinates range from 0 to 2000, and the z coordinates are all within a narrower range - say 350 to 450. During the deformation, each point has an x component of displacement, y component, and z component.
The x and y components are small (~50 at most), while the z component is the largest (goes up to 400 near the center, much less near the edges).
Using weighted moving least squares at the location of each point, I am trying to fit the components of displacements to a second degree polynomial surface in terms of the original x,y,z coordinates of the point: eg.
x component of
displacement = ax^2 + bxy + cx + dy^2.. + hz^2 + iz + j
I use the lsqr function in MATLAB,like so, looping through each point for each time interval:
Ux = displacements{k,1}(:,1);
Cx = lsqr((adjust_B_matrix'*W*adjust_B_matrix),(adjust_B_matrix'*W*Ux),1e-7,10000);
W is the weight matrix, and adjust_B_matrix is the matrix of all (x,y,z) coordinates at time 1, shifted so that they're all centered around the point at which I'm trying to fit the function.
What is going wrong?
It's just not working -- once I have the functions, they're re-centered around the actual coordinates of the points.
But once I plot the resulting points (initial pointx + displacementx, initial pointy + displacementy, initial pointz + displacementz) by plugging in the coordinates at time 1 into the now-discovered functions, it just spits out a surface that looks just like the surface at time 1.
What might be going wrong? Things I have tried:
It's not an issue with the code itself- I generated 'fake' data using a grid of points and it worked perfectly. The predicted locations were superimposed with the actual coordinates and I was able to get back the function I started with. But in my trial example, I used x,y,z from 0 to 5, evenly spaced.
Global fitting works (but I need local fitting...).
I tried MATLAB's curve fitting toolbox and just tried to fit one of the displacements to only x and y coordinates, globally. It worked perfectly.
I think I shouldn't have a singular matrix issue because I use a large radius (around 75-80) points in the calculations, somewhat dispersed in 3D space.
Suspicions:
I think it has to do with the uneven distribution of initial (x,y,z) coordinates, but I don't know why or how to fix the issue, or even what method I can use.
If you read this far, thank you so much. Any advice would be greatly appreciated.
Figure for reference:
green = predicted points at time 2. Overlapping mostly with red, the actual coordinates of the points at time 1.
blue is the correct coordinates of points at time 2 (this is where the green ones should be if things were working).
image
Updated link for files:
http://a.tmp.ninja/eWfkNmFZyTFk.zip
Contents - code, sample data (please load the .mat files).
I can't actually access the code you posted, so here's some general suggestions.
It does look like the curve fitting toolbox has tools that do exactly what you are looking for, checkout the bottom of this page: https://www.mathworks.com/help/curvefit/polynomial.html#bt9ykh.
It looks like for whatever your learned function for the displacement is just very small or zero everywhere. I suspect the issue is just a minor typo/error on your part somewhere in your pipeline, possibly translating what you have to work with the fit function will reveal the issue.
This really shouldn't be the issue, but in the future if you had much more unbalanced data you could normalize it all before fitting (x_norm = (x - x_mu)/x_std).
Also, I don't think this is your problem either, but you can check if your matrix is close to singular by checking the condition number using the cord() function. So you could check cond(adjust_B_matrix'Wadjust_B_matrix). Second, If you check the documentation for lsqr there is an option to get a debug return flag, that is worth checking too.

finding gradient/curvature of surface defined by arbitrary, non-grid-spaced points

So I have a 3 dimensional matrix of points that (presumably) define a surface. For my purposes, X and Y can be random values but when plotted along with their Z coordinates, they will define some undulating surface. I'd like to measure the local curvatures of said surface, and in order to do that, I need to be able to find the gradient of said surface, at which point calculating the curvature is trivial.
I have not yet found an implementation of how to measure this curvature that doesn't make use of Matlab's gradient function. The problem with Matlab's gradient function is that it assumes that the points are in some sort of order, similar to diff(X). This would suffice if my points were spaced along a grid, which is not necessarily the case.
One possible solution to measuring the gradient is to give in and assign each point to a discrete coordinate in a grid in the XY plane, thus overcoming this issue. However, this solution seems somewhat inelegant and was curious to see if anyone had suggestions. Thanks!
You can use griddata to interpolate from your scattered data points to grid spaced points and then calculate the gradient.

defining a minimal bounding circle in matlab

The question is
a.write a function which finds the circle with the minimal area s.t it bounds a given list of points (use fminsearch and give appropriate plot).
b.If you managed do the same for sphere (find one with minimal volume)
What I've tried so far:
%%Main function
function minarea= mincircle(points)
maxx=max(points(1,:));
maxy=max(points(2m:));
radius=max(maxx,maxy);
minarea=fminsearch(#(x) circle(x,r,c),[0,0])
end
%%This function is supposed to give equalation of circle
function eq=circle(x,r,c)
eq=(x(1)-c(1)).^2+(x(2)-c(2)).^2 %=r?
% and here I don't know how to insert r:
end`
For better understanding I'll attach a sketch.
In these terms I want to find the area of the circle whose center is in O
Note: I don't believe that the circle you drew is the smallest possible bounding circle. It should be a little smaller, up and to the right, and should touch at least two points on its perimeter.
Approaching the problem
We have a set of points, and we want to draw a circle that encompasses all of them. The problem is that you need three bits of information to define a circle: the X and Y coordinates of the circle's center, and the circle's radius. So the problem doesn't seem straightforward.
However, there is a related problem that is much easier to solve. Suppose the circle's center is fixed. From that point, we make a circle grow concentrically outwards so that it becomes bigger and bigger. At some point, the circle will encompass one of the points in our set. As it gets bigger, it will encompass a second point, and a third, until all the points in our set fall within our circle. Clearly, as soon as the last point in the set falls within our circle, we have the smallest possible circle that encompasses all the points, given that we started by fixing the center point of the circle.
Moreover, we can determine what the radius of this circle is. It is simply the maximum distance from any point in the set to the center of the circle, since we stop when the last point is touched by the perimeter of our expanding circle.
The next problem is to determine What is the best starting point to place the center of our circle? Clearly if the starting point is far away from all the points in our set, then the radius must be very large to even encompass one point in the set. Intuitively, it must be "in the middle" of our points somewhere. But where, exactly?
Using fminsearch
My suggestion is that you want to find the point P(x, y) that minimises how large you have to grow the circle to encompass all the points in the set. And we're in luck that we can use fminsearch to find P.
According to the fminsearch documentation, the function you pass in must be a function of one parameter (which may be an array), and it must return a scalar. The idea is that you want the output of your function to be as small as possible, and you want to find out what inputs will make that possible.
In our case, we want to write a function that outputs the size of our circle, given the center of the circle as input. That way, fminsearch will find the center of the smallest possible circle that will still encompass all the points. I'm going to write a function that outputs the radius required to encompass all the points given a center point P.
pointsX = [..]; % X-coordinates of points in the set
pointsY = [..]; % Y-coordinates of points in the set
function r = radiusFromPoint(P)
px = P(1);
py = P(2);
distanceSquared = (pointsX - px).^2 + (pointsY - py).^2;
r = sqrt(max(distanceSquared));
end
Then we want to use fminsearch to find the point that gives us the smallest radius. I've just naively used the origin (0, 0) as my starting estimate, but you may have a better idea (like using the first point in the set)
P0 = [0, 0]; % starting estimate
[P, radiusMin] = fminsearch(#radiusFromPoint, P0);
The circle is defined by its center at P and radius of radiusMin.
And I'll leave it to you to plot the output and generalize to the 3D case!
Actually, while you may need it to complete your homework assignment (I assume that is what this is) you don't really need to use an optimizer at all. The minboundcircle code posted with my minimal bounding tools does it without use of an optimizer. (There is also a minboundsphere tool.)
Regardless, you might find a few tricks in there that will be useful. At the very least, learn how to reduce the size of the problem (and so the speed of solution) by use of a convex hull. After all, it is only the points on the convex hull that can determine a minimal bounding circle. All other points are simply a waste of CPU time.

Arrange the vertices of a 3D convex polygonal plane in counter clockwise direction in MATLAB

I have a convex polygon in 3D. For simplicity, let it be a square with vertices, (0,0,0),(1,1,0),(1,1,1),(0,0,1).. I need to arrange these vertices in counter clockwise order. I found a solution here. It is suggested to determine the angle at the center of the polygon and sort them. I am not clear how is that going to work. Does anyone have a solution? I need a solution which is robust and even works when the vertices get very close.
A sample MATLAB code would be much appreciated!
This is actually quite a tedious problem so instead of actually doing it I am just going to explain how I would do it. First find the equation of the plane (you only need to use 3 points for this) and then find your rotation matrix. Then find your vectors in your new rotated space. After that is all said and done find which quadrant your point is in and if n > 1 in a particular quadrant then you must find the angle of each point (theta = arctan(y/x)). Then simply sort each quadrant by their angle (arguably you can just do separation by pi instead of quadrants (sort the points into when the y-component (post-rotation) is greater than zero).
Sorry I don't have time to actually test this but give it a go and feel free to post your code and I can help debug it if you like.
Luckily you have a convex polygon, so you can use the angle trick: find a point in the interior (e.g., find the midpoint of two non-adjacent points), and draw vectors to all the vertices. Choose one vector as a base, calculate the angles to the other vectors and order them. You can calculate the angles using the dot product: A · B = A B cos θ = |A||B| cos θ.
Below are the steps I followed.
The 3D planar polygon can be rotated to 2D plane using the known formulas. Use the one under the section Rotation matrix from axis and angle.
Then as indicated by #Glenn, an internal points needs to be calculated to find the angles. I take that internal point as the mean of the vertex locations.
Using the x-axis as the reference axis, the angle, on a 0 to 2pi scale, for each vertex can be calculated using atan2 function as explained here.
The non-negative angle measured counterclockwise from vector a to vector b, in the range [0,2pi], if a = [x1,y1] and b = [x2,y2], is given by:
angle = mod(atan2(y2-y1,x2-x1),2*pi);
Finally, sort the angles, [~,XI] = sort(angle);.
It's a long time since I used this, so I might be wrong, but I believe the command convhull does what you need - it returns the convex hull of a set of points (which, since you say your points are a convex set, should be the set of points themselves), arranged in counter-clockwise order.
Note that MathWorks recently delivered a new class DelaunayTri which is intended to superseded the functionality of convhull and other older computational geometry stuff. I believe it's more accurate, especially when the points get very close together. However I haven't tried it.
Hope that helps!
So here's another answer if you want to use convhull. Easily project your polygon into an axes plane by setting one coordinate zero. For example, in (0,0,0),(1,1,0),(1,1,1),(0,0,1) set y=0 to get (0,0),(1,0),(1,1),(0,1). Now your problem is 2D.
You might have to do some work to pick the right coordinate if your polygon's plane is orthogonal to some axis, if it is, pick that axis. The criterion is to make sure that your projected points don't end up on a line.

Matlab and color point specific areas

I have a grid with fixed points and random generated user's positions.
Distances for each point and user are measured from the beginning of the axis 0.0. I want to associate each user to the closest fixed point. I calculate both distance vectors and the min of them per user is pointing to the closest fixed point.
But i am stuck on finding a working way so each fixed point and associated user have something same in plot, p.e. same color and color area.
So my problem is two dimensional:
First is to manage to associate each user to its closest fixed poind
How to color the result.
Thank you.
For the point searching I would use dsearchn for this kind of thing. You can use it with or without delaunay triangulation depending on the ratio of users to fixed sites. I tend to use it the quick and easy way, which in your case would be:
indices_of_closest_fixed_points = dsearchn(fixed_points, user_points)
As for the colors I would suggest you define a color map using something like
mymap = lines(n)
where n is the number of fixed points you have. You can then use scatter to plot the points with specific colors and sizes. Perhaps something like this to get you started:
x = user_points(1,:);
y = user_points(2,:);
S = []; % point sizes, left empty for now
C = mymap(indices_of_closest_fixed_points,:); %colors
scatter(x,y,S,C);
To find the nearest point simply compute the euclidean distance between each user point and the complete set of fixed points. Then the index of the shortest distance will also be the index of the fixed point.
dist = calc_dist(fixedPts, aSingleUserPt)
[~, idx] = min(dist);
To solve the color problem, you'll need to create a colormap from a fixed point index to a unique color. Then when you plot a user point you will set the color of the plot equal to the colormap evaluated at idx
Note the euclidean distance is very easy to calcuate:
euc_dist = sqrt( (x1 - x2)^2 + (y1 - y2)^2 );
There are functions on File Exchange that will let you compute this quickly.