明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 5350|回复: 6

怎样画两个圆的公切线?

[复制链接]
发表于 2007-4-23 20:42:00 | 显示全部楼层 |阅读模式

现在已知两个圆,怎样通过程序画这两个圆的公切线?

 楼主| 发表于 2007-4-24 22:15:00 | 显示全部楼层
木有人知道吗?
发表于 2007-4-25 03:49:00 | 显示全部楼层

只要知道几何做法就没有问题。

几何做法:

在大圆圆心上画一个圆,半径为大圆半径减小圆的半径。然后从小圆圆心画直线与刚画的圆相切,然后把该直线向外偏一段距离,距离是小圆的半径。

而从程序上来做,则可以通过角度来计算该直线的圆心位置以及角度。

 楼主| 发表于 2007-4-25 09:30:00 | 显示全部楼层
本帖最后由 作者 于 2007-4-25 18:28:15 编辑

楼上的是一种方法,可是从已知一点画一个圆的切线,从几何方法上讲也很麻烦。我在想可不可不以通过设置捕捉来画呢?

比如,在cad中正常的画两个圆的公切线可以用这样的方法:

1 先画两个圆
2 命令 L 回车,命令 TAN回车,在第一个圆画一点,命令TAN,在第二个圆画一点.就是公切线

希望大家帮我想想办法,如何把上面的命令转成程序来实现?

我现在初步认为用sendcommand方法,不过不知道该如何通过程序指定两个圆的点呢?

发表于 2007-4-25 10:31:00 | 显示全部楼层

' 返回值为是否存在切线,lines为切线集合
Public Function LinesTangentToTwoCircles(circle0 As Circle2D, circle1 As Circle2D, lines As Collection) As Boolean
  Dim w As Vector2D
  w.x = circle1.center.x - circle0.center.x
  w.y = circle1.center.y - cricle0.center.y
  Dim wLenSqr As Double
  wLenSqr = w.x * w.x + w.y * w.y
  Dim rSum As Double
  rSum = circle0.radius + circle1.radius
  If wLenSqr <= rSum * rSum Then
    LinesTangentToTwoCircles = False
    Exit Function
  End If
 
  Const epsilon = 0.00001
  Dim rDiff As Double
  rDiff = circle1.radius - circle0.radius
  If Abs(rDiff) >= epsilon Then
    Dim R0sqr As Double, R1sqr As Double, c0 As Double, c1 As Double, c2 As Double, dircr As Double
    R0sqr = circle0.radius * circle0.radius
    R1sqr = circle1.radius * circle1.radius
    c0 = -R0sqr
    c1 = 2# * R0sqr
    c2 = circle1.radius * circle1.radius - R0sqr
    Dim invc2 As Double
    invc2 = 1# / c2
    discr = Sqr(Abs(c1 * c1 - 4# * c0 * c2))
    Dim s As Double, oms As Double, a As Double
    s = -0.5 * (c1 + discr) * invc2
   
    Dim Line1 As New Line2D
    Line1.p.x = circle0.center.x + s * w.x
    Line1.p.y = circle0.center.y + s * w.y
   
    Dim Line2 As New Line2D
    Line2.p.x = Line1.p.x
    Line2.p.y = Line1.p.y
    If s >= 0.5 Then
      a = Sqr(Abs(wLenSqr - R0sqr / (s * s)))
    Else
      oms = 1# - s
      a = Sqr(Abs(wLenSqr = R1sqr / (oms * oms)))
    End If
    GetDirections w, a, Line1.direction, Line2.direction
   
    Dim Line3 As New Line2D
    s = -0.5 * (c1 - discr) * invc2
    Line3.p.x = circle0.center.x + s * w.x
    Line3.p.y = circle0.center.y + s * w.y
   
    Dim Line4 As New Line2D
    Line4.p.x = Line3.p.x
    Line4.p.y = Line3.p.y
   
    If s >= 0.5 Then
      a = Sqr(Abs(wLenSqr - R0sqr / (s * s)))
    Else
      oms = 1# - s
      a = Sqr(Abs(wLenSqr - R1sqr / (oms * oms)))
    End If
    GetDirections w, a, Line3.direction, Line4.direction
  Else
    Dim mid As Point2D
    mid.x = 0.5 * (circle0.center.x + circle1.center.x)
    mid.y = 0.5 * (circle0.center.y + circle1.center.y)
   
    a = Sqr(Abs(wLenSqr - 4# * circle0.radius * circle0.radius))
    GetDirections w, a, Line1.direction, Line2.direction
    Line1.p.x = mid.x
    Line1.p.y = mid.y
    Line2.p.x = mid.x
    Line2.p.y = mid.y
   
    Dim invwlen As Double
    invwlen = 1# / Sqr(wLenSqr)
    w.x = w.x * invwlen
    w.y = w.y * invwlen
   
    Line3.p.x = mid.x + circle0.radius * w.y
    Line3.p.y = mid.y - circle0.radius * w.x
    Line3.direction.x = w.x
    Line3.direction.y = w.y
    Line4.p.x = mid.x - circle0.radius * w.y
    Line4.p.y = mid.y - circle0.radius * w.x
    Liner.direction.x = w.x
    Line4.direction.y = w.y
  End If
  lines.Add Line1
  lines.Add Line2
  lines.Add Line3
  lines.Add Line4
  LinesTangentToTwoCircles = True
End Function

Private Sub GetDirections(w As Vector2D, a As Double, dir0 As Vector2D, dir1 As Vector2D)
  Dim aSqr As Double
  aSqr = a * a
  Dim wxSqr As Double
  wxSqr = w.x * w.x
  Dim wySqr As Double
  wySqr = w.y * w.y
  Dim c2 As Double, invc2 As Double
  c2 = wxSqr + wySqr
  invc2 = 1# / c2
  Dim c0 As Double, c1 As Double, discr As Double, invwx As Double, invwy As Double
  If Abs(w.x) >= Abs(w.y) Then
    c0 = aSqr - wxSqr
    c1 = -2# * a * w.y
    discr = Sqr(Abs(c1 * c1 - 4# * c0 * c2))
    invwx = 1# / w.x
    dir0.y = -0.5 * (c1 + discr) * invc2
    dir0.x = (a - w.y * dir0.y) * invwx
    dir1.y = -0.5 * (c1 - discr) * invc2
    dir1.x = (a - w.y * dir1.y) * invwx
  Else
    c0 = aSqr - wySqr
    c1 = -2# * a * w.x
    discr = Sqr(Abs(c1 * c1 - 4# * c0 * c2))
    invwy = 1# / w.y
    dir0.x = -0.5 * (c1 + discr) * invc2
    dir0.y = (a - w.x * dir0.x) * invwy
    dir1.x = -0.5 * (c1 - discr) * invc2
    dir1.y = (a - w.x * dir1.x) * invwy
  End If
End Sub


 楼主| 发表于 2007-4-25 18:30:00 | 显示全部楼层

谢谢5楼的程序。

不过还是想大家帮我想想我在4楼说的那个方法,个人认为如果成功将会是最简单的一种方法。

 楼主| 发表于 2007-4-25 18:59:00 | 显示全部楼层

哈哈,搞定了

acad.ActiveDocument.SendCommand “line tan 100,180,0 tan 340,100,0 ”

只要在不同的圆上各取一个点作为输入参数就可以了。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-2-22 18:35 , Processed in 0.196524 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表