/// <summary>
        /// Does objects reverse geocoding.
        /// </summary>
        /// <param name="objects">Objects to geocoding.</param>
        private void _ReverseGeocode(IList <AppData.DataObject> objects)
        {
            Debug.Assert(null != objects);   // created
            Debug.Assert(0 < objects.Count); // not empty
            Debug.Assert(null != _checker);  // inited

            AppGeometry.Envelope extent = App.Current.Map.ImportCheckExtent;

            int count = objects.Count;

            for (int index = 0; index < count; ++index)
            {
                _checker.ThrowIfCancellationRequested();

                if (null == _detectedException)
                {   // NOTE: do if geocoder in valid state
                    IGeocodable geocodable = _GetGeocodable(objects[index]);
                    if (geocodable.GeoLocation.HasValue)
                    {
                        if (extent.IsPointIn(geocodable.GeoLocation.Value))
                        {   // reverse geocode
                            Address geocodedAddress =
                                _ReverseGeocodeSave(geocodable.GeoLocation.Value);
                            if (null != geocodedAddress)
                            {
                                geocodedAddress.CopyTo(geocodable.Address);
                                ++_geocodedCount;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Create extent envelope
        /// </summary>
        /// <param name="envelope">Extent envelope in WGS84</param>
        /// <param name="spatialReferenceID">Map spatial reference ID</param>
        /// <returns>Extent envelope in map spatial reference</returns>
        public static ESRI.ArcGIS.Client.Geometry.Envelope CreateExtent(ESRI.ArcLogistics.Geometry.Envelope envelope,
                                                                        int?spatialReferenceID)
        {
            // Project extent to map spatial reference
            ESRI.ArcLogistics.Geometry.Point leftTop     = new ESRI.ArcLogistics.Geometry.Point(envelope.left, envelope.top);
            ESRI.ArcLogistics.Geometry.Point rightBottom = new ESRI.ArcLogistics.Geometry.Point(envelope.right, envelope.bottom);

            // Project point from WGS84 to Web Mercator if spatial reference of map is Web Mercator
            if (spatialReferenceID.HasValue)
            {
                leftTop     = WebMercatorUtil.ProjectPointToWebMercator(leftTop, spatialReferenceID.Value);
                rightBottom = WebMercatorUtil.ProjectPointToWebMercator(rightBottom, spatialReferenceID.Value);
            }

            // Create map extent envelope
            ESRI.ArcGIS.Client.Geometry.Envelope extent = new ESRI.ArcGIS.Client.Geometry.Envelope();

            extent.XMin = leftTop.X;
            extent.XMax = rightBottom.X;
            extent.YMin = rightBottom.Y;
            extent.YMax = leftTop.Y;

            // Project point from WGS84 to Web Mercator if spatial reference of map is Web Mercator
            if (spatialReferenceID.HasValue)
            {
                extent.SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(spatialReferenceID.Value);
            }

            return(extent);
        }
        /// <summary>
        /// Does validate object.
        /// </summary>
        /// <param name="obj">Object to validation.</param>
        private void _ValidateObject(AppData.DataObject obj)
        {
            Debug.Assert(null != obj); // created

            // check geocoded point in map extent
            var geocodable = obj as IGeocodable;

            if ((null != geocodable) &&
                geocodable.IsGeocoded)
            {
                AppGeometry.Envelope extent = App.Current.Map.ImportCheckExtent;
                // geolocation is not valide
                if (!extent.IsPointIn(geocodable.GeoLocation.Value))
                {
                    // reset geolocation
                    geocodable.GeoLocation         = null;
                    geocodable.Address.MatchMethod = string.Empty;
                    // store problem description
                    string extendedFormat =
                        App.Current.FindString("ImportProcessStatusRecordOutMapExtendFormat");
                    string errorTextFormat =
                        string.Format(GEOCODE_MESSAGE_FORMAT, _objectsName, extendedFormat);
                    _details.Add(new MessageDetail(MessageType.Warning, errorTextFormat, obj));
                }
            }

            _StoreValidateResult(obj);
        }
        /// <summary>
        /// Check is location of geocodable object valid and replace it by candidate from local
        /// geocoder if exists.
        /// </summary>
        /// <param name="geocodable">Geocodable object to check.</param>
        /// <returns>Is geocodable object valid.</returns>
        private bool _SourceGeocodedObject(IGeocodable geocodable)
        {
            Debug.Assert(null != geocodable); // created

            bool isObjectGeocoded = false;

            // First check if name address pair exists in local geocoder database.
            // If exists - overwrite geolocation and address from it.
            App currentApp    = App.Current;
            var localGeocoder =
                new LocalGeocoder(currentApp.Geocoder, currentApp.NameAddressStorage);

            var nameAddress = new NameAddress();

            nameAddress.Name    = geocodable.ToString();
            nameAddress.Address = geocodable.Address.Clone() as Address;

            AddressCandidate localCandidate = localGeocoder.Geocode(nameAddress);

            if (localCandidate == null)
            {   // Update from internal object information.
                AppGeometry.Envelope extent = currentApp.Map.ImportCheckExtent;
                if (extent.IsPointIn(geocodable.GeoLocation.Value))
                {
                    geocodable.Address.MatchMethod =
                        currentApp.FindString("ImportSourceMatchMethod");
                    isObjectGeocoded = true;

                    // Full address property must be combined from other fields, because
                    // it is not importing field.
                    if (App.Current.Geocoder.AddressFormat == AddressFormat.MultipleFields)
                    {
                        GeocodeHelpers.SetFullAddress(geocodable.Address);
                    }
                    else
                    {
                        // Do nothing: do not update full address since
                        // it is used for geocoding in Single Address Field Format.
                    }
                }
                // Else could not locate object using X/Y attributes - need geocode.
            }
            else
            {   // Init from local candidate.
                // Set location.
                geocodable.GeoLocation = new AppGeometry.Point(localCandidate.GeoLocation.X,
                                                               localCandidate.GeoLocation.Y);
                // Set address.
                localCandidate.Address.CopyTo(geocodable.Address);

                isObjectGeocoded = true;
            }

            return(isObjectGeocoded);
        }
        /// <summary>
        /// Zoom to candidate depends on locator type.
        /// </summary>
        /// <param name="mapCtrl">Map control.</param>
        /// <param name="addressCandidate">Candidate to zoom.</param>
        /// <param name="locatorType">Type of locator, which return this candidate.</param>
        private static void _ZoomToCandidate(MapControl mapCtrl, AddressCandidate addressCandidate, LocatorType locatorType)
        {
            Debug.Assert(mapCtrl != null);
            Debug.Assert(addressCandidate != null);

            double extentInc = 0;

            // Get extent size.
            switch (locatorType)
            {
            case LocatorType.CityState:
            {
                extentInc = ZOOM_ON_CITY_STATE_CANDIDATE;
                break;
            }

            case LocatorType.Zip:
            {
                extentInc = ZOOM_ON_ZIP_CANDIDATE;
                break;
            }

            case LocatorType.Street:
            {
                extentInc = ZOOM_ON_STREET_CANDIDATE;
                break;
            }

            default:
            {
                Debug.Assert(false);
                break;
            }
            }

            // Make extent rectangle.
            ESRI.ArcLogistics.Geometry.Envelope rect = new ESRI.ArcLogistics.Geometry.Envelope();
            rect.SetEmpty();
            rect.Union(addressCandidate.GeoLocation);

            rect.left   -= extentInc;
            rect.right  += extentInc;
            rect.top    += extentInc;
            rect.bottom -= extentInc;

            ESRI.ArcGIS.Client.Geometry.Envelope extent = GeometryHelper.CreateExtent(rect,
                                                                                      mapCtrl.Map.SpatialReferenceID);
            mapCtrl.ZoomTo(extent);
        }
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Get rect from extent envelope
        /// </summary>
        /// <param name="envelope">Extent envelope in map spatial reference</param>
        /// <param name="spatialReferenceID">Map spatial reference ID</param>
        /// <returns>Extent envelope in WGS84</returns>
        public static ESRI.ArcLogistics.Geometry.Envelope CreateRect(ESRI.ArcGIS.Client.Geometry.Envelope env,
                                                                     int?spatialReferenceID)
        {
            // Project extent to map spatial reference
            ESRI.ArcLogistics.Geometry.Point leftTop     = new ESRI.ArcLogistics.Geometry.Point(env.XMin, env.YMax);
            ESRI.ArcLogistics.Geometry.Point rightBottom = new ESRI.ArcLogistics.Geometry.Point(env.XMax, env.YMin);

            // Project point from Web Mercator to WGS84 if spatial reference of map is Web Mercator
            if (spatialReferenceID.HasValue)
            {
                leftTop     = WebMercatorUtil.ProjectPointFromWebMercator(leftTop, spatialReferenceID.Value);
                rightBottom = WebMercatorUtil.ProjectPointFromWebMercator(rightBottom, spatialReferenceID.Value);
            }

            ESRI.ArcLogistics.Geometry.Envelope rect = new ESRI.ArcLogistics.Geometry.Envelope(
                leftTop.X, leftTop.Y, rightBottom.X, rightBottom.Y);

            return(rect);
        }
        /// <summary>
        /// Get extent for point collection.
        /// </summary>
        /// <param name="points">Points.</param>
        /// <returns>Envelope, which contains all points.</returns>
        public static ESRI.ArcLogistics.Geometry.Envelope? GetCollectionExtent(IList<ESRI.ArcLogistics.Geometry.Point> points)
        {
            ESRI.ArcLogistics.Geometry.Envelope? result = null;

            if (points.Count > 0)
            {
                ESRI.ArcLogistics.Geometry.Envelope rect = new ESRI.ArcLogistics.Geometry.Envelope();
                rect.SetEmpty();

                bool atLeastOnePointHavePosition = false;
                foreach (ESRI.ArcLogistics.Geometry.Point point in points)
                {
                    rect.Union(point);
                    atLeastOnePointHavePosition = true;
                }

                if (atLeastOnePointHavePosition)
                {
                    // Increase extent.
                    double heigthInc = EXTENT_INDENT * rect.Height;
                    double widthInc = EXTENT_INDENT * rect.Width;
                    if (heigthInc == 0)
                    {
                        heigthInc = ZOOM_ON_STREET;
                    }
                    if (widthInc == 0)
                    {
                        widthInc = ZOOM_ON_STREET;
                    }

                    rect.left -= widthInc;
                    rect.right += widthInc;
                    rect.top += heigthInc;
                    rect.bottom -= heigthInc;

                    result = rect;
                }
            }

            return result;
        }
        /// <summary>
        /// Get extent for point collection.
        /// </summary>
        /// <param name="points">Points.</param>
        /// <returns>Envelope, which contains all points.</returns>
        public static ESRI.ArcLogistics.Geometry.Envelope? GetCollectionExtent(IList <ESRI.ArcLogistics.Geometry.Point> points)
        {
            ESRI.ArcLogistics.Geometry.Envelope?result = null;

            if (points.Count > 0)
            {
                ESRI.ArcLogistics.Geometry.Envelope rect = new ESRI.ArcLogistics.Geometry.Envelope();
                rect.SetEmpty();

                bool atLeastOnePointHavePosition = false;
                foreach (ESRI.ArcLogistics.Geometry.Point point in points)
                {
                    rect.Union(point);
                    atLeastOnePointHavePosition = true;
                }

                if (atLeastOnePointHavePosition)
                {
                    // Increase extent.
                    double heigthInc = EXTENT_INDENT * rect.Height;
                    double widthInc  = EXTENT_INDENT * rect.Width;
                    if (heigthInc == 0)
                    {
                        heigthInc = ZOOM_ON_STREET;
                    }
                    if (widthInc == 0)
                    {
                        widthInc = ZOOM_ON_STREET;
                    }

                    rect.left   -= widthInc;
                    rect.right  += widthInc;
                    rect.top    += heigthInc;
                    rect.bottom -= heigthInc;

                    result = rect;
                }
            }

            return(result);
        }
        /// <summary>
        /// Is stop in rect.
        /// </summary>
        /// <param name="stop">Stop, path to which is try to intersect.</param>
        /// <param name="rect">Extent.</param>
        /// <returns>Is stop in rect.</returns>
        private static bool _IsStopInRect(Stop stop, Envelope rect)
        {
            for (int index = 0; index < stop.Path.Groups.Length; index++)
            {
                Point[] points = stop.Path.GetGroupPoints(index);
                for (int pointIndex = 0; pointIndex < points.Length - 1; pointIndex++)
                {
                    if (_IsLineIntersectsWithRect(rect, points[pointIndex], points[pointIndex + 1]))
                        return true;
                }
            }

            return false;
        }
        /// <summary>
        /// Find stops, that goes after intersection of true route schedule routes and rect. 
        /// </summary>
        /// <param name="rect">Extent.</param>
        /// <param name="routeStops">Route stops array, sorted by sequence number.</param>
        /// <param name="stops">Finded nearest stops.</param>
        private static bool _AddStopsInExtentOnTrueRoute(Envelope rect, List<Stop> routeStops, List<Stop> stops)
        {
            bool trueRouteExists = false;

            foreach (Stop stop in routeStops)
            {
                if (stop.Path != null && !stop.Path.IsEmpty)
                {
                    trueRouteExists = true;

                    if (_IsStopInRect(stop, rect))
                    {
                        stops.Add(stop);
                    }
                }
            }

            return trueRouteExists;
        }
        /// <summary>
        /// Find stops, that goes after intersection of straight schedule routes and rect.
        /// </summary>
        /// <param name="rect">Extent.</param>
        /// <param name="routeStops">Route stops array, sorted by sequence number.</param>
        /// <param name="stops">Finded nearest stops.</param>
        private static void _AddStopsInExtentOnStraightRoute(Envelope rect, List<Stop> routeStops, List<Stop> stops)
        {
            Point startPoint = routeStops[0].MapLocation.Value;
            for (int stopIndex = 1; stopIndex < routeStops.Count; stopIndex++)
            {
                Stop stop = routeStops[stopIndex];
                if (stop.MapLocation != null)
                {
                    Point endPoint = stop.MapLocation.Value;

                    if (_IsLineIntersectsWithRect(rect, startPoint, endPoint))
                    {
                        stops.Add(stop);
                    }

                    startPoint = endPoint;
                }
            }
        }
        /// <summary>
        /// Is line intersects with extent.
        /// Implementation of Cohen-Sutherland algorithm.
        /// </summary>
        /// <param name="extent">Extent.</param>
        /// <param name="startPoint">Line start.</param>
        /// <param name="endPoint">Line end.</param>
        /// <returns>Is line intersects with extent.</returns>
        public static bool _IsLineIntersectsWithRect(Envelope extent, Point startPoint, Point endPoint)
        {
            ESRI.ArcGIS.Client.Geometry.MapPoint start = new ESRI.ArcGIS.Client.Geometry.MapPoint(startPoint.X, startPoint.Y);
            ESRI.ArcGIS.Client.Geometry.MapPoint end = new ESRI.ArcGIS.Client.Geometry.MapPoint(endPoint.X, endPoint.Y);

            ESRI.ArcGIS.Client.Geometry.Envelope rect = new ESRI.ArcGIS.Client.Geometry.Envelope(
                extent.left, extent.top, extent.right, extent.bottom);

            int code_a, code_b, code;
            ESRI.ArcGIS.Client.Geometry.MapPoint temp;

            code_a = _GetPointCode(rect, start);
            code_b = _GetPointCode(rect, end);

            while (code_a > 0 || code_b > 0)
            {
                // If both points on one side, than line does not intersects extent.
                if ((code_a & code_b) > 0)
                    return false;

                if (code_a > 0)
                {
                    code = code_a;
                    temp = start;
                }
                else
                {
                    code = code_b;
                    temp = end;
                }

                if ((code & LEFT_CODE) > 0)
                {
                    temp.Y = temp.Y + (start.Y - end.Y) * (rect.XMin - temp.X) / (start.X - end.X);
                    temp.X = rect.XMin;
                }
                else if ((code & RIGHT_CODE) > 0)
                {
                    temp.Y += (start.Y - end.Y) * (rect.XMax - temp.X) / (start.X - end.X);
                    temp.X = rect.XMax;
                }

                if ((code & BOTTOM_CODE) > 0)
                {
                    temp.X += (start.X - end.X) * (rect.YMin - temp.Y) / (start.Y - end.Y);
                    temp.Y = rect.YMin;
                }
                else if ((code & TOP_CODE) > 0)
                {
                    temp.X += (start.X - end.X) * (rect.YMax - temp.Y) / (start.Y - end.Y);
                    temp.Y = rect.YMax;
                }

                if (code == code_a)
                    code_a = _GetPointCode(rect, start);
                else
                    code_b = _GetPointCode(rect, end);
            }

            return true;
        }
        /// <summary>
        /// Find stops, that goes after intersection of schedule routes and rect.
        /// </summary>
        /// <param name="schedule">Schedule with routes array.</param>
        /// <param name="rect">Extent.</param>
        /// <returns>Nearest stops.</returns>
        public static IList<Stop> FindNearestPreviousStops(Schedule schedule, Envelope rect)
        {
            List<Stop> stops = new List<Stop>();

            foreach (Route route in schedule.Routes)
            {
                List<Stop> routeStops = CommonHelpers.GetSortedStops(route);

                if (routeStops.Count > 0)
                {
                    bool trueRouteExists = false;
                    if (App.Current.MapDisplay.TrueRoute)
                    {
                        trueRouteExists = _AddStopsInExtentOnTrueRoute(rect, routeStops, stops);
                    }

                    if (!App.Current.MapDisplay.TrueRoute || !trueRouteExists)
                    {
                        _AddStopsInExtentOnStraightRoute(rect, routeStops, stops);
                    }
                }
            }

            return stops;
        }
        /// <summary>
        /// Get extent near point.
        /// </summary>
        /// <param name="position">Dropping position.</param>
        /// <returns>Extent near point.</returns>
        private Envelope _GetExtentNearDroppedPoint(System.Windows.Point position)
        {
            Debug.Assert(_mapView != null);

            System.Windows.Point leftTopPoint = new System.Windows.Point(position.X - ROUTE_WIDTH, position.Y + ROUTE_WIDTH);
            System.Windows.Point rightBottomPoint = new System.Windows.Point(position.X + ROUTE_WIDTH, position.Y - ROUTE_WIDTH);
            ESRI.ArcGIS.Client.Geometry.MapPoint leftTopMapPoint = _mapView.mapCtrl.map.ScreenToMap(leftTopPoint);
            ESRI.ArcGIS.Client.Geometry.MapPoint rightBottomMapPoint = _mapView.mapCtrl.map.ScreenToMap(rightBottomPoint);

            ESRI.ArcLogistics.Geometry.Point leftTopPointOnMap = new ESRI.ArcLogistics.Geometry.Point(
                leftTopMapPoint.X, leftTopMapPoint.Y);
            ESRI.ArcLogistics.Geometry.Point rightBottomPointOnMap = new ESRI.ArcLogistics.Geometry.Point(
                rightBottomMapPoint.X, rightBottomMapPoint.Y);

            // Project point from Web Mercator to WGS84 if spatial reference of map is Web Mercator.
            if (_mapView.mapCtrl.Map.SpatialReferenceID.HasValue)
            {
                leftTopPointOnMap = WebMercatorUtil.ProjectPointFromWebMercator(leftTopPointOnMap,
                    _mapView.mapCtrl.Map.SpatialReferenceID.Value);
                rightBottomPointOnMap = WebMercatorUtil.ProjectPointFromWebMercator(rightBottomPointOnMap,
                    _mapView.mapCtrl.Map.SpatialReferenceID.Value);
            }

            Envelope extent = new Envelope(leftTopPointOnMap.X, leftTopPointOnMap.Y,
                rightBottomPointOnMap.X, rightBottomPointOnMap.Y);
            return extent;
        }
        /// <summary>
        /// Gets string of image display parameter.
        /// </summary>
        /// <param name="extent">Map extent.</param>
        /// <returns>String of image display parameter.</returns>
        private string _GetImageDisplayParameter(GPEnvelope extent)
        {
            Debug.Assert(extent != null);

            string result = string.Empty;

            try
            {
                // Create evelope of map extent.
                Envelope env = new Envelope(Convert.ToDouble(extent.XMin),
                    Convert.ToDouble(extent.YMax),
                    Convert.ToDouble(extent.XMax),
                    Convert.ToDouble(extent.YMin));

                // Get actual width and heigth.
                int width = Convert.ToInt32(env.Width);
                int height = Convert.ToInt32(env.Height);

                // Format result.
                result = string.Format(IMAGE_DISPLAY_PARAMETER_FORMAT, width, height);
            }
            catch (InvalidCastException ex)
            {
                throw new RouteException(
                    Properties.Messages.Error_GetDiscoveryServiceConfigFailed, ex);
            }

            return result;
        }
        /// <summary>
        /// Creates route path geometry.
        /// </summary>
        /// <param name="route">Route to get points.</param>
        /// <param name="sortedRouteStops">Stops as points source.</param>
        /// <param name="extent">Map image extent.</param>
        /// <param name="width">Image width.</param>
        /// <param name="height">Image height.</param>
        /// <returns>Created path geometry by stop point.</returns>
        private PathGeometry _CreatePath(Route route,
                                         IList<Stop> sortedRouteStops,
                                         Envelope extent,
                                         double width,
                                         double height)
        {
            Debug.Assert(null != route);
            Debug.Assert(null != sortedRouteStops);
            Debug.Assert(null != extent);
            Debug.Assert(0 < width);
            Debug.Assert(0 < height);

            var pathFigure = new PathFigure();

            int startIndex = _GetStartIndex(route, sortedRouteStops);
            int processCount = _GetProcessStopCount(route, sortedRouteStops);

            bool isStartFound = false;
            for (int index = startIndex; index < processCount; ++index)
            {
                Stop stop = sortedRouteStops[index];
                if (!stop.MapLocation.HasValue)
                {
                    continue; // NOTE: skip empty
                }

                // not show path to first stop
                if (isStartFound &&
                    (stop.Path != null) &&
                    !stop.Path.IsEmpty)
                {
                    for (int pointsIndex = 0; pointsIndex < stop.Path.Groups.Length; ++pointsIndex)
                    {
                        AppGeometry.Point[] pointsArray =
                            stop.Path.GetGroupPoints(pointsIndex);

                        foreach (AppGeometry.Point point in pointsArray)
                        {
                            SysWindows.Point segmentPoint =
                                _ConvertPoint(point, (EnvelopeN)extent, width, height);

                            var segment = new LineSegment(segmentPoint, true);
                            pathFigure.Segments.Add(segment);
                        }
                    }
                }

                if (!isStartFound &&
                    stop.MapLocation.HasValue)
                {
                    // init figure start point
                    pathFigure.StartPoint =
                        _ConvertPoint(stop.MapLocation.Value, (EnvelopeN)extent, width, height);
                    pathFigure.IsClosed = false;

                    isStartFound = true;
                }
            }

            var pathGeometry = new PathGeometry();
            pathGeometry.Figures.Add(pathFigure);

            return pathGeometry;
        }
        /// <summary>
        /// Zoom to candidate depends on locator type.
        /// </summary>
        /// <param name="mapCtrl">Map control.</param>
        /// <param name="addressCandidate">Candidate to zoom.</param>
        /// <param name="locatorType">Type of locator, which return this candidate.</param>
        private static void _ZoomToCandidate(MapControl mapCtrl, AddressCandidate addressCandidate, LocatorType locatorType)
        {
            Debug.Assert(mapCtrl != null);
            Debug.Assert(addressCandidate != null);

            double extentInc = 0;

            // Get extent size.
            switch (locatorType)
            {
                case LocatorType.CityState:
                    {
                        extentInc = ZOOM_ON_CITY_STATE_CANDIDATE;
                        break;
                    }
                case LocatorType.Zip:
                    {
                        extentInc = ZOOM_ON_ZIP_CANDIDATE;
                        break;
                    }
                case LocatorType.Street:
                    {
                        extentInc = ZOOM_ON_STREET_CANDIDATE;
                        break;
                    }
                default:
                    {
                        Debug.Assert(false);
                        break;
                    }
            }

            // Make extent rectangle.
            ESRI.ArcLogistics.Geometry.Envelope rect = new ESRI.ArcLogistics.Geometry.Envelope();
            rect.SetEmpty();
            rect.Union(addressCandidate.GeoLocation);

            rect.left -= extentInc;
            rect.right += extentInc;
            rect.top += extentInc;
            rect.bottom -= extentInc;

            ESRI.ArcGIS.Client.Geometry.Envelope extent = GeometryHelper.CreateExtent(rect,
                mapCtrl.Map.SpatialReferenceID);
            mapCtrl.ZoomTo(extent);
        }
        /// <summary>
        /// Gets map extent for route.
        /// </summary>
        /// <param name="route">Route to getting points.</param>
        /// <param name="sortedRouteStops">Sorted stops from route.</param>
        /// <returns>Map extent for route (all points on map).</returns>
        private EnvelopeN _GetExtent(Route route, IList<Stop> sortedRouteStops)
        {
            Debug.Assert(null != route);
            Debug.Assert(null != sortedRouteStops);

            int spatialRefId = _mapInfo.SpatialReference.WKID;

            int startIndex = _GetStartIndex(route, sortedRouteStops);
            int processCount = _GetProcessStopCount(route, sortedRouteStops);

            var points = new List<AppGeometry.Point>();
            bool isStartFound = false;
            for (int stopIndex = startIndex; stopIndex < processCount; ++stopIndex)
            {
                Stop stop = sortedRouteStops[stopIndex];

                // NOTE: path to first stop not showing
                if (isStartFound &&
                    (null != stop.Path) &&
                    !stop.Path.IsEmpty)
                {
                    for (int index = 0; index < stop.Path.Groups.Length; ++index)
                    {
                        AppGeometry.Point[] pointsArray = stop.Path.GetGroupPoints(index);
                        foreach (AppGeometry.Point point in pointsArray)
                        {
                            AppGeometry.Point pt =
                                WebMercatorUtil.ProjectPointToWebMercator(point, spatialRefId);
                            points.Add(pt);
                        }
                    }
                }

                if (stop.MapLocation.HasValue)
                {
                    AppGeometry.Point location = stop.MapLocation.Value;
                    AppGeometry.Point loc =
                        WebMercatorUtil.ProjectPointToWebMercator(location, spatialRefId);
                    points.Add(loc);

                    if (!isStartFound)
                    {
                        isStartFound = true;
                    }
                }
            }

            var rect = new AppGeometry.Envelope();
            rect.SetEmpty();
            foreach (AppGeometry.Point point in points)
                rect.Union(point);

            // increase extent
            double heightInc = ROUTE_EXTENT_INDENT * rect.Height;
            if (heightInc == 0)
                heightInc = ROUTE_EXTENT_INDENT;
            double widthInc = ROUTE_EXTENT_INDENT * rect.Width;
            if (widthInc == 0)
                widthInc = ROUTE_EXTENT_INDENT;

            rect.left -= widthInc;
            rect.right += widthInc;
            rect.top += heightInc;
            rect.bottom -= heightInc;

            var extent = new EnvelopeN();
            extent.XMax = rect.right;
            extent.XMin = rect.left;
            extent.YMax = rect.top;
            extent.YMin = rect.bottom;

            return extent;
        }
Exemple #19
0
        /// <summary>
        /// Gets map extent for route.
        /// </summary>
        /// <param name="route">Route to getting points.</param>
        /// <param name="sortedRouteStops">Sorted stops from route.</param>
        /// <returns>Map extent for route (all points on map).</returns>
        private EnvelopeN _GetExtent(Route route, IList <Stop> sortedRouteStops)
        {
            Debug.Assert(null != route);
            Debug.Assert(null != sortedRouteStops);

            int spatialRefId = _mapInfo.SpatialReference.WKID;

            int startIndex   = _GetStartIndex(route, sortedRouteStops);
            int processCount = _GetProcessStopCount(route, sortedRouteStops);

            var  points       = new List <AppGeometry.Point>();
            bool isStartFound = false;

            for (int stopIndex = startIndex; stopIndex < processCount; ++stopIndex)
            {
                Stop stop = sortedRouteStops[stopIndex];

                // NOTE: path to first stop not showing
                if (isStartFound &&
                    (null != stop.Path) &&
                    !stop.Path.IsEmpty)
                {
                    for (int index = 0; index < stop.Path.Groups.Length; ++index)
                    {
                        AppGeometry.Point[] pointsArray = stop.Path.GetGroupPoints(index);
                        foreach (AppGeometry.Point point in pointsArray)
                        {
                            AppGeometry.Point pt =
                                WebMercatorUtil.ProjectPointToWebMercator(point, spatialRefId);
                            points.Add(pt);
                        }
                    }
                }

                if (stop.MapLocation.HasValue)
                {
                    AppGeometry.Point location = stop.MapLocation.Value;
                    AppGeometry.Point loc      =
                        WebMercatorUtil.ProjectPointToWebMercator(location, spatialRefId);
                    points.Add(loc);

                    if (!isStartFound)
                    {
                        isStartFound = true;
                    }
                }
            }

            var rect = new AppGeometry.Envelope();

            rect.SetEmpty();
            foreach (AppGeometry.Point point in points)
            {
                rect.Union(point);
            }

            // increase extent
            double heightInc = ROUTE_EXTENT_INDENT * rect.Height;

            if (heightInc == 0)
            {
                heightInc = ROUTE_EXTENT_INDENT;
            }
            double widthInc = ROUTE_EXTENT_INDENT * rect.Width;

            if (widthInc == 0)
            {
                widthInc = ROUTE_EXTENT_INDENT;
            }

            rect.left   -= widthInc;
            rect.right  += widthInc;
            rect.top    += heightInc;
            rect.bottom -= heightInc;

            var extent = new EnvelopeN();

            extent.XMax = rect.right;
            extent.XMin = rect.left;
            extent.YMax = rect.top;
            extent.YMin = rect.bottom;

            return(extent);
        }