static Dictionary <BoneAnnotation, Matrix> GetSkeletalTransforms(SkeletonAnnotation an, SkeletonAnnotation orgAn)
        {
            Dictionary <BoneAnnotation, Matrix> transformDict = new Dictionary <BoneAnnotation, Matrix>();

            for (int i = 0; i < an.bones.Count; i++)
            {
                var b  = an.bones[i];
                var ob = orgAn.bones[i];

                float angle1 = (float)Math.Atan2(ob.dst.position.Y - ob.src.position.Y, ob.dst.position.X - ob.src.position.X);
                float angle2 = (float)Math.Atan2(b.dst.position.Y - b.src.position.Y, b.dst.position.X - b.src.position.X);
                angle1 = FMath.ToDegree(angle1);
                angle2 = FMath.ToDegree(angle2);

                float len1 = FMath.Distance(ob.src.position, ob.dst.position);
                float len2 = FMath.Distance(b.src.position, b.dst.position);

                if (len1 <= 1e-4)
                {
                    transformDict[b] = new Matrix();
                    continue;
                }

                Matrix transform = new Matrix();
                transform.Translate(-ob.src.position.X, -ob.src.position.Y, MatrixOrder.Append);
                transform.Rotate(-angle1, MatrixOrder.Append);
                transform.Scale(len2 / len1, len2 / len1, MatrixOrder.Append);
                transform.Rotate(angle2, MatrixOrder.Append);
                transform.Translate(b.src.position.X, b.src.position.Y, MatrixOrder.Append);

                transformDict[b] = transform;
            }

            return(transformDict);
        }
Exemple #2
0
        static float SectionHeight(PatchSkeletalMesh mesh, PatchSection section, PatchSkeletonBone b)
        {
            List <PointF> path = GetPath(mesh).Select(v => v.position).ToList();

            var curves = SectionToAdjuscentCurves(path, section, 5, 30);

            if (path == null || curves == null || b == null)
            {
                return(0);
            }

            if (curves.Item1 == null || curves.Item2 == null)
            {
                return(0);
            }

            float height = 0;

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return(0);
            }

            PointF x, y;

            CalcBoneCoordinate(b, out x, out y);

            // 各セグメントのボーンからのズレを求める
            int cnt = Math.Min(curves.Item1.Length, curves.Item2.Length);

            for (int i = 0; i < cnt; i++)
            {
                int idx1 = curves.Item1.First + curves.Item1.Length - 1 - i;
                int idx2 = curves.Item2.First + i;
                while (idx1 < 0)
                {
                    idx1 += path.Count;
                }
                while (idx2 < 0)
                {
                    idx2 += path.Count;
                }
                PointF pt1 = path[idx1 % path.Count];
                PointF pt2 = path[idx2 % path.Count];
                pt1.X  -= b.src.position.X;
                pt1.Y  -= b.src.position.Y;
                pt2.X  -= b.src.position.X;
                pt2.Y  -= b.src.position.Y;
                height += pt1.X * y.X + pt1.Y * y.Y;
                height += pt2.X * y.X + pt2.Y * y.Y;
            }

            height /= 2 * cnt;

            return(height);
        }
Exemple #3
0
        /// <param name="checkLength">sectionから何pixel分の輪郭を計算に使うか/param>
        static float SectionHeight(PatchSkeletalMesh mesh, PatchSection section, PatchSkeletonBone b, float curveLength)
        {
            List <PatchVertex> path = GetPath(mesh);
            var rawcurves           = section2adjCurves(path, section);

            if (path == null || rawcurves == null || b == null)
            {
                return(0);
            }

            var curves = TrimCurves(path, rawcurves, 0, curveLength);

            if (curves.Item1 == null || curves.Item2 == null)
            {
                return(0);
            }

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return(0);
            }

            PointF x, y;

            BoneCoordinate(b, out x, out y);

            // 各セグメントのボーンからのズレを求める
            float height = 0;
            int   cnt    = Math.Min(curves.Item1.Length, curves.Item2.Length);

            for (int i = 0; i < cnt; i++)
            {
                int idx1 = curves.Item1.First + curves.Item1.Length - 1 - i;
                int idx2 = curves.Item2.First + i;
                while (idx1 < 0)
                {
                    idx1 += path.Count;
                }
                while (idx2 < 0)
                {
                    idx2 += path.Count;
                }
                PointF pt1 = path[idx1 % path.Count].position;
                PointF pt2 = path[idx2 % path.Count].position;
                pt1.X  -= b.src.position.X;
                pt1.Y  -= b.src.position.Y;
                pt2.X  -= b.src.position.X;
                pt2.Y  -= b.src.position.Y;
                height += pt1.X * y.X + pt1.Y * y.Y;
                height += pt2.X * y.X + pt2.Y * y.Y;
            }

            height /= 2 * cnt;

            return(height);
        }
Exemple #4
0
        static float GetSectionHeight(List <PointF> path, Tuple <CharacterRange, CharacterRange> curves, BoneAnnotation b)
        {
            if (path == null || curves == null || b == null)
            {
                return(0);
            }

            if (curves.Item1 == null || curves.Item2 == null)
            {
                return(0);
            }

            float height = 0;

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return(0);
            }

            PointF x, y;

            GetCoordinateFromBone(b, out x, out y);

            // 各セグメントのボーンからのズレを求める
            int cnt = Math.Min(curves.Item1.Length, curves.Item2.Length);

            for (int i = 0; i < cnt; i++)
            {
                int idx1 = curves.Item1.First + curves.Item1.Length - 1 - i;
                int idx2 = curves.Item2.First + i;
                while (idx1 < 0)
                {
                    idx1 += path.Count;
                }
                while (idx2 < 0)
                {
                    idx2 += path.Count;
                }
                PointF pt1 = path[idx1 % path.Count];
                PointF pt2 = path[idx2 % path.Count];
                pt1.X  -= b.src.position.X;
                pt1.Y  -= b.src.position.Y;
                pt2.X  -= b.src.position.X;
                pt2.Y  -= b.src.position.Y;
                height += pt1.X * y.X + pt1.Y * y.Y;
                height += pt2.X * y.X + pt2.Y * y.Y;
            }

            height /= 2 * cnt;

            return(height);
        }
        public static List <PointF> Deform(List <PointF> pts, List <Tuple <PointF, PointF> > moves)
        {
            List <PointF> newPts = new List <PointF>();

            for (int i = 0; i < pts.Count; i++)
            {
                bool         finish = false;
                List <float> ws     = new List <float>();
                float        w_sum  = 0;

                foreach (var mv in moves)
                {
                    if (mv.Item1 == pts[i])
                    {
                        newPts.Add(mv.Item2);
                        break;
                    }
                    float w = (float)(1 / (0.01 + Math.Pow(FMath.Distance(mv.Item1, pts[i]), 2)));
                    ws.Add(w);
                    w_sum += w;
                }

                if (finish)
                {
                    continue;
                }

                if (w_sum <= 1e-4)
                {
                    newPts.Add(pts[i]);
                    continue;
                }

                float inv_w_sum = 1 / w_sum;
                for (int j = 0; j < moves.Count; j++)
                {
                    ws[j] *= inv_w_sum;
                }

                float x = pts[i].X;
                float y = pts[i].Y;
                for (int j = 0; j < moves.Count; j++)
                {
                    var   mv = moves[j];
                    float dx = mv.Item2.X - mv.Item1.X;
                    float dy = mv.Item2.Y - mv.Item1.Y;
                    x += dx * ws[j];
                    y += dy * ws[j];
                }
                newPts.Add(new PointF(x, y));
            }
            return(newPts);
        }
Exemple #6
0
        // ボーンのdst方向にあるのがpatch2
        static void OverlayPatches(PatchSkeletalMesh patch1, PatchSkeletalMesh patch2, PatchSkeleton refSkeleton, PatchSection section1, PatchSection section2, PatchSkeletonBone bone, float border)
        {
            PatchSkeletonBone refBone = RefBone(refSkeleton, bone);
            float             min1    = float.MaxValue;
            float             max2    = float.MinValue;

            List <PatchVertex> path1 = GetPath(patch1);
            List <PatchVertex> path2 = GetPath(patch2);

            for (int i = section1.First; i < section1.First + section1.Length; i++)
            {
                var   pt    = path1[FMath.Rem(i, path1.Count)].position;
                float param = FMath.ParameterOnLine(pt, refBone.src.position, refBone.dst.position);
                if (float.IsNaN(param))
                {
                    continue;
                }
                min1 = Math.Min(min1, param);
            }
            for (int i = section2.First; i < section2.First + section2.Length; i++)
            {
                var   pt    = path2[FMath.Rem(i, path2.Count)].position;
                float param = FMath.ParameterOnLine(pt, refBone.src.position, refBone.dst.position);
                if (float.IsNaN(param))
                {
                    continue;
                }
                max2 = Math.Max(max2, param);
            }

            PointF x, y;

            BoneCoordinate(refBone, out x, out y);

            float boneLength = FMath.Distance(refBone.src.position, refBone.dst.position);
            float dparam     = border / boneLength;
            float delta      = (min1 - max2 - dparam) * boneLength;
            float dx         = x.X * delta;
            float dy         = x.Y * delta;

            // mesh2の頂点・制御点を平行移動する
            foreach (var v in patch2.mesh.vertices)
            {
                v.position = new PointF(v.position.X + dx, v.position.Y + dy);
            }
            foreach (var c in patch2.mesh.CopyControlPoints())
            {
                patch2.mesh.TranslateControlPoint(c.position, new PointF(c.position.X + dx, c.position.Y + dy), false);
            }
        }
Exemple #7
0
        // ptとdirが表す直線状を、ptから双方向に操作したときに最初に見つかるピクセル
        // iterは32ビット長を仮定
        unsafe static PointF GetNearestPixel(BitmapIterator iter, PointF pt, PointF dir, Rectangle bounds, Predicate <int> isFound = null)
        {
            if (iter.PixelSize != 4)
            {
                return(new PointF(-1, -1));
            }

            float len = FMath.Distance(dir, PointF.Empty);

            if (len <= 1e-4)
            {
                return(new PointF(-1, -1));
            }
            float dx = dir.X / len;
            float dy = dir.Y / len;

            int cnt = 0;

            while (true)
            {
                float x1 = pt.X + dx * cnt;
                float y1 = pt.Y + dy * cnt;
                float x2 = pt.X - dx * cnt;
                float y2 = pt.Y - dy * cnt;

                bool out1 = !bounds.Contains((int)x1, (int)y1);
                bool out2 = !bounds.Contains((int)x2, (int)y2);

                if (out1 && out2)
                {
                    return(new PointF(-1, -1));
                }

                if (!out1 && CheckNearestPixel(x1, y1, iter, isFound))
                {
                    return(new PointF(x1, y1));
                }

                if (!out2 && CheckNearestPixel(x2, y2, iter, isFound))
                {
                    return(new PointF(x2, y2));
                }

                cnt++;
            }
        }
Exemple #8
0
        static void CalcBoneCoordinate(PatchSkeletonBone b, out PointF x, out PointF y)
        {
            x = new PointF(1, 0);
            y = new PointF(0, 1);

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return;
            }

            float dx = (b.dst.position.X - b.src.position.X) / boneLen;
            float dy = (b.dst.position.Y - b.src.position.Y) / boneLen;

            x = new PointF(dx, dy);
            y = new PointF(dy, -dx);
        }
Exemple #9
0
        static void GetCoordinateFromBone(BoneAnnotation b, out PointF x, out PointF y)
        {
            x = new PointF(1, 0);
            y = new PointF(0, 1);

            float boneLen = FMath.Distance(b.src.position, b.dst.position);

            if (boneLen <= 1e-4)
            {
                return;
            }

            float dx = (b.dst.position.X - b.src.position.X) / boneLen;
            float dy = (b.dst.position.Y - b.src.position.Y) / boneLen;

            x = new PointF(dx, dy);
            y = new PointF(dy, -dx);
        }
        public static void SetSkeletalControlPoints(ARAPDeformation arap, SkeletonAnnotation an, int linearSpan, Dictionary <BoneAnnotation, List <PointF> > boneToControls)
        {
            if (arap == null)
            {
                return;
            }

            boneToControls.Clear();
            arap.ClearControlPoints();

            // ボーン沿いに制御点を追加
            HashSet <PointF> pts = new HashSet <PointF>();

            if (an != null && linearSpan >= 1)
            {
                foreach (var b in an.bones)
                {
                    PointF p0    = b.src.position;
                    PointF p1    = b.dst.position;
                    float  dist  = FMath.Distance(p0, p1);
                    int    ptNum = Math.Max(2, (int)(dist / linearSpan) + 1);

                    boneToControls[b] = new List <PointF>();

                    for (int i = 0; i < ptNum; i++)
                    {
                        float  t = (float)i / (ptNum - 1);
                        PointF p = i == 0 ? p0 : i == ptNum - 1 ? p1 : FMath.Interpolate(p0, p1, t);
                        if (!pts.Contains(p))
                        {
                            arap.AddControlPoint(p, p);
                        }
                        boneToControls[b].Add(p);
                        pts.Add(p);
                    }
                }
            }
        }
Exemple #11
0
        static CharacterRange TrimCurve(List <PatchVertex> path, CharacterRange curve, float offset, float length)
        {
            float total = 0;
            int   start = 0;
            int   cnt   = 1;

            for (int i = curve.First; i < curve.First + curve.Length - 1; i++)
            {
                PointF p1 = path[FMath.Rem(i, path.Count)].position;
                PointF p2 = path[FMath.Rem(i + 1, path.Count)].position;
                total += FMath.Distance(p1, p2);
                if (total < offset)
                {
                    start++;
                    break;
                }
                if (total > length)
                {
                    break;
                }
                cnt++;
            }
            return(new CharacterRange(FMath.Rem(curve.First + start, path.Count), cnt));
        }
        /*
         * // ボーンに沿うようにメッシュの頂点を微調整し、そこに制御点を打つ
         * public List<int> AddBoneConstraint(AnnotationBone bone, float threshold)
         * {
         *  var idxes = new List<int>();
         *  var src = bone.jointSrc.PositionInBmp;
         *  var dst = bone.jointDst.PositionInBmp;
         *  var dir = bone.Dir;
         *  var maxt = Vector3.Dot(dir, dst - src);
         *
         *  for (int i = 0; i < orgMeshPointList.Count; i++)
         *  {
         *      var p = orgMeshPointList[i];
         *      var t = Vector3.Dot(dir, p - src);
         *      if (0 <= t && t <= maxt)
         *      {
         *          var h = src + t * dir;
         *          float dist = Vector3.DistanceSquared(p, h);
         *          if (dist <= threshold)
         *          {
         *              orgMeshPointList[i] = h;
         *              meshPointList[i] = h;
         *              orgControls.Add(h);
         *              controls.Add(h);
         *              controlsToPart.Add(meshPtToPart[i]);
         *              idxes.Add(orgControls.Count - 1);
         *          }
         *      }
         *  }
         *
         *  return idxes;
         * }
         */

        public void Precompute()
        {
            // todo

            /*
             * meshPtToPart.Clear();
             * for (int i = 0; i < meshPointList.Count; i++)
             *  meshPtToPart.Add(0);
             *
             * controlsToPart.Clear();
             * for (int i = 0; i < controls.Count; i++)
             *  controlsToPart.Add(0);
             */

            //------------

            if (controls.Count < 3)
            {
                return;
            }

            weights = new float[meshPointList.Count * controls.Count];
            A00     = new float[meshPointList.Count * controls.Count];
            A01     = new float[meshPointList.Count * controls.Count];
            A10     = new float[meshPointList.Count * controls.Count];
            A11     = new float[meshPointList.Count * controls.Count];
            D       = new PointF[meshPointList.Count];

            for (int vIdx = 0; vIdx < meshPointList.Count; vIdx++)
            {
                int offset = vIdx * controls.Count;
                for (int i = 0; i < controls.Count; i++)
                {
                    if (meshPtToPart[vIdx] == controlsToPart[i])
                    {
                        // ぴったり同じ位置だったら無限の重みを与える
                        if (FMath.Distance(orgControls[i], orgMeshPointList[vIdx]) <= 1e-4)
                        {
                            weights[i + offset] = float.PositiveInfinity;
                        }
                        else
                        {
                            weights[i + offset] = (float)(1 / (0.01 + Math.Pow(FMath.Distance(orgControls[i], orgMeshPointList[vIdx]), 2)));
                        }
                    }
                    else
                    {
                        weights[i + offset] = 0;
                    }
                }

                PointF?Pa = CompWeightAvg(orgControls, weights, vIdx);
                if (Pa == null || !Pa.HasValue)
                {
                    return;
                }

                PointF[] Ph = new PointF[orgControls.Count];
                for (int i = 0; i < orgControls.Count; i++)
                {
                    if (!orgControls[i].IsEmpty)
                    {
                        Ph[i].X = orgControls[i].X - Pa.Value.X;
                        Ph[i].Y = orgControls[i].Y - Pa.Value.Y;
                    }
                }

                float mu = 0;
                for (int i = 0; i < controls.Count; i++)
                {
                    mu += (float)(Ph[i].X * Ph[i].X + Ph[i].Y * Ph[i].Y) * weights[i + offset];
                }

                D[vIdx].X = orgMeshPointList[vIdx].X - Pa.Value.X;
                D[vIdx].Y = orgMeshPointList[vIdx].Y - Pa.Value.Y;
                for (int i = 0; i < controls.Count; i++)
                {
                    int idx = i + offset;
                    A00[idx] = weights[idx] / mu * (Ph[i].X * D[vIdx].X + Ph[i].Y * D[vIdx].Y);
                    A01[idx] = -weights[idx] / mu * (Ph[i].X * (-D[vIdx].Y) + Ph[i].Y * D[vIdx].X);
                    A10[idx] = -weights[idx] / mu * (-Ph[i].Y * D[vIdx].X + Ph[i].X * D[vIdx].Y);
                    A11[idx] = weights[idx] / mu * (Ph[i].Y * D[vIdx].Y + Ph[i].X * D[vIdx].X);
                }
            }
        }
        void Precompute()
        {
            if (orgControls.Count < 3)
                return;

            weights = new float[meshPointList.Count * orgControls.Count];
            A00 = new float[meshPointList.Count * orgControls.Count];
            A01 = new float[meshPointList.Count * orgControls.Count];
            A10 = new float[meshPointList.Count * orgControls.Count];
            A11 = new float[meshPointList.Count * orgControls.Count];
            D = new PointF[meshPointList.Count];

            for (int vIdx = 0; vIdx < meshPointList.Count; vIdx++)
            {
                int offset = vIdx * orgControls.Count;
                for (int i = 0; i < orgControls.Count; i++)
                {
                    if (meshPtToPart[vIdx] == controlsToPart[i])
                    {
                        // ぴったり同じ位置だったら無限の重みを与える
                        if (FMath.Distance(orgControls[i], orgMeshPointList[vIdx]) <= 1e-4)
                            weights[i + offset] = float.PositiveInfinity;
                        else
                            weights[i + offset] = (float)(1 / (0.01 + Math.Pow(FMath.Distance(orgControls[i], orgMeshPointList[vIdx]), 2)));
                    }
                    else
                    {
                        weights[i + offset] = 0;
                    }
                }

                // 追加 2014/11/08
                int nonzeroCnt = 0;
                for (int i = 0; i < orgControls.Count; i++)
                    if (weights[i + offset] != 0)
                        nonzeroCnt++;
                if (nonzeroCnt <= 1)
                    continue;
//                    return;

                PointF? Pa = AverageWeight(orgControls, weights, vIdx);
                if (Pa == null || !Pa.HasValue)
                    // 変更 2014/11/08
                    continue;
//                    return;

                PointF[] Ph = new PointF[orgControls.Count];
                for (int i = 0; i < orgControls.Count; i++)
                {
                    if (!orgControls[i].IsEmpty)
                    {
                        Ph[i].X = orgControls[i].X - Pa.Value.X;
                        Ph[i].Y = orgControls[i].Y - Pa.Value.Y;
                    }
                }

                float mu = 0;
                for (int i = 0; i < orgControls.Count; i++)
                    mu += (float)(Ph[i].X * Ph[i].X + Ph[i].Y * Ph[i].Y) * weights[i + offset];


                D[vIdx].X = orgMeshPointList[vIdx].X - Pa.Value.X;
                D[vIdx].Y = orgMeshPointList[vIdx].Y - Pa.Value.Y;
                for (int i = 0; i < orgControls.Count; i++)
                {
                    int idx = i + offset;
                    A00[idx] = weights[idx] / mu * (Ph[i].X * D[vIdx].X + Ph[i].Y * D[vIdx].Y);
                    A01[idx] = -weights[idx] / mu * (Ph[i].X * (-D[vIdx].Y) + Ph[i].Y * D[vIdx].X);
                    A10[idx] = -weights[idx] / mu * (-Ph[i].Y * D[vIdx].X + Ph[i].X * D[vIdx].Y);
                    A11[idx] = weights[idx] / mu * (Ph[i].Y * D[vIdx].Y + Ph[i].X * D[vIdx].X);
                }
            }
        }
Exemple #14
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);
        }
Exemple #15
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="course">0以上.値が大きいほど荒くなる</param>
        /// <returns></returns>
        public static List <PointF> Subdivide(List <PointF> path, float course)
        {
            if (course <= 0)
            {
                return(null);
            }

            float x = float.MaxValue, y = float.MaxValue, x1 = float.MinValue, y1 = float.MinValue;

            foreach (var p in path)
            {
                x  = Math.Min(p.X, x);
                y  = Math.Min(p.Y, y);
                x1 = Math.Max(p.X, x1);
                y1 = Math.Max(p.Y, y1);
            }
            int w = (int)(x1 - x), h = (int)(y1 - y);

            x  = x - w;
            y  = y - h;
            w *= 3;
            h *= 3;

            Rectangle bounds = new Rectangle((int)x, (int)y, w, h);

            Pen pen = new Pen(Brushes.Red, 2);

            List <PointF> divPath = new List <PointF>();

            using (Bitmap line = new Bitmap((int)x + w, (int)y + h))
            {
                using (var g = Graphics.FromImage(line))
                {
                    g.Clear(Color.Transparent);
                    g.DrawCurve(pen, path.ToArray());
                }

                using (BitmapIterator iter = new BitmapIterator(line, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    for (int i = 0; i < path.Count - 1; i++)
                    {
                        divPath.Add(path[i]);
                        List <PointF> seg = SubdivideSegment(path[i], path[i + 1], course);
                        if (seg == null)
                        {
                            continue;
                        }
                        float len = FMath.Distance(path[i], path[i + 1]);
                        if (len <= 1e-4)
                        {
                            continue;
                        }
                        float  dy  = (path[i].X - path[i + 1].X) / len;
                        float  dx  = (path[i + 1].Y - path[i].Y) / len;
                        PointF dir = new PointF(dx, dy);
                        foreach (var p in seg)
                        {
                            PointF pt = GetNearestPixel(iter, p, dir, bounds, null);
                            if (pt.X >= 0 && pt.Y >= 0)
                            {
                                divPath.Add(pt);
                            }
                        }
                    }
                }
            }

            divPath.Add(path.Last());

            return(divPath);
        }