private void mergeFlowDirectionNetworkTrace(routeoptiontype rotype)
        {
            IPosition FDir  = null;
            IPosition first = null;

            try
            {
                if (!route.Features.ContainsKey(getFeatureName(rotype, navigationfeaturetype.e_fdrroute)) ||
                    !route.Features.ContainsKey(getFeatureName(rotype, navigationfeaturetype.e_traceroute) + "0"))
                {
                    throw new Exception("Either flow direction or network trace is not available.");
                }

                FDir  = ((LineString)route.Features[getFeatureName(rotype, navigationfeaturetype.e_fdrroute)].Geometry).Coordinates.Last();
                first = ((LineString)route.Features[getFeatureName(rotype, navigationfeaturetype.e_traceroute) + "0"].Geometry).Coordinates.First();

                LineString merge = new LineString(new List <IPosition>()
                {
                    FDir, first
                });
                route.Features.Add(getFeatureName(rotype, navigationfeaturetype.e_connection), new Feature(merge));
            }
            catch (Exception ex)
            {
                sm("Error Merging Flow direction trace with network trace " + ex.Message, MessageType.warning);
                return;
            }
        }
        private bool loadFlowDirectionTrace(routeoptiontype rotype)
        {
            try
            {
                Feature startpoint    = route.Features[getFeatureName(rotype, navigationfeaturetype.e_point)];
                Feature catchmentMask = route.Features[getFeatureName(rotype, navigationfeaturetype.e_catchment)];

                Feature fldrTrace = this.ssAgent.GetFDirTraceAsync(startpoint, catchmentMask);


                if (fldrTrace == null)
                {
                    throw new Exception("Flow direction trace object null.");
                }

                if (IncludeVAA)
                {
                    LoadVAAProperties(new List <Feature>()
                    {
                        fldrTrace
                    });
                }

                addRouteFeature(getFeatureName(rotype, navigationfeaturetype.e_fdrroute), fldrTrace);

                return(true);
            }
            catch (Exception ex)
            {
                sm("Error loading Flow direction trace " + ex.Message, MessageType.error);
                return(false);
            }
        }
        private bool loadCatchment(routeoptiontype rotype)
        {
            try
            {
                Point             startpoint     = ((Point)route.Features[getFeatureName(rotype, navigationfeaturetype.e_point)].Geometry);
                FeatureCollection localCatchment = this.nldiAgent.GetLocalCatchmentAsync(startpoint);

                if (localCatchment == null)
                {
                    throw new Exception(String.Format("nldi failed to return catchment. X {0}, Y {1}", startpoint.Coordinates.Longitude, startpoint.Coordinates.Latitude));
                }
                var comid = localCatchment.Features.FirstOrDefault().Properties["featureid"].ToString();
                if (string.IsNullOrEmpty(comid))
                {
                    throw new Exception(String.Format("nldi catchment does not contain property featureid X {0}, Y {1}", startpoint.Coordinates.Longitude, startpoint.Coordinates.Latitude));
                }
                this.route.ComID = comid;
                addRouteFeature(getFeatureName(rotype, navigationfeaturetype.e_catchment), localCatchment.Features.FirstOrDefault());
                sm("Catchement valid, ComID: " + comid);
                return(true);
            }
            catch (Exception ex)
            {
                sm("Catchement invalid " + ex.Message, MessageType.error);
                return(false);
            }
        }
        private string getRouteOptionName(routeoptiontype roType)
        {
            switch (roType)
            {
            case  routeoptiontype.e_start: return("start");

            case routeoptiontype.e_end: return("end");

            default: return("");
            }//end switch
        }
        private bool loadNetworkTrace(routeoptiontype rotype, NavigationOption.directiontype tracetype = NavigationOption.directiontype.downstream, double?distance = null, NavigationOption.querysourcetype source = NavigationOption.querysourcetype.flowline)
        {
            try
            {
                List <Feature>    traceItems = null;
                string            nameprefix = "";
                FeatureCollection traceFC    = this.nldiAgent2.GetNavigateAsync(this.route.ComID, (NLDIServiceAgent.navigateType)tracetype, distance, (NLDIServiceAgent.querysourceType)source);

                if (traceFC == null)
                {
                    throw new Exception("Network trace from nldi agent is null. ComID: " + this.route.ComID);
                }
                if (source == NavigationOption.querysourcetype.flowline)
                {
                    traceItems = traceFC.Features.Where(f => !String.Equals(f.Properties["nhdplus_comid"]?.ToString(), this.route.ComID)).ToList();
                    nameprefix = getFeatureName(rotype, navigationfeaturetype.e_traceroute);

                    if (IncludeVAA)
                    {
                        LoadVAAProperties(traceItems);
                    }
                }
                else
                {
                    traceItems = traceFC.Features;
                    nameprefix = source.ToString();
                }

                for (int i = 0; i < traceItems.Count(); i++)
                {
                    addRouteFeature(nameprefix + i, traceItems[i]);
                }//next item

                return(true);
            }
            catch (Exception ex)
            {
                sm("Error loading Network trace " + ex.Message, MessageType.error);
                return(false);
            }
        }
        private void loadFlowPath(routeoptiontype rotype = routeoptiontype.e_start)
        {
            if (!loadCatchment(rotype))
            {
                throw new Exception("Catchment failed to load.");
            }
            if (!loadFlowDirectionTrace(rotype))
            {
                Console.WriteLine("FlowDirection failed to trace.");
            }

            if (!loadNetworkTrace(rotype, distance: distanceLimit))
            {
                Console.WriteLine("FlowDirection failed to trace.");
            }
            mergeFlowDirectionNetworkTrace(rotype);

            if (route.Configuration.FirstOrDefault(x => x.ID == (int)NavigationOption.navigationoptiontype.e_trunkatingpolygon) != null)
            {
            }
        }
        private string getFeatureName(routeoptiontype roType, navigationfeaturetype ftype)
        {
            string name = "";

            switch (ftype)
            {
            case navigationfeaturetype.e_catchment:
                name = "catchment";
                break;

            case navigationfeaturetype.e_point:
                name = "point";
                break;

            case navigationfeaturetype.e_fdrroute:
                name = "flow_direction_route";
                break;

            case navigationfeaturetype.e_traceroute:
                name = "trace_route";
                break;

            case navigationfeaturetype.e_connection:
                name = "connection";
                break;

            case navigationfeaturetype.e_query:
                name = "query";
                break;

            default:
                name = "notspecified";
                break;
            }//end switch
            return(getFeatureOrder(ftype) + getRouteOptionName(roType) + "_" + name);
        }