/// <summary>
        /// Returns the best path distance of the given [minDeg..maxDeg] angle set.
        /// If you are not sure what the inputs mean don't tinker with it.
        /// It uses a Golden Search algorithm.
        /// </summary>
        /// <param name="deltaDeg">What the tolerance from the perfect angle is</param>
        /// <exception cref="ArgumentNullException">If either <paramref name="points"/> or <paramref name="template"/> is null</exception>
        private static float PathDistanceAtBestAngle(List <Vector2> points, TemplateGroup.Template template, float minDeg = -45,
                                                     float maxDeg = 45, float deltaDeg = 2)
        {
            if (points == null)
            {
                throw new ArgumentNullException("Points list cannot be null!");
            }
            if (template == null)
            {
                throw new ArgumentNullException("Template cannot be null");
            }

            // swap them if minDeg is larger than maxDeg
            if (maxDeg < minDeg)
            {
                float temp = minDeg;
                minDeg = maxDeg;
                maxDeg = temp;
            }
            deltaDeg = Mathf.Abs(deltaDeg);

            // The strategy is Golden Section Search(GSS), an efficient
            // algorithm that finds the minimum value in a range using the
            // Golden Ratio

            float _x1 = goldenRatio * minDeg + (1 - goldenRatio) * maxDeg;
            float _f1 = PathDistanceAtAngle(points, template, Mathf.Deg2Rad * _x1);

            float _x2 = goldenRatio * maxDeg + (1 - goldenRatio) * minDeg;
            float _f2 = PathDistanceAtAngle(points, template, Mathf.Deg2Rad * _x2);

            while (Mathf.Abs(maxDeg - minDeg) > deltaDeg)
            {
                if (_f1 < _f2)
                {
                    maxDeg = _x2;
                    _x2    = _x1;
                    _f2    = _f1;

                    _x1 = goldenRatio * minDeg + (1 - goldenRatio) * maxDeg;
                    _f1 = PathDistanceAtAngle(points, template, Mathf.Deg2Rad * _x1);
                }
                else
                {
                    minDeg = _x1;
                    _x1    = _x2;
                    _f1    = _f2;

                    _x2 = goldenRatio * maxDeg + (1 - goldenRatio) * minDeg;
                    _f2 = PathDistanceAtAngle(points, template, Mathf.Deg2Rad * _x2);
                }
            }

            return(Mathf.Min(_f1, _f2));
        }
        /// <summary>
        /// Tha path distance of a shape and a template with the shape being at a given relative rotation
        /// Points is compared to a template to find the average distance between corresponding points
        /// </summary>
        /// <param name="rad">Radian!!</param>
        /// <exception cref="ArgumentNullException">Thrown if either shape or template is null</exception>
        private static float PathDistanceAtAngle(List <Vector2> shape, TemplateGroup.Template template, float rad)
        {
            if (shape == null)
            {
                throw new ArgumentNullException("Shape cannot be null!");
            }
            if (template == null)
            {
                throw new ArgumentNullException("Tempalte cannot be null!");
            }

            return(PathDistance(RotateListToAngle(shape, rad), template));
        }
        /// <summary>
        /// Tha path distance of a shape and a template.
        /// Points is compared to a template to find the average distance between corresponding points
        /// </summary>
        /// <exception cref="ArgumentNullException">Thrown if either shape or template is null</exception>
        private static float PathDistance(List <Vector2> shape, TemplateGroup.Template template)
        {
            if (shape == null)
            {
                throw new ArgumentNullException("Shape cannot be null!");
            }
            if (template == null)
            {
                throw new ArgumentNullException("Template cannot ben null!");
            }

            int   _pointCount = Mathf.Min(template.Points.Count, shape.Count);
            float _currScore  = 0;

            for (int p = 0; p < _pointCount; p++)
            {
                _currScore += Vector2.Distance(shape[p], template.Points[p]);
            }

            return(_currScore / _pointCount);
        }