Ejemplo n.º 1
0
        // 切り口に隣接する部分パス(2つ)を返す
        // この部分を引き伸ばしてメッシュを繋げる
        static Tuple <CharacterRange, CharacterRange> SectionToAdjuscentCurves(List <PointF> path, PatchSection section, int maxPtNum, float maxAngle)
        {
            if (section.Length <= 0 || path == null || path.Count < 5 || maxPtNum < 3)
            {
                return(null);
            }

            float cos = (float)Math.Cos(maxAngle);

            // 1つ目の部分パス

            int start1 = section.First;

            while (start1 < 0)
            {
                start1 += path.Count;
            }
            start1 = start1 % path.Count;

            int end1 = start1 - 2;

            for (int i = 0; i < maxPtNum - 2; i++)
            {
                int idx   = (start1 - 2 - i + path.Count) % path.Count;
                var curve = new List <PointF>();
                for (int j = idx; j < idx + 3; j++)
                {
                    curve.Add(path[FMath.Rem(j, path.Count)]);
                }
                if (FMath.GetAngleCos(curve) < cos)
                {
                    break;
                }
                end1 = idx;
            }

            CharacterRange r1 = new CharacterRange();

            if (start1 > end1)
            {
                r1 = new CharacterRange(end1, start1 - end1 + 1);
            }
            if (start1 < end1)
            {
                // 始点と終点をまたがっている場合
                r1 = new CharacterRange(end1, start1 + path.Count - end1 + 1);
            }

            if (r1.Length <= 0)
            {
                return(null);
            }

            // 2つ目の部分パス

            int start2 = section.First + section.Length - 1;

            while (start2 < 0)
            {
                start2 += path.Count;
            }
            start2 = start2 % path.Count;

            int end2 = start2 + 2;

            for (int i = 0; i < maxPtNum - 2; i++)
            {
                int idx   = (start2 + i) % path.Count;
                var curve = path.Skip(idx).Take(3).ToList();
                if (FMath.GetAngleCos(curve) < cos)
                {
                    break;
                }
                end2 = start2 + i + 2;
            }

            CharacterRange r2 = new CharacterRange();

            if (start2 < end2)
            {
                r2 = new CharacterRange(start2, end2 - start2 + 1);
            }
            if (start2 > end2)
            {
                r2 = new CharacterRange(start2, end2 + path.Count - start2 + 1);
            }

            if (r2.Length <= 0)
            {
                return(null);
            }

            return(new Tuple <CharacterRange, CharacterRange>(r1, r2));
        }
Ejemplo n.º 2
0
        private static float OverlapWidth(PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton, PatchSection section1, PatchSection section2, PatchSkeletonBone bone, int maxLength, int maxAngle)
        {
            var refBone = RefBone(refSkeleton, bone);

            var path1   = GetPath(patch1);
            var curves1 = section2adjCurves(path1, section1);
            var sorted1 = GetSortedCurves(path1.Select(v => v.position).ToList(), curves1, refBone);

            var path2   = GetPath(patch2);
            var curves2 = section2adjCurves(path2, section2);
            var sorted2 = GetSortedCurves(path2.Select(v => v.position).ToList(), curves2, refBone);

            float[] param        = new float[] { 0, 0, 0, 0 };
            var     sortedCurves = new[] {
                sorted1[0],
                sorted1[1],
                sorted2[0],
                sorted2[1],
            };

            float minCos = (float)Math.Cos(Math.PI / 180 * maxAngle);

            for (int i = 0; i < sortedCurves.Length; i++)
            {
                var           c     = sortedCurves[i];
                var           path  = i < 2 ? path1 : path2;
                List <PointF> pts   = new List <PointF>();
                float         total = 0;
                for (int j = c.Count - 1; j >= 0; j--)
                {
                    var p = c[j];
                    pts.Add(p);
                    if (pts.Count >= 3 && FMath.GetAngleCos(pts) < minCos)
                    {
                        pts.RemoveAt(pts.Count - 1);
                        break;
                    }
                    if (pts.Count >= 2)
                    {
                        total += FMath.Distance(pts[pts.Count - 2], pts[pts.Count - 1]);
                    }
                    if (total >= maxLength)
                    {
                        pts.RemoveAt(pts.Count - 1);
                        break;
                    }
                }
                param[i] = FMath.ParameterOnLine(pts.Last(), refBone.src.position, refBone.dst.position);
            }

            float min1 = Enumerable.Range(section1.First, section1.Length).Min(idx =>
                                                                               FMath.ParameterOnLine(path1[FMath.Rem(idx, path1.Count)].position, refBone.src.position, refBone.dst.position));
            float max1 = Enumerable.Range(section1.First, section1.Length).Max(idx =>
                                                                               FMath.ParameterOnLine(path1[FMath.Rem(idx, path1.Count)].position, refBone.src.position, refBone.dst.position));

            int idx1 = Enumerable.Range(section1.First, section1.Length).First(idx =>
                                                                               max1 == FMath.ParameterOnLine(path1[FMath.Rem(idx, path1.Count)].position, refBone.src.position, refBone.dst.position));

            float min2 = Enumerable.Range(section2.First, section2.Length).Min(idx =>
                                                                               FMath.ParameterOnLine(path2[FMath.Rem(idx, path2.Count)].position, refBone.src.position, refBone.dst.position));
            float max2 = Enumerable.Range(section2.First, section2.Length).Max(idx =>
                                                                               FMath.ParameterOnLine(path2[FMath.Rem(idx, path2.Count)].position, refBone.src.position, refBone.dst.position));

            float idx2 = Enumerable.Range(section2.First, section2.Length).First(idx =>
                                                                                 max2 == FMath.ParameterOnLine(path2[FMath.Rem(idx, path2.Count)].position, refBone.src.position, refBone.dst.position));

            System.Diagnostics.Debug.Assert(param[0] <= max1);
            System.Diagnostics.Debug.Assert(param[1] <= max1);
            System.Diagnostics.Debug.Assert(param[2] >= min2);
            System.Diagnostics.Debug.Assert(param[3] >= min2);

            float[] dParams = new[] {
                Math.Max(0, min1 - param[0]),
                Math.Max(0, min1 - param[1]),
                Math.Max(0, param[2] - max2),
                Math.Max(0, param[3] - max2),
            };

            float minDParam    = dParams.Min();
            float boarderWidth = minDParam * FMath.Distance(refBone.src.position, refBone.dst.position);

            return(boarderWidth);
        }