Created
September 1, 2025 07:19
-
-
Save jkrumbiegel/84a5f5b7f1ae8cd432cbb569c12b26e7 to your computer and use it in GitHub Desktop.
Tangent lines two circles Makie projected
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using LinearAlgebra | |
| """ | |
| outertangents(c1::Circle, c2::Circle) -> Vector{Tuple{Point2f, Point2f}} | |
| Compute the outer tangent lines between two circles. | |
| Returns a vector of two tuples, each containing two Point2f objects representing the endpoints of the outer tangent lines. | |
| """ | |
| function outertangents(c1, c2) | |
| # Extract centers and radii | |
| center1 = c1.center | |
| center2 = c2.center | |
| radius1 = c1.r | |
| radius2 = c2.r | |
| # Determine which is the bigger circle | |
| big_center, big_radius, small_center, small_radius = | |
| radius1 > radius2 ? (center1, radius1, center2, radius2) : (center2, radius2, center1, radius1) | |
| radius_difference = big_radius - small_radius | |
| # Vector from small to big circle center | |
| center_diff = big_center - small_center | |
| center_distance = norm(center_diff) | |
| # Angle from small circle center to big circle center | |
| gamma = -atan(center_diff[2], center_diff[1]) | |
| # Angle for tangent calculation | |
| beta = asin(radius_difference / center_distance) | |
| alpha1 = gamma - beta | |
| alpha2 = gamma + beta | |
| # Calculate tangent points on small circle | |
| small_tangent_point_1 = small_center + Point2f( | |
| small_radius * cos(pi / 2 - alpha1), | |
| small_radius * sin(pi / 2 - alpha1) | |
| ) | |
| small_tangent_point_2 = small_center + Point2f( | |
| small_radius * cos(-pi / 2 - alpha2), | |
| small_radius * sin(-pi / 2 - alpha2) | |
| ) | |
| # Calculate tangent points on big circle | |
| big_tangent_point_1 = big_center + Point2f( | |
| big_radius * cos(pi / 2 - alpha1), | |
| big_radius * sin(pi / 2 - alpha1) | |
| ) | |
| big_tangent_point_2 = big_center + Point2f( | |
| big_radius * cos(-pi / 2 - alpha2), | |
| big_radius * sin(-pi / 2 - alpha2) | |
| ) | |
| # Return tuples of tangent line endpoints | |
| return [ | |
| (small_tangent_point_1, big_tangent_point_1), | |
| (small_tangent_point_2, big_tangent_point_2) | |
| ] | |
| end | |
| f = Figure() | |
| c1 = Observable(Circle(Point2f(0, 0), 50)) | |
| ax1 = Axis(f[1, 1], aspect = DataAspect()) | |
| poly!(ax1, c1, color = (:tomato, 0.3)) | |
| c2 = Observable(Circle(Point2f(0, 0), 10)) | |
| ax2 = Axis(f[2:3, 2:3], aspect = DataAspect()) | |
| poly!(ax2, c2, color = (:teal, 0.3)) | |
| c1_proj = lift(c1, ax1.scene.viewport, ax1.scene.camera.projectionview) do c1, _, _ | |
| center = Makie.shift_project(ax1.scene, c1.center) | |
| # assume that the circle is actually a circle | |
| point_on_circle = Makie.shift_project(ax1.scene, c1.center + Point(c1.r, 0)) | |
| r_proj = norm(center - point_on_circle) | |
| Circle(Point(center), r_proj) | |
| end | |
| c2_proj = lift(c2, ax2.scene.viewport, ax2.scene.camera.projectionview) do c2, _, _ | |
| center = Makie.shift_project(ax2.scene, c2.center) | |
| # assume that the circle is actually a circle | |
| point_on_circle = Makie.shift_project(ax2.scene, c2.center + Point(c2.r, 0)) | |
| r_proj = norm(center - point_on_circle) | |
| Circle(Point(center), r_proj) | |
| end | |
| tangents = lift(outertangents, c1_proj, c2_proj) | |
| linesegments!(f.scene, tangents, color = :black, linestyle = :dash) | |
| f |
Author
jkrumbiegel
commented
Sep 1, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment