You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
how to plot tangent line from specified point to a circle ?
34 views (last 30 days)
Show older comments
Dear Friends,
There is a specified point which is;
[X , Y]
And there is a circle which radius is
r
Before I asked, I searched for the answer and I found something. However, the codes that I found did not work for my program and I don't know why. so how can I plot a tangent line from this point to this circle with 'r' radius. Thanks
2 Comments
dpb
on 3 Dec 2015
Well, there has to be more than just the circle radius...you've got to be able to locate it somehow...the radius only says how big around it is, nothing at all about "where"
Ender Rencuzogullari
on 3 Dec 2015
sorry about missing information. the circle's center is positioned at
[0 , 0]
Accepted Answer
Star Strider
on 3 Dec 2015
See if this does what you want:
a = linspace(0, 2*pi); % Assign Angle Vector
r = 2; % Radius
ctr = [2 3]; % Centre
x = ctr(1) + r.*cos(a); % Circle ‘x’ Vector
y = ctr(2) + r.*sin(a); % Circle ‘y’ Vector
dxda = -r.*sin(a); % Derivative
dyda = r.*cos(a); % Derivative
dydx = dyda./dxda; % Slope Of Tangent
N = 21; % Choose Point On Circle (As Index)
point = [x(N) y(N)]; % Define Point
intcpt = point(2) - dydx(N).*point(1); % Calculate Intercept
xvct = point(1)-1:point(1)+1; % ‘x’ Vecor For Tangent
tngt = dydx(N).*xvct + intcpt; % Calculate Tantent
figure(1)
plot(x, y) % Plot Circle
hold on
plot(point(1), point(2), 'gp') % Plot Point
plot(xvct, tngt) % Plot Tangent At Point
hold off
axis equal
grid
13 Comments
Ender Rencuzogullari
on 3 Dec 2015
Edited: Ender Rencuzogullari
on 3 Dec 2015
Sir, probably I did not explained my question good enough. My bad. There is a point out of the circle. The point is
[X(1), Y(1)].
And then, there is a circle which its radius ' r ' and coordinate of center is at
[0 , 0]
I have tried your code and I got this result in attached image;
There existed a point and a tangent line on circle. However, I need to plot a tangent line from [X(1) , Y(1)] to this [0 , 0] centered circle with radius of r. As an image;
In deed, I want to connect this point with the circle as tangentially. When the line touches the circle, it must stop.
Star Strider
on 4 Dec 2015
Edited: Star Strider
on 4 Dec 2015
Here you go:
% % % % % PLOT TANGENTS TO A CIRCLE FROM A POINT OUTSIDE THE CIRCLE —
% % Reference: https://en.wikipedia.org/wiki/Law_of_cosines
a = linspace(0, 2*pi); % Assign Angle Vector
r = 2; % Circle Radius (‘a’)
ctr = [0.0 0.0]; % Circle Centre
x = ctr(1) + r.*cos(a); % Circle ‘x’ Vector
y = ctr(2) + r.*sin(a); % Circle ‘y’ Vector
XY = [-5.5 3.5]; % Point Outside Circle From Which Tangents Are Plotted
c = hypot(XY(1)-ctr(1),XY(2)-ctr(2));
if c <= r
error('\n\tPOINT ON OR WITHIN CIRCLE RADIUS —> NO TANGENTS POSSIBLE!\n\n')
end
b = sqrt(c.^2 - r.^2); % See Wikipedia Reference
alfa = acos((r.^2 - b.^2 - c.^2)./(-2*b*c)); % See Wikipedia Reference
beta = acos((b.^2 - r.^2 - c.^2)./(-2*r*c)); % See Wikipedia Reference
pt_ctr_angl = atan2(-(XY(2)-ctr(2)),-(XY(1)-ctr(1))); % Angle From ‘Point’ To Circle Centre
alfac = [pt_ctr_angl + alfa; pt_ctr_angl - alfa]; % Angles From ‘Point’ For Tangents
xtng = XY(1) + [b.*cos(alfac(1)); b.*cos(alfac(2))]; % Tangent Point ‘x’ Coordinates
ytng = XY(2) + [b.*sin(alfac(1)); b.*sin(alfac(2))]; % Tangent Point ‘y’ Coordinates
figure(1)
plot(x, y) % Plot Circle
hold on
plot(XY(1), XY(2), 'bp') % Plot ‘Point’
plot([XY(1) xtng(1)], [XY(2) ytng(1)]) % Plot Tangents
plot([XY(1) xtng(2)], [XY(2) ytng(2)]) % Plot Tangents
hold off
grid
axis equal % Prevent Warping
Ender Rencuzogullari
on 4 Dec 2015
Edited: Ender Rencuzogullari
on 4 Dec 2015
Sir, Thanks a lot. It works but there existed two problems in my code. such as;
first problem is: b becamed a complex number so alfa, beta, xtng, ytng are.
second problem is : Actually, c = 75.00005872 and r=75 but program takes c = 75.0000 and r = 75.0000 so it seems the same point. But actually they are not the same. (X(1) and Y(1) values are founding with 4 digits after decimal. I tried to change whole program format for more digits but I could not.)
So program takes only 4 digits after decimal for c. naturally, program does not plot tangent line because of this reason. I tried to use;
But I could not get the result that I desired. I changed even the format as "long" from preferences options. I know I asked too much and really sorry about it. However, I think that is the my main and last problem about not plotting the tangent line and becoming of b is a complex number. Sir, If you want to see the results, This is my whole program;
When run the program, inputs are respectively: 4, 30 , 20, 1, 1.25 , 0.2 , 100 , 100
"c is inside the figure(1)"
%INVOLUTE COORDINATES
module='input the module > Module = ';
m=input(module);
numberofteeth='input the number of teeth > Teeth Number = ';
T=input(numberofteeth);
pressure_angle='input the pressure angle at pitch radius > Pressure Angle(deg) = ';
pre_ang=input(pressure_angle);
addendum_coefficient='input the addendum coefficient > a = ';
a_c=input(addendum_coefficient);
dedendum='input the dedendum coefficient > b_c= ';
b_c=input(dedendum);
h_t_r_c='input the Hob Tip Radius Coefficient > HTRC= ';
HTRC=input(h_t_r_c);
%addendum
a=a_c*m;
%dedendum
b = b_c*m;
% Evaluate the "Pitch Radius"
rp = (m*T)/2;
% Evaluate the "Base Radius"
rb = rp*cos(deg2rad(pre_ang));
%Evaluate the "Root Radius"
rr = rp-b;
% Evaluate the "Tip Radius"
rt = rp + a;
% Evaluate the "Circular Pitch Tooth Thickness"
cptt = (pi*m)/2;
% Evaluate the "Involute Angle at pitch point (theta)"
theta_pitch = tan(deg2rad(pre_ang))- deg2rad(pre_ang);
prompt= 'input the slice number on involute curve= ';
n_slice=input(prompt);
prompt='input the point number of trochoid > point number= ';
PointNumberTrochoid=input(prompt);
R=linspace(rb,rt,n_slice);
% vector length N between [rb rt]
% Evaluate the pressure angle at Ri
theta = acos(rb./R);
%Evaluate the involute angle at Ri
inv_ang = tan(theta)-theta;
% Evaluate the Circular Tooth Thickness at Ri
ctt = 2*R.*(0.5*cptt./rp + theta_pitch-inv_ang);
B_involute = 0.5*ctt./R;
X_inv = R.*sin(B_involute);
Y_inv = R.*cos(B_involute);
% TROCHOID COORDINATES
c_pitch = pi*m; %circular pitch
r_hob_tip = HTRC*m; %hob tip radius
Emax= 25*pi/180;
B= b-r_hob_tip;
L= (c_pitch/4)-(B*tan(deg2rad(pre_ang)))-(r_hob_tip/cos(deg2rad(pre_ang)));
W= ((c_pitch/2)-L)/rp;
E=linspace(0,Emax,PointNumberTrochoid);
Xz = (rp.*E.*cos(E))-((rp-B).*sin(E));
Yz = ((rp-B).*cos(E))+(rp.*E.*sin(E));
dXz= -(rp.*E.*sin(E))+(B.*cos(E));
dYz= (rp.*E.*cos(E))+(B.*sin(E));
A= atan(dXz./dYz);
if E==0
A=pi/2;
end
Xt = Xz+(r_hob_tip*cos(A));
Yt = Yz-(r_hob_tip*sin(A));
X = (Yt.*sin(W))-(Xt.*cos(W));
Y = (Yt.*cos(W))+(Xt.*sin(W));
%When you grow an array incrementally as you are doing with DE, MATLAB is forced to reallocate the entire array at EVERY iteration,
%copying over the entire mess just to add ONE element.
%This will cause the operation to get slower, and the time required will grow quadratically.
%SO it will get SLOW. You know in the end EXACTLY how large DE will be. So just add ONE extra line before the loop.
%This essentially creates the array in advance, filling it with zeros.
%It need no longer reallocated at each iteration, because it will no longer need to change size at every step.
%Much of the time, preallocation is not needed. MATLAB is not a language where you need to initialize/allocate every array.
%Variables that are scalars, and will remain so are never an issue. It is only when an array is dynamically grown that preallocation is important.
%A problem arises when you don't know the final size of your array. Even there, there are tricks that one can do.
%I posted a "submission to the FEX" long ago that allows the user to store information in a form that can be more efficiently grown, then at the end, you can unpack the object into a regular array.
DE = zeros(length(X),length(X_inv)); % Preallocation for speed
for k1 =1: length(X)
for k2 =1: length(X_inv)
DE(k1,k2)= hypot(X(k1)-X_inv(k2), Y(k1)-Y_inv(k2)); % Euclidean Distance
end
end
[DEmin,ix] = min(DE(:));
[K1,K2] = ind2sub(size(DE),ix);
nxs_idx= find( Y <= Y_inv(K2)); % Only Retain Indices Of ‘Y axis value of trochoid’ Points >= Closest Point
% Those first three fprintf commands,below, show the "Nearest Point" on Trochoid curve
% to point on Involute curve. The nearest point on trochoid might be at any
% coordinate. Coordinate of this point should be found because we need to be aware of
% whether its coordinate is outside of the involute curve or not. If the nearest point of Trochoid is outside,
% there will be problem about shape of tooth. Thus, we can make the program executes the limit condition due to its coordinate
% about specifying to coordinates of those points for plotting graph.
% However, If there needs to arise to see the difference between distance of
% actual nearest points and the distance of nearest points under the
% limitation which will be encoded ,at further steps, delete the comment "%" commands and run.
%fprintf(1,'\nNearest Points:\n\tDistance = %.4f mm\n', DEmin)
%fprintf(1,'\t\tX(%d), Y(%d) \t\t\t= %.4f mm, %.4f mm\n',K1, K1, X(K1), Y(K1))
%fprintf(1,'\t\tX_inv(%d), Y_inv(%d) \t= %.4f mm , %.4f mm \n', K2, K2, X_inv(K2), Y_inv(K2))
D_E = zeros(length(X(nxs_idx)),length(X_inv));
for i=1: length(X(nxs_idx))
for j=1: length(X_inv)
D_E(i,j) = hypot(X(i)-X_inv(j), Y(i)-Y_inv(j)); % Eucledian Distance
end
end
[D_Emin,i_x] = min(D_E(:));
[K_1,K_2] = ind2sub(size(D_E),i_x);
Qpt = [X(K_1) Y(K_1)]; % Nearest (X,Y) Point
Q_invpt = [X_inv(K2) Y_inv(K2)]; % Nearest (X_inv,Y_inv) Point
fprintf(1,'\nNearest Points:\n\tDistance = %.5f mm\n', D_Emin)
fprintf(1,'\t\tX(%d), Y(%d) \t\t\t= %.5f mm, %.5f mm\n',K_1, K_1, X(K_1), Y(K_1))
fprintf(1,'\t\tX_inv(%d), Y_inv(%d) \t= %.5f mm , %.5f mm \n', K_2, K_2, X_inv(K_2), Y_inv(K_2))
% D evaluates the difference between actual minimum distance of nearest points
% and minimum distance of nearest points under limit condition.
% D = abs(DEmin-D_Emin);
%Eventually, Coordinates might be plotted to obtain Tooth Profile
figure(1)
plot(X(1:K_1), Y(1:K_1),'-r','LineWidth',2)
hold on
plot(-X(1:K_1), Y(1:K_1),'-r','LineWidth',2)
hold on
plot(X_inv(K2:length(X_inv)) , Y_inv(K2:length(X_inv)),'-r','LineWidth',2)
hold on
plot(-X_inv(K2:length(X_inv)) , Y_inv(K2:length(X_inv)),'-r','LineWidth',2)
hold on
plot(Qpt(1),Qpt(2),'bp', Q_invpt(1),Q_invpt(2),'gp') % Plot Closest Points
hold on
plot(-Qpt(1),Qpt(2),'bp', -Q_invpt(1),Q_invpt(2),'gp')
hold on
plot([Qpt(1); Q_invpt(1)], [Qpt(2); Q_invpt(2)], '-r','LineWidth',2) % Connect Closest Points
hold on
plot([-Qpt(1); -Q_invpt(1)], [Qpt(2); Q_invpt(2)], '-r','LineWidth',2)
hold on
base_circle = linspace(0,2*pi);
xb = rb*cos(base_circle);
yb = rb*sin(base_circle);
plot(xb,yb)
hold on
pitch_circle = linspace(0,2*pi);
xp = rp*cos(pitch_circle);
yp = rp*sin(pitch_circle);
plot(xp,yp,'--')
hold on
%tip_circle = linspace(0,2*pi);
%xt = rt*cos(tip_circle);
%yt = rt*sin(tip_circle);
%plot(xt,yt,'--m')
%hold on
root_circle = linspace(0,2*pi);
xr = rr*cos(root_circle);
yr = rr*sin(root_circle);
plot(xr,yr,'k','LineWidth',2)
XY = [(X(1)) (Y(1))]; % Point Outside Circle From Which Tangents Are Plotted
c = hypot(XY(1),XY(2));
if c <= rr
fprintf(2,'\n\tPOINT ON OR WITHIN CIRCLE RADIUS —> NO TANGENTS POSSIBLE!\n\n')
end
gap = sqrt(c^2 - rr^2); % See Wikipedia Reference
alfa = acos((rr^2 - gap^2 - c^2)/(-2*gap*c)); % See Wikipedia Reference
beta = acos((gap^2 - rr^2 - c^2)/(-2*rr*c)); % See Wikipedia Reference
alfac = [atan2(-XY(2),-XY(1)) + alfa; atan2(-XY(2),-XY(1)) - alfa]; % Angles From ‘Point’ For Tangents
xtng = XY(1) + [gap*cos(alfac(1)); gap*cos(alfac(2))]; % Tangent Point ‘x’ Coordinates
ytng = XY(2) + [gap*sin(alfac(1)); gap*sin(alfac(2))]; % Tangent Point ‘y’ Coordinates
plot(XY(1), XY(2), 'bp') % Plot ‘Point’
plot([XY(1) xtng(1)], [XY(2) ytng(1)]) % Plot Tangents
plot([XY(1) xtng(2)], [XY(2) ytng(2)]) % Plot Tangents
hold off
axis equal
title('Plot Showing Nearest Points')
line([-X_inv(end) X_inv(end)],[Y_inv(end) Y_inv(end)],'Color','r','LineWidth',2)
figure(2)
plot(X(1:K_1), Y(1:K_1),'-r','LineWidth',2)
hold on
plot(-X(1:K_1), Y(1:K_1),'-r','LineWidth',2)
hold on
plot(X_inv(K2:length(X_inv)) , Y_inv(K2:length(X_inv)),'-r','LineWidth',2) % Plot (X_inv,Y_inv) Without Overlap
hold on
plot(-X_inv(K2:length(X_inv)) , Y_inv(K2:length(X_inv)),'-r','LineWidth',2)
hold on
plot([Qpt(1); Q_invpt(1)], [Qpt(2); Q_invpt(2)], '-r','LineWidth',2) % Connect Lines
hold on
plot([-Qpt(1); -Q_invpt(1)], [Qpt(2); Q_invpt(2)], '-r','LineWidth',2)
hold on
pitch_circle = linspace(0,2*pi);
xp = rp*cos(pitch_circle);
yp = rp*sin(pitch_circle);
plot(xp,yp,'--')
hold on
base_circle = linspace(0,2*pi);
xb = rb*cos(base_circle)+0;
yb = rb*sin(base_circle)+0;
plot(xb,yb)
hold on
%tip_circle = linspace(0,2*pi);
%xt = rt*cos(tip_circle);
%yt = rt*sin(tip_circle);
%plot(xt,yt,'--m')
%hold on
root_circle = linspace(0,2*pi);
xr = rr*cos(root_circle);
yr = rr*sin(root_circle);
plot(xr,yr,'k')
hold off
axis equal
line([-X_inv(end) X_inv(end)],[Y_inv(end) Y_inv(end)],'Color','r','LineWidth',2)
xlabel('tooth thickness (mm)')
ylabel('tooth height (mm)')
title('Tooth Profile')
Star Strider
on 4 Dec 2015
The point you are plotting the tangents from cannot be on the circle radius or inside the circle. That is likely where the complex numbers are coming from. MATLAB maintains full internal precision, so the format display options will not affect that. You are not using the Symbolic Math Toolbox or symbolic variables, so vpa and related functions will have no affect on your computations.
Be absolutely certain that the point defined as my XY vector of point coordinates is outside the circle, and that c > r.
When I run my code with r=75 and XY=[0 75.00005872], it runs as it should, and does not produce complex numbers or errors. (It is difficult to see the tangent lines without enlarging the plot considerably, but they are correct.)
My code works. I have no idea what the problem is with respect to using it with your data. (I changed it so that it now works with circles not centred at the origin. I edited my previous Comment to post the new version. My code is otherwise unchanged, and the change will not affect the way it works with your data.)
Ender Rencuzogullari
on 4 Dec 2015
I will find a way to change the precision of c. I appreciate for your interest again.
Star Strider
on 4 Dec 2015
My pleasure.
The problem may be that you are changing my code to include your variables. One change that could make things easier is to create a function from my code:
function [xtng, ytng] = pt_circ_tangent(ctr, r, XY)
% PT_CIRC_TANGENT calculates and plots the tangent lines from
% a point outside the circle to points on the
% circumference. It will throw an error if the point is
% on or inside the circle.
% INPUT ARGUMENTS:
% ctr: Two-element vector with the [x, y] coordinates of
% circle center
% r: Scalar value of circle radius
% XY: Two-element vector of the [x,y] coordinates of the
% point from which the tangent lines will be drawn
% OUTPUTS:
% xtng,ytng: Points on the circle to which the tangent
% lines are plotted
a = linspace(0, 2*pi); % Assign Angle Vector
% r = 2; % Circle Radius (‘a’)
% ctr = [0.0 0.0]; % Circle Centre
x = ctr(1) + r.*cos(a); % Circle ‘x’ Vector
y = ctr(2) + r.*sin(a); % Circle ‘y’ Vector
% XY = [-5.5 3.5]; % Point Outside Circle From Which Tangents Are Plotted
c = hypot(XY(1)-ctr(1),XY(2)-ctr(2));
if c <= r
error('\n\tPOINT ON OR WITHIN CIRCLE RADIUS —> NO TANGENTS POSSIBLE!\n\n')
end
b = sqrt(c.^2 - r.^2); % See Wikipedia Reference
alfa = acos((r.^2 - b.^2 - c.^2)./(-2*b*c)); % See Wikipedia Reference
beta = acos((b.^2 - r.^2 - c.^2)./(-2*r*c)); % See Wikipedia Reference
pt_ctr_angl = atan2(-(XY(2)-ctr(2)),-(XY(1)-ctr(1))); % Angle From ‘Point’ To Circle Centre
alfac = [pt_ctr_angl + alfa; pt_ctr_angl - alfa]; % Angles From ‘Point’ For Tangents
xtng = XY(1) + [b.*cos(alfac(1)); b.*cos(alfac(2))]; % Tangent Point ‘x’ Coordinates
ytng = XY(2) + [b.*sin(alfac(1)); b.*sin(alfac(2))]; % Tangent Point ‘y’ Coordinates
figure(1)
plot(x, y) % Plot Circle
hold on
plot(XY(1), XY(2), 'bp') % Plot ‘Point’
plot([XY(1) xtng(1)], [XY(2) ytng(1)]) % Plot Tangents
plot([XY(1) xtng(2)], [XY(2) ytng(2)]) % Plot Tangents
hold off
grid
axis equal % Prevent Warping
end
Save it in your MATLAB path as: pt_circ_tangent.m
The arguments are internally comment-documented, and I commented-out the lines in the code that would otherwise over-ride the arguments. You can have as many outputs as you like. Here, I just output the tangent points on the circle. It will plot the point, circle, and tangent lines. If you don’t want that plot, just comment them out. I would not delete the plot because you can use it for reference. Consider it part of the documentation.
Ender Rencuzogullari
on 4 Dec 2015
Edited: Ender Rencuzogullari
on 4 Dec 2015
Sir, I have tried this function but I have still the same error. The program is taking c as xx.0000 instead of its actual value xx.0000xxxx. Thus, It is giving c-r= 0 and tangent line does not occur. Besides, my program did not accept this function. I don't know why.
Star Strider
on 4 Dec 2015
The function works perfectly for me, for example with:
ctr = [2.5 1.5];
r = 1.6;
XY = [7.5 -2.5];
[xtng, ytng] = pt_circ_tangent(ctr, r, XY)
If you saved it in your MATLAB search path, you should have no problem using it. It will throw an error if the point is on or inside the circle. That is how I wrote it.
See if defining ‘r’ as:
r = 75 - sqrt(eps);
changes anything. The square root of the machine precision constant eps is (on my machine) 1.49011611938477e-08, so with that change, r=74.9999999850988. That should not introduce significant error into your computations, and should allow your code to work with my function.
Ender Rencuzogullari
on 5 Dec 2015
I tried to allow the program accept the function, but It did not accept. Thanks for your helps sir
Star Strider
on 5 Dec 2015
My pleasure.
I got the impression you got my code to work in your other Question. I have no idea why my function does not work on your computer. I have no problem with it.
Star Strider
on 14 Jun 2019
@Scott McCleary —
The ‘xvct’ vector is simply the independent variable of the line calculated in the ‘tngt’ assignment (dependent variable for the tangent line), and the plotted in:
plot(xvct, tngt) % Plot Tangent At Point
Dev Chhatbar
on 18 Dec 2022
Your above code works wonders. I was just curious as to know how would one adapt it such that it allows the user to pick a point and allow the user to input the x, y and radius components for the Circle? Would appreciate your help.
More Answers (0)
See Also
Categories
Find more on Line Plots in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)