How to assign point to multiple circles

1 回表示 (過去 30 日間)
012786534
012786534 2020 年 2 月 11 日
コメント済み: 012786534 2020 年 2 月 14 日
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

採用された回答

Adam Danz
Adam Danz 2020 年 2 月 11 日
編集済み: Adam Danz 2020 年 2 月 11 日
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 件のコメント
Adam Danz
Adam Danz 2020 年 2 月 12 日
編集済み: Adam Danz 2020 年 2 月 13 日
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 2020 年 2 月 14 日
Thank you Adam, I really appreciate your help.

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

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeLighting, Transparency, and Shading についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by