private Dictionary <Point, SkeletonMinutia> ComputeMinutiaCenters(Dictionary <Point, List <Point> > linking)
        {
            var centers = new Dictionary <Point, SkeletonMinutia>();

            foreach (var currentPos in linking.Keys)
            {
                var linkedMinutiae = linking[currentPos];
                var primaryPos     = linkedMinutiae[0];
                if (!centers.ContainsKey(primaryPos))
                {
                    var sum = new Point();
                    foreach (var linkedPos in linkedMinutiae)
                    {
                        sum += linkedPos;
                    }
                    var center  = new Point(sum.X / linkedMinutiae.Count, sum.Y / linkedMinutiae.Count);
                    var minutia = new SkeletonMinutia(center);
                    AddMinutia(minutia);
                    centers[primaryPos] = minutia;
                }

                centers[currentPos] = centers[primaryPos];
            }

            return(centers);
        }
        private static bool IsWithinGapLimits(SkeletonMinutia end1, SkeletonMinutia end2)
        {
            const int  ruptureSize = 5;
            const int  gapSize     = 20;
            const byte gapAngle    = 32;

            var distanceSq = (end1.Position - end2.Position).SqLength;

            if (distanceSq <= MathEx.Sq(ruptureSize))
            {
                return(true);
            }
            if (distanceSq > MathEx.Sq(gapSize))
            {
                return(false);
            }

            var gapDirection = Angle.AtanB(end1.Position, end2.Position);
            var direction1   = Angle.AtanB(end1.Position, GetAngleSampleForGapRemoval(end1));

            if (Angle.Distance(direction1, Angle.Opposite(gapDirection)) > gapAngle)
            {
                return(false);
            }
            var direction2 = Angle.AtanB(end2.Position, GetAngleSampleForGapRemoval(end2));

            if (Angle.Distance(direction2, gapDirection) > gapAngle)
            {
                return(false);
            }
            return(true);
        }
        private static Point GetAngleSampleForGapRemoval(SkeletonMinutia minutia)
        {
            const int angleSampleOffset = 22;
            var       ridge             = minutia.Ridges[0];

            if (angleSampleOffset < ridge.Points.Count)
            {
                return(ridge.Points[angleSampleOffset]);
            }
            return(ridge.End.Position);
        }
 public void RemoveMinutia(SkeletonMinutia minutia)
 {
     Minutiae.Remove(minutia);
 }
 public void AddMinutia(SkeletonMinutia minutia)
 {
     Minutiae.Add(minutia);
 }