フィルターのクリア

MATLAB's boundary function does not return the boundaries of the polygon

27 ビュー (過去 30 日間)
O.Hubert
O.Hubert 2024 年 1 月 25 日
編集済み: O.Hubert 2024 年 1 月 26 日
Dear all,
From a collection of longitude and latitude data points that form provinces of a country, I would like to keep only the points that determine the borders of the country.
However, the boundary function does not return the correct borders, they are much smoother than what they should be, and I wonder why that is.
To be sure that it was not a question of ordering of the provinces (my understanding is that it does not matter for boundary), creating jumps from one side of the country to the other, I considered only one province. Such a province is highly concave, but, again, this should be manageable for boundary if I understood correctly the purpose of boundary. For information, I do use the largest shrinking parameter for boundary (1), but to no avail.
You will find attached a minimum (non-)working example of the task at hand, as well as an M-file, reproduced hereunder. I also attach a second neighboring province in order to create a two-provinces country.
Any idea why the boundary of the polygon is not the polygon itself when I have only one province? Am I doing something wrong?
Thank you in advance.
% Load the data
load('MWE_boundary.mat');
Lon_initial=Lon;
Lat_initial=Lat;
% Define useful things
remove_nans=1;
% As boundary does not like NaN, identify them
isnann=find(isnan(Lon));
% Remove or interpolate NaNs
if remove_nans==1
Lon=Lon(~isnan(Lon));
Lat=Lat(~isnan(Lat));
else
Lon(isnann)=Lon(isnann-1);
Lat(isnann)=Lat(isnann-1);
end
% Execute boundary
[idx_limit,area_limit]=boundary(Lon',Lat',1);
outside_boundary=[Lon(idx_limit)' Lat(idx_limit)'];
polyoutside=polyshape(outside_boundary);
Warning: Polyshape has duplicate vertices, intersections, or other inconsistencies that may produce inaccurate or unexpected results. Input data has been modified to create a well-defined polyshape.
% Plot the results
figure;plot(polyoutside);hold on;
plot(Lon,Lat);hold on;
scatter(Lon,Lat);
% => the boundaries are not the boundaries.
  2 件のコメント
Mathieu NOE
Mathieu NOE 2024 年 1 月 26 日
just to show you, you're not the first person to have trouble with boundary (as everything it has also some limitations)

サインインしてコメントする。

採用された回答

Mathieu NOE
Mathieu NOE 2024 年 1 月 26 日
with the Fex submission i mentionned above
you can get better results (maybe not perfect) but you must be patient, it's taking more time than the regular boundary function
code
% Load the data
load('MWE_boundary.mat');
Lon_initial=Lon;
Lat_initial=Lat;
% Define useful things
remove_nans=1;
% As boundary does not like NaN, identify them
isnann=find(isnan(Lon));
% Remove or interpolate NaNs
if remove_nans==1
Lon=Lon(~isnan(Lon));
Lat=Lat(~isnan(Lat));
else
Lon(isnann)=Lon(isnann-1);
Lat(isnann)=Lat(isnann-1);
end
% Execute boundary
[idx_limit,area_limit]=boundary(Lon',Lat',1);
% outside_boundary=[Lon(idx_limit)' Lat(idx_limit)'];
% polyoutside=polyshape(outside_boundary);
%% test with find_delaunay_boundary03 and others
% (from Fex : https://fr.mathworks.com/matlabcentral/fileexchange/60690-boundary-extraction-identification-and-tracing-from-point-cloud-data?s_tid=ta_fx_results )
Fd = 0.01; %Fd = dmax (max point to point distance)
[bids, E, Ne] = find_delaunay_boundary03([Lon' Lat'],Fd);
% [bids, E, Ne] = find_delaunay_boundary03_fig1([Lon' Lat'],Fd);
% [bids, E, Ne] = find_delaunay_boundary03_noAngleThreshold([Lon' Lat'],Fd);
% Plot the results
figure(1);
subplot(1,2,1)
plot(Lon,Lat,'bo');hold on;
title('with boundary, s = 1');
plot(Lon(idx_limit),Lat(idx_limit),'*r');
% Plot the results
subplot(1,2,2)
plot(Lon,Lat,'bo');hold on;
title(strrep('with find_delaunay_boundary03, Fd = 0.01','_',' '));
for ck = 1:numel(bids)
plot(Lon(bids{ck}), Lat(bids{ck}), '*r')
end
  1 件のコメント
O.Hubert
O.Hubert 2024 年 1 月 26 日
編集済み: O.Hubert 2024 年 1 月 26 日
Thanks a lot, Mathieu.
I think the answer you provided is sufficiently good for my case.
I also tried another, much less elaborate way. Essentially, I define a grid of points based on the extreme latitudes and longitudes of the country I am interested in. Then I try whether each of those points is inside any of the provinces. For each row and column of the grid, the first point that is at least in one province is therefore the one closest to the border. It's far from perfect and I don't like that solution, but it's an approximation. As I don't really need the ordering of the points but will use it as a "mask" to put over my geo-localized data, it's fine.
Xcoord=nanmin(Lon)-0.1:0.1:nanmax(Lon)+0.1;
Ycoord=nanmin(Lat)-0.1:0.1:nanmax(Lat)+0.1;
[XXmesh, YYmesh]=meshgrid(Xcoord,Ycoord);
XYvec=[XXmesh(:) YYmesh(:)];
Provincestoconsider=1;
nbboundaries=numel(Provincestoconsider);
ISinteriorr=zeros(size(XYvec,1),nbboundaries);
for i=1:nbboundaries
polytemp=polyshape(Lon',Lat');
[in,on] = isinterior(polytemp,XYvec(:,1),XYvec(:,2));
bordertemp=in+on;
ISinteriorr(:,i)=bordertemp;
end

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeMap Display についてさらに検索

製品


リリース

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by