//public override bool strokeFitsMap(Stroke s)
        //{
        //    var areaPoints = LinearInterpolation.getPointsByDistance(new LinearInterpolation(s.Points), AreaPointDistance);
        //    return !areaPoints.Zip(areas,
        //                (p, a) => a.PointInToleranceArea(p.X, p.Y)
        //           ).Any(b => !b);
        //}

        public override Observation[] getSymbolTrace(BaseTrajectory s)
        {
            var strokeInterpolation = (translationInvariant) ?
                                      new LinearInterpolation(s.getInvariantPoints()) :
                                      new LinearInterpolation(s.TrajectoryPoints);
            var areaPoints = LinearInterpolation.getPointsByDistance(strokeInterpolation, AreaPointDistance);

            //ToDo: tolerate longer inputs than trained?
            //if (areaPoints.Length > Areas.Length) return null;

            //ToDo: tolerate shorter inputs?
            if (areaPoints.Length < Areas.Length)
            {
                return(null);
            }

            var observations = new Observation[Areas.Length + 2]; //+ GS and GE
            int iObs         = 1;

            string baseSym = "S" + ID + "_A";
            string symbol;
            long   time;

            for (int iArea = 0; iArea < Areas.Length; iArea++)
            {
                var area = Areas[iArea];
                if (iArea >= areaPoints.Length)
                {
                    break;
                }

                var point = areaPoints[iArea];

                if (area.PointInArea(point.X, point.Y))
                {
                    symbol = baseSym + (iArea + 1) + "_Hit";
                    time   = point.Time;
                }
                else if (area.PointInToleranceArea(point.X, point.Y))
                {
                    symbol = baseSym + (iArea + 1) + "_Tolerance";
                    time   = point.Time;
                }
                else
                {
                    return(null);
                }

                observations[iObs++] = new Observation(symbol, time);
            }

            //GestureStart symbol
            observations[0] = new Observation("GestureStart", s.TrajectoryPoints[0].Time);
            //GestureEnd symbol
            observations[observations.Length - 1] = new Observation("GestureEnd", s.TrajectoryPoints[s.TrajectoryPoints.Length - 1].Time);

            return(observations);
        }
        private void generateSmallestEnclosingCircles()
        {
            var areaPointsPerStroke = interpolatedStrokes.Select(s => LinearInterpolation.getPointsByDistance(s, AreaPointDistance)).ToArray();
            //var maxNArea = areaPointsPerStroke.Max(areaPoints => areaPoints.Length);

            //Areas = Enumerable.Range(0, maxNArea).Select(
            //            a => new SmallestEnclosingCircle(areaPointsPerStroke.Where(points => points.Length > a).Select(points => points[a])) //Where was added here due to different area counts
            //        ).ToArray();

            var minNArea = areaPointsPerStroke.Min(areaPoints => areaPoints.Length);

            Areas = Enumerable.Range(0, minNArea).Select(
                a => new SmallestEnclosingCircle(areaPointsPerStroke.Select(points => points[a]))
                ).ToArray();
        }