I would like to calculate the average distance from a point to a polygon using MATLAB. The polygon is represented by a sequence of points, such as P{(0,0),(1,0),(2,0.5),(1,1),(2,2),(0,2),(0,0)}. Note that the polygon could be convex or nonconvex. To calculate the average distance between point a(-1,-1) and polygon P, I can use the equation as below
I do not know how to implement that using MATLAB. Is there any function I can use?
You can probably use this intpoly function from: https://www.mathworks.com/matlabcentral/fileexchange/62278-intpoly-f-x-y
Something like f = #(x,y) sqrt((x+1).^2 + (y+1).^2) to throw into intploy
Related
I am searching for a (fast) way to calculate the nearest point y in a dataset to a given point x under a (x,y)-depending distance function.
My distance function has the form: d(x,y) = 1/f(x,y) * |||x-y||^2, where ||x|| denotes the standard Euclidean-norm. The function f(x,y) fulfills all necessary properties such that d(x,y) is a distance measurement i.e. positive, symmetric,...
For a "normal" distance function I could to some transformation on the data itself and use some k-nearest neighbor approaches. But for this case I could not find something useful. Does anyone have an idea?
Right now, I am using Julia for the implementation.
You should be able to use most standard spacial indexes (kd-tree, r-tree, quadtree, and their derivatives) as long as d(x,y) is "convex".
With "convex" I mean that a curve of equidistant points around P is convex. E.g. for Euclidean this is a circle, for Manhatten/Taxi distance it is a square.
This is required because these indexes usually partition the data into squares, rectangles or half-spaces (kd-tree), so they rely on calculating the minimum distance to a group of points by calculating the distance to the corner or sides of a bounding rectangle. As long as your distance function is convex (or at least not concave) then any index of these indexes should work.
Euclidean is distance transform from a . I am using Euclidean = bwdist(a,'euclidean');
Based on this, may i know how the calculation works? from/to what point MATLAB calculate to get the Euclidean based on MATLAB?
From formula , sqrt[(x2-x1)^2 + (y2-y1)^2], which means we need 2 points. How do MATLAB calculation for each pixel? Thank you
I think the following link explains about the function quite directly.
https://uk.mathworks.com/help/images/ref/bwdist.html
D = bwdist(BW) computes the Euclidean distance transform of the binary image BW. For each pixel in BW, the distance transform assigns a number that is the distance between that pixel and the nearest nonzero pixel of BW.
for your first point a(1,1), the nearest point is a(2,2), so the distance is sqrt(2).
for a(1,2), the nearest non-zero is a(2,2) too, so the distance is sqrt(1) = 1.
for a(2,2), the nearest non-zero is it self, so the distance is sqrt(0) = 0.
Good luck.
I want to calculate geodesic distance between non-adjacent nodes in an directed graph. As in the following matrix (W), zeros reperesent that those nodes are non-adjacent and other values show weights of the edges corresponding nodes. I calculated the distance according to the following equation:
I used the MATLAB function graphshortestpath(). However, I'm afraid this function couldn't provide what I am looking for. So the question is what is another way to calculate such a distance? Is there another function in MATLAB for that? Is it possible that making the matrix sparse affects final result?
Program code:
N=6; % Size of matrix W
W=[0,0.797944993710195,0,0,0,0;0.495326358306295,0,0.164911895411107,0,0,0;0,0.0530273831645896,0,0.00901073533222818,0,0;0,0,0.00709165683115063,0,0.438584093809830,0;0,0,0,0.397895339311598,0,0.000916573989905329;0,0,0,0,0.00104307323830613,0]; %Connectivity matrix
Geo_dist=zeros(N); %temporary variable for geodesic distance measurement
W_sparse=sparse(W); %Making W sparse because the matlab function works only with sparse matrix
for g=1:N
for h=1:N
if W(g,h)==0 & g~=h;
Geo_dist(g,h)=graphshortestpath(W_sparse,g,h,'directed',false);
end
end
end
Can you use bwdistgeodesic or graydist in the Image Processing Toolbox directly on the image grid?
https://www.mathworks.com/help/images/ref/graydist.html
https://www.mathworks.com/help/images/ref/bwdistgeodesic.html
Or if you prefer something smoother, imsegfmm will let you use fast marching method to compute the geodesic distance if you look at the doc example:
https://www.mathworks.com/help/images/ref/imsegfmm.html
I'm assuming in my response that you have gridded image data and that this isn't a graph of arbitrary connectivity since this is tagged "image-processing".
In matlab, I have a list of 2410 locations given by their latitude and longitude. I want to create a distance matrix in kilometres. I know how to do this in degrees but how do I do this in kilometres? I have the mapping toolbox, using 2016b. Thanks!
For example, my distance matrix in degrees looks like this:
First you need to ask your self what you mean by distance.
Do you want the euclidean distance between the points? Imagine you could tunnel through the earth from one point to the other, this is the euclidean distance between the points. To calculate this distance you need to first convert each of the lat long points to ecef points. You can do this conversion with this code (https://www.mathworks.com/matlabcentral/fileexchange/7942-covert-lat--lon--alt-to-ecef-cartesian). After you've converted each point to an ecef point you can now calculate the euclidean norm https://en.wikipedia.org/wiki/Norm_(mathematics)) between each possible pair of points.
Or do you want to calculate the distance a traveler would traverse if they were to walk along the surface of the earth. From the looks of it, this is a much more difficult problem requiring an iterative solver. Fortunately someone has already done the work of implementing an algorithm to do this for you (https://www.mathworks.com/matlabcentral/fileexchange/5379-geodetic-distance-on-wgs84-earth-ellipsoid). Note if you read the comments of this function it appears as if mathworks has already implemented a different algorithm to perform the same calculation in the mapping toolbox. To calculate the matrix you simply need to iterate over each possible pairing of lat long points and plug them into the vdist function.
Following should calculate the distance matrix for you using the vdist function above. Note I have not tested this code so you may to to correct errors.
points % assuming this is a matrix of your points [2 x N] formatted as follows
% [ lat1 , lat2, ... ]
% [ lon1 , lat2, ... ]
dist = zeros(N,N); % the resulting distance matrix
for(idx1 = 1:N)
for(idx2 = 1:N)
dist(idx1,idx2) = vdist(points(1,idx1),points(2,idx1),points(1,idx2)points(2,idx2) );
end
end
Note because the earth surface is manifold (https://en.wikipedia.org/wiki/Manifold) the results will be similar if the points are close to each other. If speed is important to you and the points are closely grouped, you may want to use the first method to calculate your distance matrix. How close together the points should be to make use of this approximation will depend on how accurate you need the results to be.
I need to solve a minimization problem with Matlab and I'm wondering which is the easiest solution. All the potential solutions that I've been thinking in require lot of programming effort.
Suppose that I have a lat/long coordinate point (A,B), what I need is to search for the nearest point to this one in a map of lat/lon coordinates.
In particular, the latitude and longitude arrays are two matrices of 2030x1354 elements (1km distance) and the idea is to find the unique indexes in those matrices that minimize the distance to the coordinates (A,B), i.e., to find the closest values to the given coordinates (A,B).
Any help would be very appreciated.
Thanks!
This is always a fun one :)
First off: Mohsen Nosratinia's answer is OK, as long as
you don't need to know the actual distance
you can guarantee with absolute certainty that you will never go near the polar regions
and will never go near the ±180° meridian
For a given latitude, -180° and +180° longitude are actually the same point, so simply looking at differences between angles is not sufficient. This will be more of a problem in the polar regions, since large longitude differences there will have less of an impact on the actual distance.
Spherical coordinates are very useful and practical for purposes of navigation, mapping, and that sort of thing. For spatial computations however, like the on-surface distances you are trying to compute, spherical coordinates are actually pretty cumbersome to work with.
Although it is possible to do such calculations using the angles directly, I personally don't consider it very practical: you often have to have a strong background in spherical trigonometry, and considerable experience to know its many pitfalls -- very often there are instabilities or "special points" you need to work around (the poles, for example), quadrant ambiguities you need to consider because of trig functions you've introduced, etc.
I've learned to do all this in university, but I also learned that the spherical trig approach often introduces complexity that mathematically speaking is not strictly required, in other words, the spherical trig is not the simplest representation of the underlying problem.
For example, your distance problem is pretty trivial if you convert your latitudes and longitudes to 3D Cartesian X,Y,Z coordinates, and then find the distances through the simple formula
distance (a, b) = R · arccos( a/|a| · b/|b| )
where a and b are two such Cartesian vectors on the sphere. Note that |a| = |b| = R, with R = 6371 the radius of Earth.
In MATLAB code:
% Some example coordinates (degrees are assumed)
lon = 360*rand(2030, 1354);
lat = 180*rand(2030, 1354) - 90;
% Your point of interest
P = [4, 54];
% Radius of Earth
RE = 6371;
% Convert the array of lat/lon coordinates to Cartesian vectors
% NOTE: sph2cart expects radians
% NOTE: use radius 1, so we don't have to normalize the vectors
[X,Y,Z] = sph2cart( lon*pi/180, lat*pi/180, 1);
% Same for your point of interest
[xP,yP,zP] = sph2cart(P(1)*pi/180, P(2)*pi/180, 1);
% The minimum distance, and the linear index where that distance was found
% NOTE: force the dot product into the interval [-1 +1]. This prevents
% slight overshoots due to numerical artifacts
dotProd = xP*X(:) + yP*Y(:) + zP*Z(:);
[minDist, index] = min( RE*acos( min(max(-1,dotProd),1) ) );
% Convert that linear index to 2D subscripts
[ii,jj] = ind2sub(size(lon), index)
If you insist on skipping the conversion to Cartesian and use lat/lon directly, you'll have to use the Haversine formula, as outlined on this website for example, which is also the method used by distance() from the mapping toolbox.
Now, all of this is valid for the whole Earth, provided you find the smooth spherical Earth accurate enough an approximation. If you want to include the Earth's oblateness or some higher order shape model (or God forbid, distances including terrain), you need to do far more complicated stuff. But I don't think that is your goal here :)
PS - I wouldn't be surprised that if you would write everything out that I did, you'll probably re-discover the Haversine formula. I just prefer to be able to calculate something as simple as distances along the sphere from first principles alone, rather than from some black box formula you had implanted in your head sometime long ago :)
Let Lat and Long denote latitude and longitude matrices, then
dist2=sum(bsxfun(#minus, cat(3,A,B), cat(3,Lat,Long)).^2,3);
[I,J]=find(dist2==min(dist2(:)));
I and J contain the indices in A and B that correspond to nearest point. Note that if there are multiple answers, I and J will not be scalar values, but vectors.