How to assign point to multiple circles

2 views (last 30 days)
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

Accepted Answer

Adam Danz
Adam Danz on 11 Feb 2020
Edited: Adam Danz on 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 Comments
Adam Danz
Adam Danz on 12 Feb 2020
Edited: Adam Danz on 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 on 14 Feb 2020
Thank you Adam, I really appreciate your help.

Sign in to comment.

More Answers (0)

Categories

Find more on Geographic Plots in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!