三维空间两直线/线段最短距离、线段计算算法 【转】
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                三维空间两直线/线段最短距离、线段计算算法 【转】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.                        
                                
                            
                            
                            https://segmentfault.com/a/1190000006111226  
d(ls,lt)=|sj?tj|=|s0?t0+(be?cd)u???(ae?bd)v??ac?b d(ls,lt)=|sj?tj|=|s0?t0+(be?cd)u???(ae?bd)v??ac?b2|
                        
                        
                        ?
d(ls,lt)=|sj?tj|=|s0?t0+(be?cd)u???(ae?bd)v??ac?b d(ls,lt)=|sj?tj|=|s0?t0+(be?cd)u???(ae?bd)v??ac?b2|
?
?
具體實(shí)現(xiàn)代碼如下(C#實(shí)現(xiàn)):
public bool IsEqual(double d1, double d2) { if (Math.Abs(d1 - d2) < 1e-7) return true; return false; } public double SqureDistanceSegmentToSegment(double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, double x4, double y4, double z4) { // 解析幾何通用解法,可以求出點(diǎn)的位置,判斷點(diǎn)是否在線段上 // 算法描述:設(shè)兩條無(wú)限長(zhǎng)度直線s、t,起點(diǎn)為s0、t0,方向向量為u、v // 最短直線兩點(diǎn):在s1上為s0+sc*u,在t上的為t0+tc*v // 記向量w為(s0+sc*u)-(t0+tc*v),記向量w0=s0-t0 // 記a=u*u,b=u*v,c=v*v,d=u*w0,e=v*w0——(a); // 由于u*w=、v*w=0,將w=-tc*v+w0+sc*u帶入前兩式得: // (u*u)*sc - (u*v)*tc = -u*w0 (公式2) // (v*u)*sc - (v*v)*tc = -v*w0 (公式3) // 再將前式(a)帶入可得sc=(be-cd)/(ac-b2)、tc=(ae-bd)/(ac-b2)——(b) // 注意到ac-b2=|u|2|v|2-(|u||v|cosq)2=(|u||v|sinq)2不小于0 // 所以可以根據(jù)公式(b)判斷sc、tc符號(hào)和sc、tc與1的關(guān)系即可分辨最近點(diǎn)是否在線段內(nèi) // 當(dāng)ac-b2=0時(shí),(公式2)(公式3)獨(dú)立,表示兩條直線平行。可令sc=0單獨(dú)解出tc // 最終距離d(L1、L2)=|(P0-Q0)+[(be-cd)*u-(ae-bd)v]/(ac-b2)| double ux = x2 - x1; double uy = y2 - y1; double uz = z2 - z1; double vx = x4 - x3; double vy = y4 - y3; double vz = z4 - z3; double wx = x1 - x3; double wy = y1 - y3; double wz = z1 - z3; double a = (ux * ux + uy * uy + uz * uz); //u*u double b = (ux * vx + uy * vy + uz * vz); //u*v double c = (vx * vx + vy * vy + vz * vz); //v*v double d = (ux * wx + uy * wy + uz * wz); //u*w double e = (vx * wx + vy * wy + vz * wz); //v*w double dt = a * c - b * b; double sd = dt; double td = dt; double sn = 0.0;//sn = be-cd double tn = 0.0;//tn = ae-bd if (IsEqual(dt, 0.0)) { //兩直線平行 sn = 0.0; //在s上指定取s0 sd = 1.00; //防止計(jì)算時(shí)除0錯(cuò)誤 tn = e; //按(公式3)求tc td = c; } else { sn = (b * e - c * d); tn = (a * e - b * d); if (sn < 0.0) { //最近點(diǎn)在s起點(diǎn)以外,同平行條件 sn = 0.0; tn = e; td = c; } else if (sn > sd) { //最近點(diǎn)在s終點(diǎn)以外(即sc>1,則取sc=1) sn = sd; tn = e + b; //按(公式3)計(jì)算 td = c; } } if (tn < 0.0) { //最近點(diǎn)在t起點(diǎn)以外 tn = 0.0; if (-d < 0.0) //按(公式2)計(jì)算,如果等號(hào)右邊小于0,則sc也小于零,取sc=0 sn = 0.0; else if (-d > a) //按(公式2)計(jì)算,如果sc大于1,取sc=1 sn = sd; else { sn = -d; sd = a; } } else if (tn > td) { tn = td; if ((-d + b) < 0.0) sn = 0.0; else if ((-d + b) > a) sn = sd; else { sn = (-d + b); sd = a; } } double sc = 0.0; double tc = 0.0; if (IsEqual(sn, 0.0)) sc = 0.0; else sc = sn / sd; if (IsEqual(tn, 0.0)) tc = 0.0; else tc = tn / td; double dx = wx + (sc * ux) - (tc * vx); double dy = wy + (sc * uy) - (tc * vy); double dz = wz + (sc * uz) - (tc * vz); return dx * dx + dy * dy + dz * dz; }參考文獻(xiàn):http://geomalgorithms.com/a07-_distance.html
- 2016年07月29日發(fā)布
轉(zhuǎn)載于:https://www.cnblogs.com/mazhenyu/p/7154449.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的三维空间两直线/线段最短距离、线段计算算法 【转】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 高阶函数 - 函数节流
- 下一篇: mybaties总结+hibernate
