怎样画两个圆的公切线?
<p>现在已知两个圆,怎样通过程序画这两个圆的公切线?</p> 木有人知道吗? <p>只要知道几何做法就没有问题。</p><p>几何做法:</p><p>在大圆圆心上画一个圆,半径为大圆半径减小圆的半径。然后从小圆圆心画直线与刚画的圆相切,然后把该直线向外偏一段距离,距离是小圆的半径。</p><p>而从程序上来做,则可以通过角度来计算该直线的圆心位置以及角度。</p> 本帖最后由 作者 于 2007-4-25 18:28:15 编辑 <br /><br /> <p>楼上的是一种方法,可是从已知一点画一个圆的切线,从几何方法上讲也很麻烦。我在想可不可不以通过设置捕捉来画呢?</p><p>比如,在cad中正常的画两个圆的公切线可以用这样的方法:</p><p>1 先画两个圆 <br/>2 命令 L 回车,命令 TAN回车,在第一个圆画一点,命令TAN,在第二个圆画一点.就是公切线 <br/></p><p></p><p>希望大家帮我想想办法,如何把上面的命令转成程序来实现?</p><p>我现在初步认为用sendcommand方法,不过不知道该如何通过程序指定两个圆的点呢?</p> <p>' 返回值为是否存在切线,lines为切线集合<br/>Public Function LinesTangentToTwoCircles(circle0 As Circle2D, circle1 As Circle2D, lines As Collection) As Boolean<br/> Dim w As Vector2D<br/> w.x = circle1.center.x - circle0.center.x<br/> w.y = circle1.center.y - cricle0.center.y<br/> Dim wLenSqr As Double<br/> wLenSqr = w.x * w.x + w.y * w.y<br/> Dim rSum As Double<br/> rSum = circle0.radius + circle1.radius<br/> If wLenSqr <= rSum * rSum Then<br/> LinesTangentToTwoCircles = False<br/> Exit Function<br/> End If<br/> <br/> Const epsilon = 0.00001<br/> Dim rDiff As Double<br/> rDiff = circle1.radius - circle0.radius<br/> If Abs(rDiff) >= epsilon Then<br/> Dim R0sqr As Double, R1sqr As Double, c0 As Double, c1 As Double, c2 As Double, dircr As Double<br/> R0sqr = circle0.radius * circle0.radius<br/> R1sqr = circle1.radius * circle1.radius<br/> c0 = -R0sqr<br/> c1 = 2# * R0sqr<br/> c2 = circle1.radius * circle1.radius - R0sqr<br/> Dim invc2 As Double<br/> invc2 = 1# / c2<br/> discr = Sqr(Abs(c1 * c1 - 4# * c0 * c2))<br/> Dim s As Double, oms As Double, a As Double<br/> s = -0.5 * (c1 + discr) * invc2<br/> <br/> Dim Line1 As New Line2D<br/> Line1.p.x = circle0.center.x + s * w.x<br/> Line1.p.y = circle0.center.y + s * w.y<br/> <br/> Dim Line2 As New Line2D<br/> Line2.p.x = Line1.p.x<br/> Line2.p.y = Line1.p.y<br/> If s >= 0.5 Then<br/> a = Sqr(Abs(wLenSqr - R0sqr / (s * s)))<br/> Else<br/> oms = 1# - s<br/> a = Sqr(Abs(wLenSqr = R1sqr / (oms * oms)))<br/> End If<br/> GetDirections w, a, Line1.direction, Line2.direction<br/> <br/> Dim Line3 As New Line2D<br/> s = -0.5 * (c1 - discr) * invc2<br/> Line3.p.x = circle0.center.x + s * w.x<br/> Line3.p.y = circle0.center.y + s * w.y<br/> <br/> Dim Line4 As New Line2D<br/> Line4.p.x = Line3.p.x<br/> Line4.p.y = Line3.p.y<br/> <br/> If s >= 0.5 Then<br/> a = Sqr(Abs(wLenSqr - R0sqr / (s * s)))<br/> Else<br/> oms = 1# - s<br/> a = Sqr(Abs(wLenSqr - R1sqr / (oms * oms)))<br/> End If<br/> GetDirections w, a, Line3.direction, Line4.direction<br/> Else<br/> Dim mid As Point2D<br/> mid.x = 0.5 * (circle0.center.x + circle1.center.x)<br/> mid.y = 0.5 * (circle0.center.y + circle1.center.y)<br/> <br/> a = Sqr(Abs(wLenSqr - 4# * circle0.radius * circle0.radius))<br/> GetDirections w, a, Line1.direction, Line2.direction<br/> Line1.p.x = mid.x<br/> Line1.p.y = mid.y<br/> Line2.p.x = mid.x<br/> Line2.p.y = mid.y<br/> <br/> Dim invwlen As Double<br/> invwlen = 1# / Sqr(wLenSqr)<br/> w.x = w.x * invwlen<br/> w.y = w.y * invwlen<br/> <br/> Line3.p.x = mid.x + circle0.radius * w.y<br/> Line3.p.y = mid.y - circle0.radius * w.x<br/> Line3.direction.x = w.x<br/> Line3.direction.y = w.y<br/> Line4.p.x = mid.x - circle0.radius * w.y<br/> Line4.p.y = mid.y - circle0.radius * w.x<br/> Liner.direction.x = w.x<br/> Line4.direction.y = w.y<br/> End If<br/> lines.Add Line1<br/> lines.Add Line2<br/> lines.Add Line3<br/> lines.Add Line4<br/> LinesTangentToTwoCircles = True<br/>End Function</p><p>Private Sub GetDirections(w As Vector2D, a As Double, dir0 As Vector2D, dir1 As Vector2D)<br/> Dim aSqr As Double<br/> aSqr = a * a<br/> Dim wxSqr As Double<br/> wxSqr = w.x * w.x<br/> Dim wySqr As Double<br/> wySqr = w.y * w.y<br/> Dim c2 As Double, invc2 As Double<br/> c2 = wxSqr + wySqr<br/> invc2 = 1# / c2<br/> Dim c0 As Double, c1 As Double, discr As Double, invwx As Double, invwy As Double<br/> If Abs(w.x) >= Abs(w.y) Then<br/> c0 = aSqr - wxSqr<br/> c1 = -2# * a * w.y<br/> discr = Sqr(Abs(c1 * c1 - 4# * c0 * c2))<br/> invwx = 1# / w.x<br/> dir0.y = -0.5 * (c1 + discr) * invc2<br/> dir0.x = (a - w.y * dir0.y) * invwx<br/> dir1.y = -0.5 * (c1 - discr) * invc2<br/> dir1.x = (a - w.y * dir1.y) * invwx<br/> Else<br/> c0 = aSqr - wySqr<br/> c1 = -2# * a * w.x<br/> discr = Sqr(Abs(c1 * c1 - 4# * c0 * c2))<br/> invwy = 1# / w.y<br/> dir0.x = -0.5 * (c1 + discr) * invc2<br/> dir0.y = (a - w.x * dir0.x) * invwy<br/> dir1.x = -0.5 * (c1 - discr) * invc2<br/> dir1.y = (a - w.x * dir1.x) * invwy<br/> End If<br/>End Sub</p><p><br/></p> <p>谢谢5楼的程序。</p><p></p><p>不过还是想大家帮我想想我在4楼说的那个方法,个人认为如果成功将会是最简单的一种方法。</p> <p>哈哈,搞定了</p><p>acad.ActiveDocument.SendCommand “line tan 100,180,0 tan 340,100,0 ”</p><p>只要在不同的圆上各取一个点作为输入参数就可以了。</p>
页:
[1]