关于求直线垂足方法的讨论
本帖最后由 作者 于 2007-5-14 13:11:06 编辑 <br /><br /> <p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">一、对于<font face="Times New Roman">2</font>维空间的直线</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>给定<font face="Times New Roman">2</font>维空间的直线<font face="Times New Roman">objline</font>和点<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">m</b>, </font>可以用直线的<font face="Times New Roman">Angle</font>属性获得直线<font face="Times New Roman">objline</font>和<font face="Times New Roman">x</font>轴的夹角<font face="Times New Roman">ang, </font>这样就可以计算出垂线和<font face="Times New Roman">x</font>轴的夹角为<font face="Times New Roman">(<span style="COLOR: blue;">ang + pi / 2), </font></span>过点<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">m</font></b>画出直线<font face="Times New Roman">objline</font>的一个垂直线段<font face="Times New Roman">, </font>找出它于直线<font face="Times New Roman">objline</font>的交点即为所要的垂点<font face="Times New Roman">.</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">参考代码如下<font face="Times New Roman">:</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">Option Explicit<br/>Public Sub Sample()<br/> Dim objline As AcadLine<br/> Dim lineObj As AcadLine<br/> Dim returnPnt As Variant<br/> Dim sp(0 To 2) As Double<br/> Dim ep(0 To 2) As Double<br/> Dim ang As Double<br/> Dim pt(0 To 2) As Double<br/> Const pi = 3.14159<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"> '1. </font>一条线两端点坐标<font face="Times New Roman">(x1,y1);(x2,y2) </font>:设该直线为<font face="Times New Roman">objline<br/> ' </font>如果只有两端点坐标<font face="Times New Roman">(x1,y1);(x2,y2), </font>可用<font face="Times New Roman"> addline </font>方法画出该直线<br/><font face="Times New Roman"> ThisDrawing.Utility.GetEntity objline, pt, "Select a line"<br/> ang = objline.Angle<br/> returnPnt = ThisDrawing.Utility.GetPoint(, "Enter a point: ")<br/> sp(0) = returnPnt(0)<br/> sp(1) = returnPnt(1)<br/> sp(2) = returnPnt(2)<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"> '2.</font>做直线<font face="Times New Roman">objline</font>的一个垂直线段<font face="Times New Roman">lineObj<br/> ep(0) = sp(0) + Cos(ang + pi / 2)<br/> ep(1) = sp(1) + Sin(ang + pi / 2)<br/> ep(2) = sp(2)<br/> Set lineObj = ThisDrawing.ModelSpace.AddLine(sp, ep)<br/> '3.</font>找出直线<font face="Times New Roman">objline</font>和它的垂直线段<font face="Times New Roman">lineObj</font>的交点<font face="Times New Roman">pt<br/> returnPnt = lineObj.IntersectWith(objline, acExtendNone)<br/> If VarType(returnPnt) <> vbEmpty Then<br/> If LBound(returnPnt) <= UBound(returnPnt) Then<br/> pt(0) = returnPnt(0)<br/> pt(1) = returnPnt(1)<br/> pt(2) = returnPnt(2)<br/> End If<br/> End If<br/> returnPnt = lineObj.IntersectWith(objline, acExtendBoth)<br/> If VarType(returnPnt) <> vbEmpty Then<br/> If LBound(returnPnt) <= UBound(returnPnt) Then<br/> pt(0) = returnPnt(0)<br/> pt(1) = returnPnt(1)<br/> pt(2) = returnPnt(2)<br/> End If<br/> End If<br/> lineObj.Delete<br/> '4.</font>画垂线<font face="Times New Roman">(</font>作为检查<font face="Times New Roman">)<br/> Dim obj1 As AcadLine<br/> Set obj1 = ThisDrawing.ModelSpace.AddLine(sp, pt)<br/>End Sub<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">'***********************************************************</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><p><font face="Times New Roman"> </font></p></p><p><font face="Times New Roman"> </font></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">二、对于<font face="Times New Roman">3</font>维空间的直线<font face="Times New Roman">, </font>可以通过以下<font face="Times New Roman">2</font>种方法来找出其垂足<font face="Times New Roman">.</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">A. </font>通过坐标系转换</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>把<font face="Times New Roman">3</font>维空间<font face="Times New Roman">(</font>在此为<font face="Times New Roman">WCS)</font>内由给定直线和点所确定的平面转换到<font face="Times New Roman">2</font>维空间<font face="Times New Roman">(</font>在此为<font face="Times New Roman">UCS) (</font>所谓<font face="Times New Roman">2</font>维不过是<font face="Times New Roman">z=0</font>的一个特殊坐标系<font face="Times New Roman">), </font>就可以用前面提供的代码找出其垂足<font face="Times New Roman">, </font>然后再把它转换回到<font face="Times New Roman">3</font>维空间<font face="Times New Roman">(WCS)</font>即可<font face="Times New Roman">.</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">步骤如下<font face="Times New Roman">:</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">1. </font>先确定由给定直线<font face="Times New Roman">objline (<b style="mso-bidi-font-weight: normal;">s</b>, <b style="mso-bidi-font-weight: normal;">e</b>)</font>和点<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">m</font></b>所确定的<font face="Times New Roman">2</font>维空间<font face="Times New Roman">(UCS), </font>使给定直线和点</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>在<font face="Times New Roman">UCS</font>中的<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">z = 0</font></b></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> 1) </span>UCS</font>的原点</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>假设直线的一个端点<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">s</font></b>为<font face="Times New Roman">UCS</font>的原点<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">O</b>rigin</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> 2) </span>UCS<br/> </font>的坐标轴</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>假设<font face="Times New Roman">UCS<br/> </font>的<font face="Times New Roman">x , y, z</font>轴的单位方向矢量分别设为<font face="Times New Roman"><br/> <b style="mso-bidi-font-weight: normal;">x</b>', <b style="mso-bidi-font-weight: normal;">y</b>', <b style="mso-bidi-font-weight: normal;">z</b>'</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>给定直线假设为<font face="Times New Roman">UCS<br/> </font>的<font face="Times New Roman">x<br/> </font>轴<font face="Times New Roman">, </font>其上一点坐标为</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> <b style="mso-bidi-font-weight: normal;">X</b>AxisPoint=<b style="mso-bidi-font-weight: normal;">O</b>rigin+<b style="mso-bidi-font-weight: normal;"> x</b>' </font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>由给定直线的一个端点<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">s</font></b>指向给定点<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">m</font></b>的矢量设为<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">v = p - s</b>, </font>则<font face="Times New Roman">UCS<br/> </font>的</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> z<br/> </font></span>轴的单位方向矢量<font face="Times New Roman"><br/> <b style="mso-bidi-font-weight: normal;">z</b>' =<b style="mso-bidi-font-weight: normal;"> x</b>' × <b style="mso-bidi-font-weight: normal;">v <span style="mso-spacerun: yes;"> / | x</b>' × <b style="mso-bidi-font-weight: normal;">v |<p></p></b></span></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><b style="mso-bidi-font-weight: normal;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> </font></span></b>由右手法则<font face="Times New Roman">, y</font>轴的单位方向矢量<font face="Times New Roman"><br/> <b style="mso-bidi-font-weight: normal;">y</b>'=<b style="mso-bidi-font-weight: normal;"> z</b>' ×<b style="mso-bidi-font-weight: normal;"> x</b>' , </font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> y</span><br/> </font>轴上一点坐标为</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> <b style="mso-bidi-font-weight: normal;">Y</b>AxisPoint=<b style="mso-bidi-font-weight: normal;">O</b>rigin+<b style="mso-bidi-font-weight: normal;"> y</b>' </font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><b style="mso-bidi-font-weight: normal;"><span style="mso-spacerun: yes;"> </span></b>3) </font>产生<font face="Times New Roman">UCS<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"> </span></font>利用<font face="Times New Roman">Add</font>方法产生<font face="Times New Roman">UCS</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> RetVal = object.Add(<b style="mso-bidi-font-weight: normal;">O</b>rigin, <b style="mso-bidi-font-weight: normal;">X</b>AxisPoint, <b style="mso-bidi-font-weight: normal;">Y</b>AxisPoint, Name)</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> object =ThisDrawing.UserCoordinateSystems<p></p></font></span></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">2. </font>求坐标系转化矩阵</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> ActiveX</font></span>提供了获得坐标系转化矩阵的方法<font face="Times New Roman">, </font>但它是从当前坐标系<font face="Times New Roman">UCS</font>转化到世界坐标系<font face="Times New Roman">WCS</font>的转化矩阵<font face="Times New Roman">R(4x4).</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> R = object.GetUCSMatrix()</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">在此问题中<font face="Times New Roman">, </font>把<font face="Times New Roman">3</font>维空间<font face="Times New Roman">(WCS)</font>内由给定直线和点所确定的平面转换到<font face="Times New Roman">2</font>维空间<font face="Times New Roman">(UCS)</font>时要用它的逆转化矩阵<font face="Times New Roman">V, </font><font face="Times New Roman">V</font>的前<font face="Times New Roman">3x3</font>项可以由<font face="Times New Roman">R</font>的转置获得<font face="Times New Roman">, </font>即<font face="Times New Roman">V(i,j)=R(j,i) <span style="mso-spacerun: yes;"> (i,j =1,3)</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">V</font>的第<font face="Times New Roman">4</font>列的平移部分通过<font face="Times New Roman">R</font>的前<font face="Times New Roman">3x4</font>项计算获得<font face="Times New Roman">, </font>即<font face="Times New Roman"><br/> V(i,4)=-R(j,i)*R(j,4) <span style="mso-spacerun: yes;"> (i,j =1,3)</span></font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">V</font>的第<font face="Times New Roman">4</font>行同<font face="Times New Roman">R</font>的第<font face="Times New Roman">4</font>行<font face="Times New Roman">, </font>均为<font face="Times New Roman">(0,0,0,1), <span style="mso-spacerun: yes;"> V(4,i)=R(4,i) (i =1,4)</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">3. </font>坐标转换</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><span style="mso-spacerun: yes;"><font face="Times New Roman"> </font></span>坐标转换用<font face="Times New Roman">TransformBy</font>方法</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> object.TransformBy Matrix<span style="mso-spacerun: yes;"> ( Matrix </span>= R or V )<b style="mso-bidi-font-weight: normal;"><p></p></b></font></span></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><p><font face="Times New Roman"> </font></p></p><p><font face="Times New Roman"> </font></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman">B. </font>建立数学模型求垂足</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">模型如下<font face="Times New Roman">:</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">直线的两端点假设为<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">s</b>(s1,s2,s3), <b style="mso-bidi-font-weight: normal;">e</b>(e1,e2,e3), </font>给定点<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">m</b>(m1,m2,m3)</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">直线端点<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">s</font></b>作为<font face="Times New Roman">1</font>维坐标轴的原点<font face="Times New Roman">, </font>直线上任意点<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">P</b>(x,y,z)</font>在该<font face="Times New Roman">1</font>维坐标的坐标设为<font face="Times New Roman">t<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">直线的单位方向矢量设为</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> </span><b style="mso-bidi-font-weight: normal;">u<br/> </b>= (e1-s1, e2-s2, e3-s3)/((e1-s1)^2+(e2-s2)^2+(e3-s3)^2)^0.5 = (u1,u2,u3)</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">直线上任意点<font face="Times New Roman"><b style="mso-bidi-font-weight: normal;">P</b>(x,y,z)</font>的参数方程可表示为<font face="Times New Roman">,<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> </span><b style="mso-bidi-font-weight: normal;">P</b><br/> =<br/> <b style="mso-bidi-font-weight: normal;">s + </b>t*<b style="mso-bidi-font-weight: normal;">u</b><p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">垂线<b style="mso-bidi-font-weight: normal;"><font face="Times New Roman">mp</font></b>满足以下方程<font face="Times New Roman">,</font></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><b style="mso-bidi-font-weight: normal;"><span style="mso-spacerun: yes;"> mp</span></b>·<b style="mso-bidi-font-weight: normal;">u</b> = 0<p></p></font></p><p></p><p></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;">解此方程得<font face="Times New Roman"><br/> t = u1(m1 - s1) + u2(m2 - s2) + u3(m3 - s3) </font>后<font face="Times New Roman">, </font>垂足的坐标就可以算出</p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> x=s1+u1*t</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> y=s2+u2*t</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt;"><font face="Times New Roman"><span style="mso-spacerun: yes;"> z=s3+u3*t</font></span></p> <p>我特感兴趣,有时间好好讨论一下</p> 比较费劲可通过VLAX类来调用VLISP的vlax-curve-getClosestPointTo函数直接返回曲线上离指定点最近的点
这么简单的方法就不需要讨论了吧 多谢分享,下来参考学习学习 有时间好好讨论一下 wuyunpeng888 发表于 2009-6-22 21:38 static/image/common/back.gif
比较费劲
可通过VLAX类来调用VLISP的vlax-curve-getClosestPointTo函数直接返回曲线上离指定点最近的点
这 ...
最近点不一定是垂足!! 最近点不是垂足?你举个反例看看 指定点是你自己给的,直线不是无限长的,一个判断交点就知道是不是在延长线上了,直接就排除
页:
[1]