• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            雁過無痕

              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::

            前一篇文章討論了二維坐標系下的判斷,下面討論三維的情況。

            三維坐標下,對點的判斷明顯要復雜很多。如果google“Point in triangle”,第一個搜索結果就是這個,可惜的是,作者沒有對結果進一步討論,沒有給出一個好的實現,而且其所有結論只在已知四點共面時才成立

             

             

             

             

            前面已經證明過,面積法和向量同向法是等價的。

            ab × ac = ab × ap + ap × ac + pb × pc

            |ab × ac| = |ab × ap| + |ap × ac| + |pb × pc|

            由于ab × ac、ab × ap、ap × ac、pb × pc這4個向量平行同向,因而可以先判斷a、b、c、p這四點是否共面(通過計算混合積),若共面的話,則4個向量一定共線,接著只要判斷后三個向量是否都和第一個向量(ab × ac)同向(可以通過判斷后三個向量與第一個向量的點積的正負性來確定)

             

            代碼:

             

            #include<cfloat>

            template<typename T> class Vec3 {

             T x, y, z;

            public:

             Vec3(T xx, T yy, T zz) : x(xx), y(yy), z(zz) {}

             Vec3 operator-(const Vec3& v) const { return Vec3(x - v.x, y - v.y, z - v.z); }

             T dot(const Vec3& v) const { return x * v.x + y * v.y + z * v.z; }

             

             Vec3 cross(const Vec3& v) const {

                return Vec3(y * v.z - z * v.y, z * v.x - x * v.z,x * v.y - y * v.x);

             }

            };

             

            typedef Vec3<double> V3d;

             

            //方法一

            bool is_in_triangle3a(const V3d& a, const V3d& b, const V3d& c, const V3d& p)

            {

             V3d ab(b - a), ac(c - a), ap(p -a);

             if (fabs(ab.cross(ac).dot(ap)) >= DBL_EPSILON) return false; //四點不共面

             V3d abc = ab.cross(ac), abp = ab.cross(ap), apc = ap.cross(ac);

             double t0 = abc.dot(abc), t1 = abp.dot(abc), t2 = apc.dot(abc);

             

             //t1 >= 0     t2 >= 0    t1 + t2 <= t0       t0肯定大于0

             // return (t1 >= -DBL_EPSILON) & (t2 >= -DBL_EPSILON) & (t0 - t1 - t2 >= -DBL_EPSILON);

             double delta = fabs(t1) + fabs(t2) + fabs(t0 - t1 - t2) - t0;

              return fabs(delta) < DBL_EPSILON; 

            }

             

            方法一,需要30次乘法計算。即使在已知四點共面的情況下,仍需要27次乘法計算,僅節省了3次乘法計算。考慮到每次計算向量積需要6次乘法計算,而計算點積只要3次乘法計算,因而可以考慮消除向量積計算:

             

             

            利用公式:

             (a × b)· c = (c × a)· b       (混合積)

             a × (b × c) = b(a·c) c(a·b)  (拉格朗日公式)

            可得:

            (a × b)·(a × c) = ((a × c) × a)·b = ((a·a)c – (a·c)a)·b

            = (a·a) * (b·c) – (a·c) * (a·b)

             

            利用這個展開式,可得:

             

            //方法二

            bool is_in_triangle3b(const V3d& a, const V3d& b, const V3d& c, const V3d& p)

            {

             V3d ab(b - a), ac(c - a), ap(p -a);

             if (fabs(ab.cross(ac).dot(ap)) >= DBL_EPSILON) return false; //四點不共面

             V3d abc = ab.cross(ac), abp = ab.cross(ap), apc = ap.cross(ac);

             

             //double t0 = abc.dot(abc), t1 = abp.dot(abc), t2 = apc.dot(abc); //對這三個計算公式進行展開

             double v11 = ab.dot(ab), v22 = ac.dot(ac), v12 = ab.dot(ac);

             double v13 = ab.dot(ap), v23 = ac.dot(ap);

             double t0 = v11 * v22 - v12 * v12;

             double t1 = v11 * v23 - v12 * v13;

             double t2 = v22 * v13 - v12 * v23;

             

             double delta = fabs(t1) + fabs(t2) + fabs(t0 - t1 - t2) - t0;

             return fabs(delta) < DBL_EPSILON; 

            }

             

            方法二,需要30次乘法計算,但在已知四點共面時則只需要21次乘法計算

             

            上面的兩種方法,方法一,容易記,容易實現,且在不能確定四點共面時,效率與方法二差不多(甚至可能略高);而方法二最大的優點,則是在已知四點共面時,比方法一少用6次乘法,但是實現起來實在麻煩。那么,是否存在更好的方法呢?答案是肯定的,這就是后面要提到的方法(多一次條件判斷,只要13乘法(四點共面時只要8))。

             


            作者: flyinghearts
            出處: http://www.cnblogs.com/flyinghearts/
            本文采用知識共享署名-非商業性使用-相同方式共享 2.5 中國大陸許可協議進行許可,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
            posted on 2011-07-14 23:28 flyinghearts 閱讀(1629) 評論(0)  編輯 收藏 引用 所屬分類: 算法
            久久人人爽人人爽人人片AV不 | 青草国产精品久久久久久| 亚洲国产精品无码久久98| 国内精品久久久久久野外| 久久无码人妻一区二区三区午夜| 久久青青草原精品国产不卡| 一级做a爰片久久毛片看看| 亚洲精品无码久久久久AV麻豆| 99久久精品免费观看国产| 国产三级精品久久| 人妻中文久久久久| 久久精品视频一| 久久亚洲私人国产精品| 国产精品毛片久久久久久久| 91久久精品国产成人久久| 久久综合九色综合久99| 97视频久久久| AV无码久久久久不卡蜜桃| 99久久国产综合精品五月天喷水| 久久无码国产| 色欲综合久久中文字幕网| 亚洲狠狠综合久久| 一97日本道伊人久久综合影院| 亚洲国产精品无码久久一区二区| 狠狠色丁香婷婷综合久久来| 久久精品亚洲乱码伦伦中文| 亚洲综合伊人久久大杳蕉| 久久亚洲国产精品一区二区| 婷婷国产天堂久久综合五月| 久久人爽人人爽人人片AV| 办公室久久精品| 无码久久精品国产亚洲Av影片| 91亚洲国产成人久久精品| 三级三级久久三级久久| 青青草原综合久久| 超级97碰碰碰碰久久久久最新| 久久国产精品久久久| 狠狠色综合网站久久久久久久高清| 一级做a爰片久久毛片16| 一本色道久久综合亚洲精品| 久久国产热这里只有精品|