I am writing to ask how to draw an arc intersecting two concentric circles given the angles of intersection.
How does one draw a circle intersecting two concentric circles given it’s angles of intersection?
Circle A and Circle B are concentric. For convenience say the centers are at the origin where x = y = 0; Circle A has radius 10 units and Circle B has radius 11 units.
Circle C intersects Circle A on the x-axis with an angle of, say 30 degrees to the line tangent to circle A at the point of intersection and intersects Circle B with an angle of 25 degrees to the line tangent to circle B at the point of intersection. The center of Circle C lies inside Circle B.The equation of the circles A and B are easy; high school geometry. It’s the equation of the intersecting circle I’m having trouble with.
Thanks
More like this, vittorio:
Circle C (unknown center and radius) intersects Circle B (radius 11.00, Where Circle C intersects is unknown) with an angle of 25 degrees to the line tangent to Circle B at the point of its intersection.
No idea how to do the equations, but you can get pretty close with a little iterative experimentation. Usefulness of this depends on what your needs are and whether you have a lot of these to solve or just a few.
Intersecting Circles.3dm (105.7 KB)
Hi David, all
I too am not able to find the circle equation, so I tried to follow Mark’s suggestion about experimenting.
Here is a Grasshopper definition that should let you look for a solution accurate enough, maybe reducing the slider domain.
The radius of the circle and the resulting angle are show under the slider
walden.gh (13.4 KB)
HTH, cheers
Hi Mark,
That is extremely close. Thanks. I’ll be using the numbers to generate G-Code for a CNC mill and due to the fact that I’ve got so many cases to investigate, it needs to work for angles other than just 30 and for radii other than just 10 and 11.
Can you describe the method you used to iterate? Did you use “cut and try” or did you use a different approach? I might be able to come up with a Python script to automate the process to a given amount of precision.
Hi emillio,
Thanks I’ll give it a try and get back to you.
Hi emillio,
Well, this is embarrassing! It’s been so long since I’ve used Grasshopper that I’ve forgotten how. I succeeded in loading GH by typing Grasshopper in the command line of Rhino, but that’s as far as I got. How can I try out your file?
Hi David
In GH, go to the upper menu and pick File -> Open Document …
and you should be able to load the definition.
Then you can set the radius of the arc by the slider. The resulting angle should be shown below.
I’m afraid the definition probably is not what you need if you have to find the arc for several different circles and angles.
It assumes the values of 10 and 11 for the radii and 30 and 25 degrees for the angles.
You can edit those values in the definition or insert sliders for them, but I think you would also have to edit the slider’s domain any time and the thing might become too time-consuming.
You mentioned a Python script, I think that would be much faster …
Anyway, I hope this helps
Cheers
p.s
Just in case you had a different release … the definition runs on GH release 0.9.0076
Hi emillio,
Thank you. Very impressive. I don’t mind tweaking the values at all. I’m very grateful for the help.
David,
Yeah, cut and try. Scale the unknown circle, check the result, undo and adjust the scale value and try again.
Emillio is way ahead of me. His GH is a much more elegant solution. I’m going to study that one.
Mark, all
Thanks. I appreciate the time and effort you have invested looking at this.
Recall that the point-slope form for the equation of a line is y = mx + b where m is the slope and b is the y-intercept,
and that the standard form of the equation of a circle with center (h, k) and radius r is (x - h)^2 + (y - k)^2 = r^2
so for Circle A: (x_of_A - 0.0)^2 + (y_of_A - 0.0)^2 = 10^2 = (x_of_A)^2 + (y_of_A)^2
and for Circle B: (x_of_B - 0.0)^2 + (y_of_B - 0.0)^2 = 11^2 = (x_of_B)^2 + (y_of_B)^2
and for the unknown circle C: (x_of_C - h_of_C)^2 = (r_of_C)^2 = ?
The unknown center of Circle C lies somewhere on the line perpendicular to the line tangent to Circle C at the point of intersection with Circle A. Circle C intersects Circle A with an angle of 30 degrees and with Circle B with an angle of 25 degrees, in this case.
I believe that if I can find the points which Circle A,B and C have in common I’ll be able to find the center of Circle C.
I have written a “brute force” script in Python which predicts the performance of centrifugal fans. It iterates the 7 parameters of a fan through a user-defined range of each of those 7 parameters. The last one ran for 40 minutes or so on my Gateway laptop and in that time calculated the performance of 8,845,200 cases. Each iteration of the nest of loops usually finds better performers in terms of power absorbed and output, which I call “Best Fans” and those are written to a comma-separated (CSV) text file. I then import the CSV file into MS Excel and sort them any way I like. The last one chose 8,805,885 cases but using Excel it’s easy to identify the few that I’m interested in. Circle C defines the shape of a simple fan blade. What’s left to do is draw the “Best Fan” in Rhino, build a model and test it. Thus my desire to know the answer to this question.
David
Hi David, Mark
Thanks for the appreciation (and thanks for the explanation, David), but I’m sure that in GH we could directly solve the problem, maybe using Galapagos or using a Python script or Kangaroo or something else.
And obviously a Rhino Python script could be used as well to look for the solution.
Unfortunately now I haven’t the time I would need to investigate further this interesting problem ( and I’d need a lot of time for that … )
David, what about another “brute force” script ?
Here we only have one parameter to explore …
Thanks, cheers
Thanks emillio.
Tell me what you need and I’ll see if I can produce it.
You guys rock!
David
David, you mean to build a script ?
Well … actually I had already written a script … to be honest just for fun.
But was reluctant to post it since it only was the usual quick and dirty attempt.
( Pretty incomprehensible and confused … sorry )
But maybe it could help … and you are sure more than able to extract what could be useful from it, if anything.
I only tested the script with the set of data you posted, don’t know what it does with different data …
The script also needs that you pick a point not far from the guessed circle center.
It works moving the center of the unknown circle along the line you talked about, and seeing what happens
In an case, here it is
import Rhino
import rhinoscriptsyntax as rs
import math
def circlesinter( c0, c1, nearpt ):
'''
from 2 circles:
intersection point near to 'nearpt'
'''
tolr = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance
cu0 = Rhino.Geometry.ArcCurve( c0 )
cu1 = Rhino.Geometry.ArcCurve( c1 )
cinters = Rhino.Geometry.Intersect.Intersection.CurveCurve(
cu0, cu1, tolr, tolr )
dist = 1.0e30
for intevent in list( cinters ):
pt = ( intevent.PointA + intevent.PointB ) / 2.0
pdist = pt.DistanceTo( nearpt )
if pdist < dist:
interpt = pt
dist = pdist
return interpt
def pslope( cir, pt ):
'''
slope of circle at given point from X axis
-> degrees ( from 0 to 180 )
'''
ok, u = cir.ClosestParameter( pt )
tang = cir.TangentAt( u )
tang.Unitize()
degs = math.degrees ( Rhino.Geometry.Vector3d.VectorAngle(
tang, Rhino.Geometry.Vector3d.XAxis ) )
if degs < 0:
degs += 360
if degs > 180:
degs -= 180
return degs
def intercircle( inrad, rad, inangle ):
'''
-> intersecting circle
from inner circle radius
from circle radius
'''
interpt = Rhino.Geometry.Point3d( inrad, 0.0, 0.0 )
direc = Rhino.Geometry.Vector3d(
- math.cos( math.radians( inangle ) ),
math.sin( math.radians( inangle ) ),
0.0 )
center = interpt + direc * rad
return Rhino.Geometry.Circle( center, rad )
def outdegrees( inrad, outcir, inangle, radius, nearpt ):
'''
-> angle at outer intersection, circle
'''
circle = intercircle( inrad, radius, inangle )
interpt = circlesinter( circle, outcir, nearpt )
outslope = pslope( outcir, interpt )
cirslope = pslope( circle, interpt )
angle = abs( outslope - cirslope )
return angle, circle
def main():
inrad = rs.GetReal( 'Radius of inner circle ?' )
outrad = rs.GetReal( 'Radius of outer circle ?' )
inangle = rs.GetReal( 'Angle at intersection with inner circle ?' )
outangle = rs.GetReal( 'Angle at intersection with outer circle ?' )
tolr = rs.GetReal( 'Tolerance ?' )
incir = Rhino.Geometry.Circle( Rhino.Geometry.Point3d.Origin, inrad )
outcir = Rhino.Geometry.Circle( Rhino.Geometry.Point3d.Origin, outrad )
Rhino.RhinoDoc.ActiveDoc.Objects.AddCircle( incir )
Rhino.RhinoDoc.ActiveDoc.Objects.AddCircle( outcir )
p0 = Rhino.Geometry.Point3d( inrad, 0.0, 0.0 )
direc = Rhino.Geometry.Vector3d(
- math.cos( math.radians( inangle ) ),
math.sin( math.radians( inangle ) ),
0.0 )
p1 = p0 + direc * outrad * 2
Rhino.RhinoDoc.ActiveDoc.Objects.AddLine( p0, p1 )
guesspt = rs.GetPoint( 'Arc center guess ?' )
nearpt = Rhino.Geometry.Point3d( outrad, 0.0, 0.0 )
delta = ( outrad - inrad ) / 2.0
inpt = Rhino.Geometry.Point3d( inrad, 0.0, 0.0 )
starad = inpt.DistanceTo( guesspt )
rad = starad
degs, circ = outdegrees( inrad, outcir, inangle, rad, nearpt )
dedeg = abs( degs - outangle )
deangle = dedeg
angle = degs
radius = rad
circle = circ
while True:
# print 'DELTA %g' % delta
divide = True
rad = starad - delta * 2
degs, circ = outdegrees( inrad, outcir, inangle, rad, nearpt )
dedeg = abs( degs - outangle )
if dedeg < deangle:
deangle = dedeg
angle = degs
radius = rad
circle = circ
divide = False
rad = starad - delta
degs, circ = outdegrees( inrad, outcir, inangle, rad, nearpt )
dedeg = abs( degs - outangle )
if dedeg < deangle:
deangle = dedeg
angle = degs
radius = rad
circle = circ
divide = True
rad = starad + delta
degs, circ = outdegrees( inrad, outcir, inangle, rad, nearpt )
dedeg = abs( degs - outangle )
if dedeg < deangle:
deangle = dedeg
angle = degs
radius = rad
circle = circ
divide = True
rad = starad + delta * 2
degs, circ = outdegrees( inrad, outcir, inangle, rad, nearpt )
dedeg = abs( degs - outangle )
if dedeg < deangle:
deangle = dedeg
angle = degs
radius = rad
circle = circ
divide = False
starad = radius
if delta < tolr:
break
if divide:
delta /= 2.0
print 'Radius %.6f => %.6f degrees at intersection' % ( starad, angle )
Rhino.RhinoDoc.ActiveDoc.Objects.AddCircle( circle )
Rhino.RhinoDoc.ActiveDoc.Views.Redraw()
main()
After this one, I also had tried to write a more linear thing … but failed completely …
Then … that’s all.
I hope it might help somehow.
Cheers
BAM! That nailed it! Good Job emellio!!!
Thank you Mark!!! You guys are awesome!
Now I’ll see if I can get it to work on other cases. I’ll try it first in the python IDE and then try to use it in Rhino!
emillio, I copied your script, saved it as emillio.py, loaded it via the in-build editor in Rhino 5, ran it and it reported:
Rhinoceros\RhinoPython\emillio.py", line 151
break
^
SyntaxError: ‘break’ outside loop
Do you think it might be an indentation issue?
Mark, I guess I’m confused. Did you run emillio’s script in Fusion or did you use Fusion without his script?
Yuo’re right, David
Looks like Discourse had some problem …
walden.py (4.4 KB)
Here is the script
Cheers
p.s.
BTW I don’t think that Fusion be able to run Rhino scripts
I think Mark Hu. did that on his own