Пример #1
0
        public static double ComputeUnscaledFormFactor(
            this Polygon3d polygon,
            V3d p, V3d n,
            double eps = 1e-6)
        {
            var vc = polygon.PointCount;

            V3d[] cpa = new V3d[vc + 1];

            var cc = 0;
            var pb = polygon[0] - p;
            var hb = Vec.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;

            if (hb >= -eps)
            {
                cpa[cc++] = pb;
            }
            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;

            for (int vi = 1; vi < vc; vi++)
            {
                var  p1 = polygon[vi] - p; var h1 = Vec.Dot(p1, n);
                bool h1p = h1 > eps, h1n = h1 < -eps;
                if (h0p && h1n || h0n && h1p)
                {
                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));
                }
                if (h1 >= -eps)
                {
                    cpa[cc++] = p1;
                }
                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;
            }
            if (h0p && hbn || h0n && hbp)
            {
                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));
            }

            var cpr = cpa.Map(cc, v => v.Length);

            var    cv = Vec.Cross(cpa[0], cpa[cc - 1]);
            double ff = Vec.Dot(n, cv)
                        * Fun.AcosClamped(Vec.Dot(cpa[0], cpa[cc - 1])
                                          / (cpr[0] * cpr[cc - 1]))
                        / cv.Length;

            for (int ci = 0; ci < cc - 1; ci++)
            {
                cv  = Vec.Cross(cpa[ci + 1], cpa[ci]);
                ff += Vec.Dot(n, cv)
                      * Fun.AcosClamped(Vec.Dot(cpa[ci + 1], cpa[ci])
                                        / (cpr[ci + 1] * cpr[ci]))
                      / cv.Length;
            }
            return(ff);
        }