1 view (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

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')

Adam Danz
on 12 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')

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

Start Hunting!
## 0 Comments

Sign in to comment.