# I would like my code to allow the user to plot as many circles as they want until the user right clicks, if the circle plotted intersects any other circle it must change color

6 views (last 30 days)
Dougle on 29 Apr 2022
Answered: Steven Lord on 29 Apr 2022
If the circle plotted intersects any of the the other circles on the figure, then the circle must change color otherwise keep the same color. I have a code that works for two circles correctly but I don't know how to get more circles and stop when user right clicks. Also must use ginput just like my code.
My code:
clc;
clear;
clf;
hold on;
axis manual;
title('Circles');
xlim([0 10]);
ylim([-4 4]);
theta= linspace(0,2*pi,1000);
color = 'r';
% circle 1
fprintf('Left click on the figure to choose a center point. \n');
[x1c,y1c] = ginput(1);
plot(x1c,y1c,'+','Color','r','LineWidth',1);
fprintf('Left click on the figure to choose a point on the circle''s perimeter. \n');
[r1a,r1b] = ginput(1);
plot(r1a,r1b);
r1 = sqrt((x1c-r1a).^2+(y1c-r1b).^2);
area1 = pi*(r1).^2;
txt1 = ['area: ', num2str(area1)];
text(x1c-0.55,y1c+0.3,txt1,'Color','r');
x1= r1.*cos(theta)+ x1c;
y1= r1.*sin(theta)+ y1c;
plot(x1,y1,'Color','r','LineWidth',2);
% circle 2
fprintf('Left click on the figure to choose a center point. \n');
[x2c,y2c] = ginput(1);
plot(x2c,y2c,'+','Color',color,'LineWidth',1);
fprintf('Left click on the figure to choose a point on the circle''s perimeter. \n');
[r2a,r2b] = ginput(1);
plot(r2a,r2b);
r2 = sqrt((x2c-r2a).^2+(y2c-r2b).^2);
% intersection
centers = sqrt((y2c-y1c).^2+(x2c-x1c).^2);
color = rand(1,3);
else
color = 'r';
end
plot(x2c,y2c,'+','Color',color,'LineWidth',1);
area2 = pi*(r2).^2;
txt2 = ['area: ', num2str(area2)];
text(x2c-0.55,y2c+0.3,txt2,'Color',color);
x2 = r2.*cos(theta)+ x2c;
y2 = r2.*sin(theta)+ y2c;
plot(x2,y2,'Color',color,'LineWidth',2);
Intersecting: Not intersecting: I want to have my code do as many circles as I want, not just two. For loop? While loop?

Riccardo Scorretti on 29 Apr 2022
Hi. Here is a possible implementation of what you want. Basically, the set of circles are stored in arrays setOf_xc, setOf_yc and setOf_r, so that the intersection test is executed with respect of all existing circles. By the way, your intersection test was wrong, in that it didn't take unto account the case of concentric circles. Finally, the function ginput returns as third argument the mouse button pressed (1 = left, 2 = center, 3 = right).
Is that what you want?
clc;
clear;
clf;
hold on;
axis manual;
title('Circles');
xlim([0 10]);
ylim([-4 4]);
theta= linspace(0,2*pi,1000);
setOf_xc = [];
setOf_yc = [];
setOf_r = [];
while true
color = 'r';
% n-th circle
fprintf('Left click on the figure to choose a center point. \n');
[xc,yc,btn] = ginput(1);
if btn > 1 , break ; end
plot(xc,yc,'+','Color',color,'LineWidth',1);
fprintf('Left click on the figure to choose a point on the circle''s perimeter. \n');
[ra,rb,btn] = ginput(1);
plot(ra,rb);
r = sqrt((xc-ra).^2+(yc-rb).^2);
% intersection
for n = 1 : numel(setOf_r)
centers = sqrt((yc-setOf_yc(n)).^2 + (xc-setOf_xc(n)).^2);
if centers > r+setOf_r(n) || centers < abs(r-setOf_r(n))
% Nothing to do
else
color = rand(1,3);
break;
end
end
plot(xc,yc,'+','Color',color,'LineWidth',1);
area2 = pi*(r).^2;
txt2 = ['area: ', num2str(area2)];
text(xc-0.55,yc+0.3,txt2,'Color',color);
x = r.*cos(theta)+ xc;
y = r.*sin(theta)+ yc;
plot(x,y,'Color',color,'LineWidth',2);
setOf_xc(end+1) = xc;
setOf_yc(end+1) = yc;
setOf_r(end+1) = r;
end Walter Roberson on 29 Apr 2022
Two circles intersect if the distance between their centers is less than or equal to the sum of their radii, except when one of the circles is completely embedded in another one.
You did not make a rule about the case where one circle is completely inside another. If you were to make the rule that in that case too that the newer circle needed to change color, then you can just use the rule I mentioned first.
You did not make a clear rule about what color the additional circles have to be.
Suppose that you have circle A (red) intersect circle B. B has to change color so B is green. Now you add circle C that does not intersect with A but does intersect with B. Is it okay for C to stay red ?
Is the rule intended to just be that when you draw a new circle, that it must not be the same color as any circle that it intersects ?

Alberto Cuadra Lara on 29 Apr 2022
Edited: Alberto Cuadra Lara on 29 Apr 2022
Hello Brock,
As other members of the community have pointed out, there were few conditions missing. I have reorganize your script in sub-pass functions.
• Include everything in a while loop that stops when the user right-clicks.
• If the new circle intersects any of the circles all the intersected circles change to the same random color.
• Include the condition where the circles are inside each other.
Best,
Alberto
function interactive_intersection_circles()
% Plot circles until the user right-clicks. If the circles intersect,
% they will change to the same random color.
% Definitions
L = 100; % Length theta vector
theta = linspace(0, 2*pi, L); % [rad]
% Initialization
n = 0; % Counter of circles
x = zeros(1, 200);
y = zeros(1, 200);
r = zeros(1, 200);
obj_circles = matlab.graphics.chart.primitive.Line.empty(0, 100);
% Create figure
set_figure();
% While loop (stop when user press right click)
while true
% Increase counter
n = n + 1;
% Define random color in case intersection
random_color = rand(1,3);
% Do until user press right click
cursor_selection = get(gcf, 'SelectionType');
if strcmpi(cursor_selection, 'alt')
break;
end
% Get circle
[x(n), y(n), r(n), obj_circles(n)] = get_cicle(theta);
% Check intersections
for i = 1:n-1
FLAG_INTERSECTION = compute_intersection(x(n), y(n), r(n), x(i), y(i), r(i));
if FLAG_INTERSECTION
obj_circles(i).Color = random_color;
obj_circles(n).Color = random_color;
end
end
end
end
% SUB-PASS FUNCTIONS
function A = area_circle(r)
% Compute area circle
A = pi * r.^2;
end
function [x, y] = cartisian_coordinate(x0, y0, r, theta)
% Compute position circle in cartisian coordinate system
x = r .* cos(theta) + x0;
y = r .* sin(theta) + y0;
end
function [x, y] = get_center_point()
% Get n points from current figure
fprintf('Left click on the figure to choose a center point. \n');
[x, y] = ginput(1);
plot(x, y, '+', 'Color', 'r', 'LineWidth', 1);
end
function [x, y] = get_perimeter_point()
% Get n points from current figure
fprintf('Left click on the figure to choose a point on the circle''s perimeter. \n');
[x, y] = ginput(1);
plot(x, y);
end
function obj_circle = plot_circle(x, y)
% Plot circle
obj_circle = plot(x, y, 'Color', 'r', 'LineWidth', 2);
end
function distance = compute_distance(x1, y1, x2, y2)
% Compute Euclidean distance
distance = sqrt((y2 - y1).^2 + (x2 - x1).^2);
end
function [x1, y1, r, obj_circle] = get_cicle(theta)
% Get and plot circle
% Get center point
[x1, y1] = get_center_point();
% Get perimeter point
[x2, y2] = get_perimeter_point();
r = compute_distance(x1, y1, x2, y2);
% Compute area
A = area_circle(r);
% Print Area
% ....
% Get position circle in cartisian coordinate system
[x, y] = cartisian_coordinate(x1, y1, r, theta);
% Plot circle
obj_circle = plot_circle(x, y);
end
function FLAG_INTERSECTION = compute_intersection(x1, y1, r1, x2, y2, r2)
% Compute intersection
% Compute Euclidean distance
distance = compute_distance(x1, y1, x2, y2);
% Compute sum of the radius of the two circles
% Check intersection
if distance <= total_radius && distance + min(r1, r2) >= max(r1, r2)
FLAG_INTERSECTION = true;
else
FLAG_INTERSECTION = false;
end
end
function [ax, config, fig] = set_figure(varargin)
% Initialize figure with a standard composition
%
% Optional args:
% * ax (axis): Figure axis
% * config (struct): Struct with default plot parameters
%
% Returns:
% ax (axis): Axis of the standard figure
% config (struct): Struct with default plot parameters
% fig (figure): Standard figure
% Default values
config.linewidth = 1.8; % Default linewidth for plots
config.fontsize = 22; % Default fontsize
config.labelx = 'x'; % Default xlabel
config.labely = 'y'; % Default ylabel
% Unpack input
if nargin > 0
ax = varargin{1};
if nargin > 1
config = varargin{2};
end
if ~isempty(ax.XLabel)
config.labelx = ax.XLabel;
end
if ~isempty(ax.YLabel)
config.labely = ax.YLabel;
end
else
fig = figure;
set(fig,'units','normalized','innerposition',[0.1 0.1 0.5 0.6])
ax = axes(fig);
end
set(ax,'LineWidth', config.linewidth, 'FontSize', config.fontsize-2, 'BoxStyle', 'full')
hold(ax, 'on'); axis(ax, 'manual');
xlabel(ax, config.labelx, 'FontSize', config.fontsize, 'interpreter', 'latex');
ylabel(ax, config.labely, 'FontSize', config.fontsize, 'interpreter', 'latex');
xlim([0 10]);
ylim([0 10]);
end Steven Lord on 29 Apr 2022
% Define a function to make a "circle" with random center and radius
% A 1000-sided polyshape is a pretty good approximation
% Create the first circle. I used rand, but you would use the data from
existingCircles = makecircle(rand(1, 2), rand);
% Fill in the rest of the array with empty polyshapes
existingCircles(1, 10) = polyshape;
% Plot it
h = plot(existingCircles);
axis equal
hold on
% Make 9 more circles
for k = 2:10
newcircle = makecircle(rand(1, 2), rand);
% Compute by how much the new circle overlaps the existing circles
intersectionAreas = area(intersect(existingCircles, newcircle));
if any(intersectionAreas) > 0
disp('Intersection detected')
% Update the properties of the appropriate elements of h based on
% which circles intersect the new circle
end
% Add the new circle to the list of existing circles
existingCircles(k) = newcircle;
% and add it to the plot
h(k) = plot(newcircle);
end
Intersection detected Intersection detected Intersection detected Intersection detected Intersection detected Intersection detected Intersection detected Intersection detected Intersection detected 