// 切り口に隣接する部分パス(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)); }
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); }