/// <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> /// 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; }
/// <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); }