protected override void Load(ContainerBuilder builder)
        {
            base.Load(builder);

            // register route processors
            builder.RegisterAssemblyTypes(typeof(IRouteProcessor).Assembly)
            .Where(t => typeof(IRouteProcessor).IsAssignableFrom(t) &&
                   !t.IsAbstract &&
                   t.GetConstructors().Any() &&
                   GeoExtensions.GetTargetType <RouteProcessorAttribute>(t) != null)
            .Keyed <IRouteProcessor>(t => t.GetCustomAttribute <RouteProcessorAttribute>() !.Type)
            .AsImplementedInterfaces()
            .SingleInstance();

            // register exporters
            builder.RegisterAssemblyTypes(typeof(IRouteProcessor).Assembly)
            .Where(t => typeof(IExporter).IsAssignableFrom(t) &&
                   !t.IsAbstract &&
                   t.GetConstructors().Any() &&
                   GeoExtensions.GetTargetType <ExporterAttribute>(t) != null)
            .Keyed <IExporter>(t => t.GetCustomAttribute <ExporterAttribute>() !.Type)
            .AsImplementedInterfaces()
            .SingleInstance();

            // register importers
            builder.RegisterAssemblyTypes(typeof(IRouteProcessor).Assembly)
            .Where(t => typeof(IImporter).IsAssignableFrom(t) &&
                   !t.IsAbstract &&
                   t.GetConstructors().Any() &&
                   GeoExtensions.GetTargetType <ImporterAttribute>(t) != null)
            .Keyed <IImporter>(t => t.GetCustomAttribute <ImporterAttribute>() !.Type)
            .AsImplementedInterfaces()
            .SingleInstance();
        }
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        protected override async Task <List <Coordinate>?> ExecuteRequestAsync(
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
            List <Coordinate> coordinates,
            CancellationToken cancellationToken)
        {
            var retVal = new List <Coordinate>();

            switch (coordinates.Count)
            {
            case 0:
                return(retVal);

            case 1:
                retVal.Add(coordinates[0]);

                return(retVal);

            default:
                retVal.Add(coordinates[0]);

                break;
            }

            var curStartingIdx     = 0;
            var ptsSinceLastReport = 0;

            for (var idx = 1; idx < coordinates.Count; idx++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }

                ptsSinceLastReport++;

                if (ptsSinceLastReport >= ReportingInterval)
                {
                    OnReportingInterval(ptsSinceLastReport);
                    ptsSinceLastReport -= ReportingInterval;
                }

                var mostRecentDistance = GeoExtensions
                                         .GetDistance(coordinates[idx - 1], coordinates[idx]);

                var distanceFromOrigin = GeoExtensions
                                         .GetDistance(coordinates[curStartingIdx], coordinates[idx]);

                if (mostRecentDistance <= Configuration.MaxSeparation &&
                    distanceFromOrigin <= Configuration.MaxDistanceMultiplier * Configuration.MaxSeparation)
                {
                    continue;
                }

                retVal.Add(coordinates[idx]);
                curStartingIdx = idx;
            }

            return(retVal);
        }
        private List <Coordinate> InterpolatePoints(LinkedList <Coordinate> nodes)
        {
            var retVal = new List <Coordinate>();

            Coordinate?prevPt = null;

            foreach (var curPt in nodes)
            {
                if (prevPt == null)
                {
                    retVal.Add(curPt);
                    prevPt = curPt;

                    continue;
                }

                var distance = GeoExtensions.GetDistance(prevPt, curPt);

                if (distance <= Configuration.MaxSeparation)
                {
                    retVal.Add(curPt);
                    prevPt = curPt;

                    continue;
                }

                // interpolate
                var numPtsNeeded = Convert.ToInt32(
                    Math.Ceiling(distance.GetValue(Configuration.MaxSeparation.Unit) /
                                 Configuration.MaxSeparation.OriginalValue));

                var deltaLat  = (curPt.Latitude - prevPt.Latitude) / numPtsNeeded;
                var deltaLong = (curPt.Longitude - prevPt.Longitude) / numPtsNeeded;

                for (var idx = 0; idx < numPtsNeeded; idx++)
                {
                    retVal.Add(new Coordinate
                    {
                        Latitude  = prevPt.Latitude + (idx + 1) * deltaLat,
                        Longitude = prevPt.Longitude + (idx + 1) * deltaLong
                    });
                }

                prevPt = curPt;
            }

            return(retVal);
        }