How to assign point to multiple circles

6 Ansichten (letzte 30 Tage)
012786534
012786534 am 11 Feb. 2020
Kommentiert: 012786534 am 14 Feb. 2020
Hi,
I have small script to assign points to circles. However, when a point falls into overlapping circles, then I want it to be assigned to the circle with the nearest center. In other words, a point can only be assigned to one circle. That last part is giving me a problem. Otherwise no more than 2 circles can overlap and if a point fall outside all the circles then it is not assigned anything.
Please note that I dont have any packages.
Thoughts ?
% Positions of points
lat = [47.5, 45.5, 46.5, 46.6, 47.8, 45.7, 44]';
lon = [-63.5, -61.5, -62.5, -62.4, -63.6, -61.7, -59.9]';
pts_positions = table(lat, lon);
% Center of circles
lat = [47, 45, 43]';
lon = [-63, -61, -59]';
name = {'A'; 'B'; 'C'};
circles_positions = table(name,lat, lon);
angles = linspace(0, 2*pi, 720);
radius = 2;
% Assign points to circles
for i = 1:height(circles_positions)
j = circles_positions(i, 1);
x = radius * cos(angles) + circles_positions.lon(i);
y = radius * sin(angles) + circles_positions.lat(i);
mask = pts_positions.lat > min(y) & pts_positions.lon < max(y) & ...
pts_positions.lon > min(x) & pts_positions.lon < max(x);
pts_positions.circle_name(mask) = table2cell(j(1,1));
end

Akzeptierte Antwort

Adam Danz
Adam Danz am 11 Feb. 2020
Bearbeitet: Adam Danz am 11 Feb. 2020
The first block of code below identifies which circle center is closest to each pts_positions using pdist2(). It then assigns the circle name from circles_positions to each row in pts_positions.
% Positions of points
lat = [47.5, 45.5, 46.5, 46.6, 47.8, 45.7, 44]';
lon = [-63.5, -61.5, -62.5, -62.4, -63.6, -61.7, -59.9]';
pts_positions = table(lat, lon);
% Center of circles
lat = [47, 45, 43]'; % I recommend you use different variable names here to avoid confusion.
lon = [-63, -61, -59]'; % I recommend you use different variable names here to avoid confusion.
name = {'A'; 'B'; 'C'};
circles_positions = table(name,lat, lon);
% angles = linspace(0, 2*pi, 720); % no longer needed
radius = 2;
% Determine which circle center is closest to each coordinate.
% distToCircCenters(i,j) is the distance between pts(i) and cirlces(j)
distToCircCenters = pdist2(pts_positions{:,:}, circles_positions{:,{'lat','lon'}});
% closestCircIdx is a positive integer identifying which circle in circles_positions is closest
[~, closestCircIdx] = min(distToCircCenters, [], 2);
% Assign circle name
pts_positions.circle_name = circles_positions.name(closestCircIdx);
The block of code below plots the results using rounded rectangles. The circles are color coded and the (lon,lat) points are color coded to show which circle they belong to.
% Plot the circles (this uses rounded rectangles)
nCircles = numel(circles_positions.lat);
plotCircFcn = @(x,y,r)rectangle('Position',[x-r,y-r,r*2,r*2],'Curvature',[1,1]);
clf()
hold on
axis equal
box on
recHand = arrayfun(@(i)plotCircFcn(circles_positions.lon(i),circles_positions.lat(i),radius),1:nCircles);
% Color the circles and mark the centers
circColors = [jet(nCircles), repmat(0.5,nCircles,1)]; % color and transparency (undocumented)
set(recHand, {'FaceColor'}, mat2cell(circColors, ones(size(circColors,1),1), size(circColors,2)) )
plot(circles_positions.lon, circles_positions.lat, 'k*')
% Plot the lat and lon points color coding which circle they belong to
scatter(pts_positions.lon, pts_positions.lat, 90, circColors(closestCircIdx,1:3), 'filled', 'MarkerEdgeColor', 'k')
  3 Kommentare
Adam Danz
Adam Danz am 12 Feb. 2020
Bearbeitet: Adam Danz am 13 Feb. 2020
I added an additional (lon,lat) coordinates that is out of bounds for all circles. The points that are out of bounds will be colored black.
% Positions of points
lat = [47.5, 45.5, 46.5, 46.6, 47.8, 45.7, 44, 47.5]';
lon = [-63.5, -61.5, -62.5, -62.4, -63.6, -61.7, -59.9, -60.5]';
pts_positions = table(lat, lon);
% Center of circles
lat = [47, 45, 43]'; % I recommend you use different variable names here to avoid confusion.
lon = [-63, -61, -59]'; % I recommend you use different variable names here to avoid confusion.
name = {'A'; 'B'; 'C'};
circles_positions = table(name,lat, lon);
angles = linspace(0, 2*pi, 720);
radius = 2;
% Determine which circle center is closest to each coordinate.
% distToCircCenters(i,j) is the distance between pts(i) and cirlces(j)
distToCircCenters = pdist2(pts_positions{:,:}, circles_positions{:,{'lat','lon'}});
% If points are outside of circle, replace distance with NaN
nCircles = numel(circles_positions.lat);
distToCircCenters(distToCircCenters > radius) = NaN;
distToCircCenters(:, nCircles+1) = inf;
% closestCircIdx is a positive integer identifying which circle in circles_positions is closest
[~, closestCircIdx] = min(distToCircCenters, [], 2);
% Assign circle name
circNames = [circles_positions.name; 'None'];
pts_positions.circle_name = circNames(closestCircIdx);
% Plot the circles (this uses rounded rectangles)
plotCircFcn = @(x,y,r)rectangle('Position',[x-r,y-r,r*2,r*2],'Curvature',[1,1]);
clf()
hold on
axis equal
box on
recHand = arrayfun(@(i)plotCircFcn(circles_positions.lon(i),circles_positions.lat(i),radius),1:nCircles);
% Color the circles and mark the centers
circColors = [jet(nCircles), repmat(0.5,nCircles,1)]; % color and transparency (undocumented)
set(recHand, {'FaceColor'}, mat2cell(circColors, ones(size(circColors,1),1), size(circColors,2)) )
plot(circles_positions.lon, circles_positions.lat, 'k*')
% Plot the lat and lon points color codeing which circle they belong to
circColors2 = [circColors; [0 0 0 circColors(1,end)]];
scatter(pts_positions.lon, pts_positions.lat, 90, circColors2(closestCircIdx,1:3), 'filled', 'MarkerEdgeColor', 'k')
012786534
012786534 am 14 Feb. 2020
Thank you Adam, I really appreciate your help.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (0)

Kategorien

Mehr zu Geographic Plots finden Sie in Help Center und File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by