/// <summary> /// Converts the specified find address candidate response object to an address candidate /// object. /// </summary> /// <param name="response">The instance of the find address candidate response /// to be converted.</param> /// <returns>A new <see cref="AddressCandidate"/> object based on information from /// the response.</returns> private AddressCandidate _Convert(FindAddressCandidateResponse response) { if (response == null || response.Score == null || response.Address == null || response.Location == null || response.Extent == null) { return(null); } var result = new AddressCandidate { // Convert candidate match score. Score = response.Score.GetValueOrDefault(), // Convert candidate address. Address = new Address { FullAddress = response.Address, }, // Convert candidate geolocation. GeoLocation = new Geometry.Point { X = response.Location.X, Y = response.Location.Y, } }; return(result); }
private CandidateGraphicObject(AddressCandidate candidate) : base(candidate) { _candidate = candidate; _candidate.PropertyChanged += new PropertyChangedEventHandler(_candidate_PropertyChanged); Geometry = _CreatePoint(candidate); }
/// <summary> /// Create graphic object for candidate /// </summary> /// <param name="candidate">Source candidate</param> /// <returns>Graphic object for candidate</returns> public static CandidateGraphicObject Create(AddressCandidate candidate) { CandidateGraphicObject graphic = new CandidateGraphicObject(candidate) { Symbol = new CandidateSymbol() }; graphic.SetZIndex(ObjectLayer.BACKZINDEX); return graphic; }
/// <summary> /// Geocode batch of of items. /// </summary> /// <param name="nameAddresses">Name\Address pairs to geocode.</param> /// <returns></returns> public AddressCandidate[] BatchGeocode(NameAddress[] nameAddresses) { Debug.Assert(nameAddresses != null); Debug.Assert(_geocoder != null); // Create candidates array. AddressCandidate[] candidates = new AddressCandidate[nameAddresses.Length]; // Try to find candidates in local storage and put in appropriate position in candidates array. // Leave null if candidate not found. Return not addresses, which not exists in local storage. List<Address> addressesToGeocode = _ProcessLocalBatchGeocoding(nameAddresses, candidates); if (addressesToGeocode.Count > 0) { // Make batch geocode at server. AddressCandidate[] candidatesFromServer = _geocoder.BatchGeocode(addressesToGeocode.ToArray()); // Fill results of batch geocoding in candidates array. _ProcessServerBatchGeocoding(candidatesFromServer, candidates); } return candidates; }
/// <summary> /// Fill candidates array with geocoding results from server. /// </summary> /// <param name="candidatesFromServer">Candidates, geocoded by server batch geocoding. /// </param> /// <param name="candidates">Candidates, geocoded by local storage.</param> private void _ProcessServerBatchGeocoding(AddressCandidate[] candidatesFromServer, AddressCandidate[] candidates) { Debug.Assert(candidatesFromServer != null); Debug.Assert(candidates != null); int curIndex = 0; for (int candidateFromServerIndex = 0; candidateFromServerIndex < candidatesFromServer.Length; candidateFromServerIndex++) { while (curIndex < candidates.Length && candidates[curIndex] != null) { curIndex++; } Debug.Assert(curIndex < candidates.Length); // If candidate geocoded - save it. Otherwise skip this position in candidates list. if (candidatesFromServer[candidateFromServerIndex] != null) { candidates[curIndex] = candidatesFromServer[candidateFromServerIndex]; } else { curIndex++; } } }
/// <summary> /// Zoom to candidate depends on locator type. /// </summary> /// <param name="mapCtrl">Map control.</param> /// <param name="addressCandidate">Candidate to zoom.</param> public static void ZoomToCandidates(MapControl mapCtrl, AddressCandidate[] addressCandidates) { Debug.Assert(mapCtrl != null); Debug.Assert(addressCandidates != null); LocatorType? locatorType = null; if (addressCandidates.Length == 1) { locatorType = GeocodeHelpers.GetLocatorTypeOfCandidate(addressCandidates[0]); } if (locatorType == null) { // If not composite locator - zoom to candidate. List<ESRI.ArcLogistics.Geometry.Point> points = new List<ESRI.ArcLogistics.Geometry.Point>(); foreach (AddressCandidate addressCandidate in addressCandidates) { points.Add(addressCandidate.GeoLocation); } SetExtentOnCollection(mapCtrl, points); } else { _ZoomToCandidate(mapCtrl, addressCandidates[0], locatorType.Value); } }
private void processOrders(string path) { DataTable table = new DataTable(); table = ReadCSV(path); foreach (DataRow row in table.Rows) { // Create New empty Order CapacitiesInfo capInfo = m_application.Project.CapacitiesInfo; OrderCustomPropertiesInfo propInfo = m_application.Project.OrderCustomPropertiesInfo; ESRI.ArcLogistics.DomainObjects.Order resultOrder = new ESRI.ArcLogistics.DomainObjects.Order(capInfo, propInfo); OrderCustomPropertiesInfo orderPropertiesInfo = resultOrder.CustomPropertiesInfo; OrderCustomProperties orderProperties = resultOrder.CustomProperties; CapacitiesInfo orderCapacitiesInfo = resultOrder.CapacitiesInfo; Capacities orderCapacities = resultOrder.Capacities; bool geocodeProvided = false; bool geocodeCorrect = false; double tempD; DateTime TWdateTime; Double tempX = 0.0; Double tempY = 0.0; // Insert Order Information resultOrder.PlannedDate = m_application.CurrentDate; for (int i = 0; i < table.Columns.Count; i++) { try { switch (table.Columns[i].ColumnName) { #region Case Statements case "Name": resultOrder.Name = row["Name"].ToString(); break; case "Address": resultOrder.Address.AddressLine = row["Address"].ToString(); break; case "City": resultOrder.Address.Locality3 = row["City"].ToString(); break; case "State": resultOrder.Address.StateProvince = row["State"].ToString(); break; case "Zip": resultOrder.Address.PostalCode1 = row["Zip"].ToString(); break; case "Zip4": resultOrder.Address.PostalCode2 = row["Zip4"].ToString(); break; case "Country": resultOrder.Address.Country = row["Country"].ToString(); break; case "PlannedDate": DateTime tempDT = new DateTime(); if (System.DateTime.TryParse(row["PlannedDate"].ToString(), out tempDT)) resultOrder.PlannedDate = tempDT; break; case "Priority": if (row["Priority"].ToString() == "High") resultOrder.Priority = OrderPriority.High; else if (row["Priority"].ToString() == "Normal") resultOrder.Priority = OrderPriority.Normal; break; case "OrderType": if (row["OrderType"].ToString() == "Pickup") resultOrder.Type = OrderType.Pickup; else if (row["OrderType"].ToString() == "Delivery") resultOrder.Type = OrderType.Delivery; break; case "ServiceTime": if (Double.TryParse(row["ServiceTime"].ToString(), out tempD)) resultOrder.ServiceTime = tempD; break; case "TimeWindowStart": string tempS = row["TimeWindowStart"].ToString(); if (DateTime.TryParse(tempS, out TWdateTime)) { if (TWdateTime.TimeOfDay != TimeSpan.Zero) { resultOrder.TimeWindow.From = TWdateTime.TimeOfDay; resultOrder.TimeWindow.IsWideOpen = false; } } break; case "TimeWindowFinish": if (DateTime.TryParse(row["TimeWindowFinish"].ToString(), out TWdateTime)) { if (TWdateTime.TimeOfDay != TimeSpan.Zero) { resultOrder.TimeWindow.To = TWdateTime.TimeOfDay; resultOrder.TimeWindow.IsWideOpen = false; } } break; case "TimeWindow2Start": if (DateTime.TryParse(row["TimeWindow2Start"].ToString(), out TWdateTime)) { if (TWdateTime.TimeOfDay != TimeSpan.Zero) { resultOrder.TimeWindow2.From = TWdateTime.TimeOfDay; resultOrder.TimeWindow2.IsWideOpen = false; } } break; case "TimeWindow2Finish": if (DateTime.TryParse(row["TimeWindow2Finish"].ToString(), out TWdateTime)) { if (TWdateTime.TimeOfDay != TimeSpan.Zero) { resultOrder.TimeWindow2.To = TWdateTime.TimeOfDay; resultOrder.TimeWindow2.IsWideOpen = false; } } break; case "MaxViolationTime": if (Double.TryParse(row["MaxViolationTime"].ToString(), out tempD)) resultOrder.MaxViolationTime = tempD; break; case "VehicleSpecialties": if (row["VehicleSpecialties"].ToString() != "") { string[] stringSeparators = new string[] { ";", "," }; string[] specialties = row["VehicleSpecialties"].ToString().Split(stringSeparators, StringSplitOptions.None); foreach (string s in specialties) { VehicleSpecialty vs = new VehicleSpecialty(); vs.Name = s; foreach (VehicleSpecialty V in m_application.Project.VehicleSpecialties) { if (String.Compare(V.Name, vs.Name, true) == 0) { V.CopyTo(vs); m_application.Project.VehicleSpecialties.Remove(V); break; } } m_application.Project.VehicleSpecialties.Add(vs); resultOrder.VehicleSpecialties.Add(vs); } } break; case "DriverSpecialties": if (row["DriverSpecialties"].ToString() != "") { string[] stringSeparators2 = new string[] { ";", "," }; string[] specialties2 = row["DriverSpecialties"].ToString().Split(stringSeparators2, StringSplitOptions.None); foreach (string s in specialties2) { DriverSpecialty ds = new DriverSpecialty(); ds.Name = s; foreach (DriverSpecialty D in m_application.Project.DriverSpecialties) { if (String.Compare(D.Name, ds.Name, true) == 0) { D.CopyTo(ds); m_application.Project.DriverSpecialties.Remove(D); break; } } m_application.Project.DriverSpecialties.Add(ds); resultOrder.DriverSpecialties.Add(ds); } } break; case "X": string x = row["X"].ToString(); if (x != "" && x != null) if (Double.TryParse(row["X"].ToString(), out tempX)) { if (tempX >= -180.0 && tempX <= 180.0 && tempX != 0.0) { geocodeProvided = true; geocodeCorrect = true; } else if (tempX == 0.0) geocodeCorrect = true; } break; case "Y": string y = row["Y"].ToString(); if (y != "" && y != null) if (Double.TryParse(row["Y"].ToString(), out tempY)) { if (tempY >= -90.0 && tempY <= 90.0 && tempY != 0) { geocodeProvided = true; geocodeCorrect = true; } else if (tempY == 0.0) geocodeCorrect = true; } break; #endregion }// End Switch if (orderProperties.Count > 0 ) { OrderCustomProperty orderPropertyInfoItem = null; for (int j = 0; j < orderPropertiesInfo.Count; j++) { orderPropertyInfoItem = orderPropertiesInfo.ElementAt(j) as OrderCustomProperty; string tempName = orderPropertyInfoItem.Name.Replace(" ", ""); if (tempName == table.Columns[i].ColumnName) { orderProperties[j] = (row[table.Columns[i].ToString()].ToString()); break; } } } if( orderCapacities.Count > 0) { CapacityInfo orderCapacityInfoItem = null; for (int k = 0; k < orderCapacitiesInfo.Count; k++) { orderCapacityInfoItem = orderCapacitiesInfo.ElementAt(k); string tempName = orderCapacityInfoItem.Name.Replace(" ", ""); if (tempName == table.Columns[i].ColumnName) { if(Double.TryParse(row[table.Columns[i].ToString()].ToString(), out tempD)) orderCapacities[k] = tempD; break; } } } } catch (Exception e) { string statusMessage = " Import from " + Params.Instance.importName + " encountered a problem: " + e.Message; m_application.Messenger.AddError(statusMessage); } } resultOrder.CustomProperties = orderProperties; resultOrder.Capacities = orderCapacities; if (geocodeProvided && geocodeCorrect) { AddressCandidate candidate1 = new AddressCandidate(); ESRI.ArcLogistics.Geometry.Point p = new ESRI.ArcLogistics.Geometry.Point(tempX, tempY); candidate1.GeoLocation = p; candidate1.Score = 100; candidate1.Address = resultOrder.Address; resultOrder.GeoLocation = candidate1.GeoLocation; } else { AddressCandidate candidate = m_application.Geocoder.Geocode(resultOrder.Address); if (candidate != null) resultOrder.GeoLocation = candidate.GeoLocation; else { //TODO: Handle orders which were not geocoded!! } } // Add Order m_application.Project.Orders.Add(resultOrder); } }
/// <summary> /// Set geocoded fields to address. /// </summary> /// <param name="geocodable">Geocodable object to set address and position.</param> /// <param name="candidate">Source candidate.</param> public static void SetCandidate(IGeocodable geocodable, AddressCandidate candidate) { Debug.Assert(geocodable != null); Debug.Assert(candidate != null); // Set geolocation. geocodable.GeoLocation = new ESRI.ArcLogistics.Geometry.Point( candidate.GeoLocation.X, candidate.GeoLocation.Y); geocodable.Address.MatchMethod = candidate.Address.MatchMethod ?? string.Empty; if (App.Current.Geocoder.AddressFormat == AddressFormat.MultipleFields) { // Concatenate Full Address from other address fields. SetFullAddress(geocodable.Address); } else if (App.Current.Geocoder.AddressFormat == AddressFormat.SingleField) { // Do nothing: don't touch user entered\imported Full Address // and can't parse Full Address to address parts. } else { // Do nothing. Debug.Assert(false); } }
/// <summary> /// Get locator type of candidate. /// </summary> /// <param name="candidate">Address candidate.</param> /// <returns>Locator type of candidate. Null in case of not composite locator.</returns> public static LocatorType? GetLocatorTypeOfCandidate(AddressCandidate candidate) { Debug.Assert(candidate != null); LocatorType? result = null; if (App.Current.Geocoder.IsCompositeLocator) { List<LocatorInfo> sublocators = new List<LocatorInfo>(); sublocators.AddRange(App.Current.Geocoder.Locators); // Check candidate is from street locator. List<LocatorInfo> streetLocators = _ExtractLocators(AddressPart.AddressLine, sublocators); if (_IsMatchMethodBelongsToLocators(streetLocators, candidate.Address.MatchMethod)) { result = LocatorType.Street; } else { // Check candidate is from cityState locator. List<LocatorInfo> cityStateLocators = _ExtractLocators(AddressPart.StateProvince, sublocators); if (_IsMatchMethodBelongsToLocators(cityStateLocators, candidate.Address.MatchMethod)) { result = LocatorType.CityState; } else { // Check candidate is from zip locator. List<LocatorInfo> zipLocators = _ExtractLocators(AddressPart.PostalCode1, sublocators); if (_IsMatchMethodBelongsToLocators(zipLocators, candidate.Address.MatchMethod)) { result = LocatorType.Zip; } } } } return result; }
/// <summary> /// Get AddressCandidate from geocode service response. /// </summary> /// <param name="geocodedAddress">Geocode service response.</param> /// <returns>Geocoded AddressCandidate.</returns> private AddressCandidate _GetAddressCandidate(PropertySet geocodedAddress) { AddressCandidate result = new AddressCandidate(); Address address = new Address(); result.Address = address; // Look for needed properties and put them in to AddressCandidate. foreach (PropertySetProperty property in geocodedAddress.PropertyArray) { if (property.Key.Equals(SHAPE_PROPERTY_KEY, StringComparison.OrdinalIgnoreCase)) { PointN locationN = (PointN)property.Value; result.GeoLocation = new ESRI.ArcLogistics.Geometry.Point(locationN.X, locationN.Y); ; } else if (property.Key.Equals(SCORE_PROPERTY_KEY, StringComparison.OrdinalIgnoreCase)) result.Score = Convert.ToInt16(property.Value); else if (property.Key.Equals(MATCHADDR_PROPERTY_KEY, StringComparison.OrdinalIgnoreCase)) address.FullAddress = (string)property.Value ?? string.Empty; else if (property.Key.Equals(LOCNAME_PROPERTY_KEY, StringComparison.OrdinalIgnoreCase)) address.MatchMethod = (string)property.Value ?? string.Empty; } if (!_UpdateLocatorProperties(result)) { result = null; } return result; }
/// <summary> /// Updates locator related properties for the specified address candidate. /// </summary> /// <param name="candidate">The reference to the address candidate to be updated.</param> /// <returns>True if and only if the locator corresponding to the address match method /// for the specified candidate is enabled.</returns> private bool _UpdateLocatorProperties(AddressCandidate candidate) { if (!this.IsCompositeLocator) { candidate.Locator = _defaultLocator; return true; } var locatorEnabled = true; var locator = default(LocatorInfo); var matchMethod = candidate.Address.MatchMethod ?? string.Empty; if (_locators.TryGetValue(matchMethod, out locator)) { candidate.Locator = locator; locatorEnabled = locator.Enabled; if (locatorEnabled) { candidate.Address.MatchMethod = locator.Title ?? string.Empty; } } return locatorEnabled; }
/// <summary> /// Parses batch geocoding result. Set geocode candidates values to relative object. /// </summary> /// <param name="candidates">Candidates from geocoding.</param> /// <param name="objects">Objects to geocoding.</param> private void _ParseBatchGeocodeResult(AddressCandidate[] candidates, IList<AppData.DataObject> objects) { Debug.Assert(null != objects); // created Debug.Assert(null != candidates); // created Debug.Assert(candidates.Length == objects.Count); // valid state Debug.Assert(null != _checker); // inited // valid check extent var importExtent = App.Current.Map.ImportCheckExtent; // init progress int count = objects.Count; for (int index = 0; index < count; ++index) { _checker.ThrowIfCancellationRequested(); // get current object AppData.DataObject obj = objects[index]; IGeocodable geocodable = _GetGeocodable(obj); bool needMessage = false; if (geocodable.IsGeocoded) { // add message - Could not locate object using X/Y attributes. // Order was located using address information instead Debug.Assert(!importExtent.IsPointIn(geocodable.GeoLocation.Value)); needMessage = true; } AddressCandidate candidate = candidates[index]; _UpdateGeocodableInfo(needMessage, candidate, obj); } }
/// <summary> /// Does batch geocoding. /// </summary> /// <param name="objects">Objects to geocoding.</param> private void _BatchGeocode(IList<AppData.DataObject> objects) { Debug.Assert(null != objects); // created Debug.Assert(0 < objects.Count); // not empty Debug.Assert(null != _checker); // inited try { // create list of addresses Address[] addresses = _CreateAddressList(objects); // start geocode App currentApp = App.Current; AddressCandidate[] candidates = null; if (objects[0] is Order) { // for orders - use local geocoding NameAddress[] namedAddress = _CreateNamedAddressList(objects); var localGeocoder = new LocalGeocoder(currentApp.Geocoder, currentApp.NameAddressStorage); candidates = localGeocoder.BatchGeocode(namedAddress); } else { // for other object - use server geocoder candidates = currentApp.Geocoder.BatchGeocode(addresses); } _checker.ThrowIfCancellationRequested(); // validate geocode _ValidateLocation(addresses, candidates); // If current geocoder is arcgiscomgeocoder - check that we got // candidates from "good" locators. var arcgisgeocoder = App.Current.Geocoder as ArcGiscomGeocoder; if (arcgisgeocoder != null) { for (int i = 0; i < candidates.Count(); i++) { var goodAddressType = arcgisgeocoder.ExactLocatorsTypesNames.Contains(candidates[i].AddressType); if (!goodAddressType) candidates[i] = new AddressCandidate(); } } // parse result _ParseBatchGeocodeResult(candidates, objects); } catch (Exception ex) { Logger.Error(ex); // store exception _detectedException = ex; } }
/// <summary> /// Create map point for candidate /// </summary> /// <param name="candidate">Candidate to get geometry</param> /// <returns>Map point of candidate position</returns> private ESRI.ArcGIS.Client.Geometry.MapPoint _CreatePoint(AddressCandidate candidate) { ESRI.ArcGIS.Client.Geometry.MapPoint mapPoint = null; ESRI.ArcLogistics.Geometry.Point geoLocation = candidate.GeoLocation; // Project point from WGS84 to Web Mercator if spatial reference of map is Web Mercator if (ParentLayer != null && ParentLayer.SpatialReferenceID != null) { geoLocation = WebMercatorUtil.ProjectPointToWebMercator(geoLocation, ParentLayer.SpatialReferenceID.Value); } mapPoint = new ESRI.ArcGIS.Client.Geometry.MapPoint(geoLocation.X, geoLocation.Y); return mapPoint; }
/// <summary> /// Converts the specified find address candidate response object to an address candidate /// object. /// </summary> /// <param name="response">The instance of the find address candidate response /// to be converted.</param> /// <returns>A new <see cref="AddressCandidate"/> object based on information from /// the response.</returns> private AddressCandidate _Convert(FindAddressCandidateResponse response) { if (response == null || response.Score == null || response.Address == null || response.Location == null || response.Extent == null) { return null; } var result = new AddressCandidate { // Convert candidate match score. Score = response.Score.GetValueOrDefault(), // Convert candidate address. Address = new Address { FullAddress = response.Address, }, // Convert candidate geolocation. GeoLocation = new Geometry.Point { X = response.Location.X, Y = response.Location.Y, } }; return result; }
/// <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> /// Return list without empty candidates. /// </summary> /// <param name="candidatesArr">Candidates array.</param> /// <returns>Candidates list without empty items.</returns> private List<AddressCandidate> _RemoveNullElements(AddressCandidate[] candidatesArr) { List<AddressCandidate> candidates = new List<AddressCandidate>(); foreach (AddressCandidate candidate in candidatesArr) { if (candidate != null) { candidates.Add(candidate); } } return candidates; }
/// <summary> /// Updates geocodable information. /// </summary> /// <param name="needMessage">Need show message.</param> /// <param name="candidate">Geocoded candidate (can be NULL).</param> /// <param name="obj">Source object to geocoded candidate.</param> private void _UpdateGeocodableInfo(bool needMessage, AddressCandidate candidate, AppData.DataObject obj) { Debug.Assert(null != obj); // Created. IGeocodable geocodable = _GetGeocodable(obj); geocodable.GeoLocation = null; if ((null == candidate) || (candidate.Score <= App.Current.Geocoder.MinimumMatchScore)) { // Not geocoded. geocodable.Address.MatchMethod = string.Empty; } else { GeocodeHelpers.SetCandidate(geocodable, candidate); ++_geocodedCount; // Store warning. if (needMessage) { string objectName = _informer.ObjectName; string errorTextFormat = App.Current.GetString("ImportProcessStatusRecordOutMapExtendGeocodedFormat", objectName.ToLower(), "{0}", objectName); var description = new MessageDetail(MessageType.Warning, errorTextFormat, obj); _details.Add(description); } } }
/// <summary> /// Get address from property set response. /// </summary> /// <param name="propertySet">Property set.</param> /// <returns>Address.</returns> private Address _GetAddress(PropertySet propertySet) { Address address = new Address(); foreach (PropertySetProperty prop in propertySet.PropertyArray) { // Try to extract address field. int fieldCount = _addressFields.Length; for (int index = 0; index < fieldCount; index++) { if (prop.Key.Equals(_locatorFieldNames[index], StringComparison.OrdinalIgnoreCase)) { AddressPart addressPart = _addressFields[index].Type; address[addressPart] = _RemoveDuplicateWhiteSpace((string)prop.Value); break; } } // Try to extract locator name. if (prop.Key.Equals(LOCNAME_PROPERTY_KEY, StringComparison.OrdinalIgnoreCase)) { string locName = (string)prop.Value; address.MatchMethod = locName ?? string.Empty; } } string fullAddress = ""; for (int index = 0; index < _addressFields.Length; index++) { AddressPart addressPart = _addressFields[index].Type; if (address[addressPart] != null) { if (fullAddress.Length != 0 && address[addressPart].Length != 0) fullAddress += ", "; fullAddress += address[addressPart]; } } if (fullAddress.Length != 0) address.FullAddress = fullAddress; var candidate = new AddressCandidate { Address = address, }; _UpdateLocatorProperties(candidate); return address; }
/// <summary> /// Validates geolocation candidates by streets geocoder. /// </summary> /// <param name="addresses">Address to geocode.</param> /// <param name="candidates">Geocded candidates.</param> private void _ValidateLocation(Address[] addresses, AddressCandidate[] candidates) { Debug.Assert(null != addresses); // created Debug.Assert(null != candidates); // created Debug.Assert(candidates.Length == addresses.Length); // valid stated Debug.Assert(null != _checker); // inited // init location validator var streetsGeocoder = App.Current.StreetsGeocoder; var locationValidator = new LocationValidator(streetsGeocoder); // do validation var incorrectCandidates = locationValidator .FindIncorrectLocations(candidates) .GroupBy(index => addresses[index]) .ToArray(); // get incorrect candidate indexes var addressesForGeocoding = incorrectCandidates .Select(item => item.Key) .ToArray(); _checker.ThrowIfCancellationRequested(); // regeocoding by streets geocoder var fixedCandidates = streetsGeocoder.BatchGeocode(addressesForGeocoding); // update regeocoded candidates for (var index = 0; index < fixedCandidates.Length; ++index) { _checker.ThrowIfCancellationRequested(); foreach (var j in incorrectCandidates[index]) { candidates[j] = fixedCandidates[index]; } } }
/// <summary> /// Get AddressCandidate from record. /// </summary> /// <param name="record">Source record.</param> /// <param name="pointFieldIndex">Index of point field.</param> /// <param name="scoreFieldIndex">Index of score field.</param> /// <param name="matchAddrFieldIndex">Index of match address field.</param> /// <param name="locNameFieldIndex">Index of locator name field.</param> /// <param name="includeDisabledLocators">Is need to add candidates from disabled locators.</param> /// <param name="addrTypeIndex">Index of address type field.</param> /// <returns>Address candidate.</returns> private AddressCandidate _GetAddressCandidateFromRecord(Record record, int pointFieldIndex, int scoreFieldIndex, int matchAddrFieldIndex, int locNameFieldIndex, bool includeDisabledLocators, int addrTypeIndex) { AddressCandidate result = new AddressCandidate(); Address address = new Address(); result.Address = address; PointN locationN = (PointN)record.Values[pointFieldIndex]; // Check that we got non null point in record. if (locationN != null) { result.GeoLocation = new ESRI.ArcLogistics.Geometry.Point(locationN.X, locationN.Y); } result.Score = Convert.ToInt16(record.Values[scoreFieldIndex]); string matchAddr = (string)record.Values[matchAddrFieldIndex]; address.FullAddress = matchAddr ?? string.Empty; string locName = string.Empty; if (locNameFieldIndex != -1) { locName = (string)record.Values[locNameFieldIndex]; } address.MatchMethod = locName ?? string.Empty; // Assign address type property value. string addrType = string.Empty; if (addrTypeIndex != -1) { addrType = (string)record.Values[addrTypeIndex]; } result.AddressType = addrType ?? string.Empty; if (!_UpdateLocatorProperties(result) && !includeDisabledLocators) { result = null; } return result; }
/// <summary> /// Make string like 'Bevmo couldn’t be located, we’ve zoomed to Pat’s Ranch Rd. Use the pushpin tool to locate exactly.' /// If street candidate - use Address Line from geocodable item, otherwise(citystate or zip) use full address. /// </summary> /// <param name="item">Geocodable item.</param> /// <param name="candidateToZoom">First candidate to zoom.</param> /// <returns>Geocode result string.</returns> private string _MakeNotFoundButZoomedString(IGeocodable item, AddressCandidate candidateToZoom) { string messageFmt = (string)App.Current.FindResource(GEOCODE_RESULT_ZOOMED_RESOURCE_NAME); StringBuilder stringBuilder = new StringBuilder(); // Add "Not located, but zoomed to..." string. stringBuilder.AppendFormat(messageFmt, item.ToString()); // Add zoomed address. string zoomedAddress = GeocodeHelpers.GetZoomedAddress(item, candidateToZoom); stringBuilder.Append(zoomedAddress); // Add dot at the end of sentence. stringBuilder.Append(MESSAGE_STRING_PARTS_DELIMETER); // Add "Use pushpin" string. stringBuilder.Append((string)App.Current.FindResource(USE_PUSHPIN_RESOURCE_NAME)); string result = stringBuilder.ToString(); return result; }
/// <summary> /// Make string parts like 'We couldn’t find… so we’ve zoomed to…' /// If street candidate - use Address Line from geocodable item, otherwise(citystate or zip) use full address. /// </summary> /// <param name="item">Geocodable item.</param> /// <param name="candidateToZoom">First candidate to zoom.</param> /// <returns>Geocode result string parts.</returns> public static string GetZoomedAddress(IGeocodable item, AddressCandidate candidateToZoom) { LocatorType? locatorType = GeocodeHelpers.GetLocatorTypeOfCandidate(candidateToZoom); string zoomedAddress; // If locator type of candidate is street than get Address Line. if (locatorType.HasValue && locatorType.Value == LocatorType.Street && !string.IsNullOrEmpty(item.Address.AddressLine)) { // Extract street name. zoomedAddress = GeocodeHelpers.ExtractStreet(item.Address.AddressLine); } else { // Otherwise use full address. zoomedAddress = candidateToZoom.Address.FullAddress; } return zoomedAddress; }
/// <summary> /// End geocoding with match found. Save candidate position to edited item. /// </summary> /// <param name="geocodable">Item to geocode.</param> /// <param name="candidate">Matched candidate.</param> private void _ProcessMatchFound(IGeocodable geocodable, AddressCandidate candidate) { string manuallyEditedXY = (string)Application.Current.FindResource("ManuallyEditedXY"); if (string.Equals(candidate.Address.MatchMethod, manuallyEditedXY)) { geocodable.GeoLocation = new ESRI.ArcLogistics.Geometry.Point(candidate.GeoLocation.X, candidate.GeoLocation.Y); ; candidate.Address.CopyTo(geocodable.Address); } else { GeocodeHelpers.SetCandidate(geocodable, candidate); } if (MatchFound != null) MatchFound(this, EventArgs.Empty); IsGeocodingInProcess = false; }
/// <summary> /// Show hint "Could not located, but zoomed..." /// </summary> /// <param name="geocodableItem">Geocodable object.</param> /// <param name="candidatesToZoom">Address to which map was zoomed. Null if not zoomed.</param> public void ShowZoomToCandidatePopup(IGeocodable geocodableItem, AddressCandidate[] candidatesToZoom) { if (_isGeocodingHintInitialized) { // Show hint suspendedly because final selection changed event in datagrid control is suspended. // And so hint will be hided on selection changed. Dispatcher.BeginInvoke(new Action(delegate() { if (SelectedItems.Count > 0 && SelectedItems[0] == geocodableItem) { GeocodingHint.ShowHint(geocodableItem, candidatesToZoom); } }), DispatcherPriority.Background); } }
/// <summary> /// Convert local storage record to address candidate. /// </summary> /// <param name="nameAddressRecord">Local storage record.</param> /// <returns>Address candidate.</returns> private AddressCandidate _ConvertToCandidate(NameAddressRecord nameAddressRecord) { Debug.Assert(nameAddressRecord != null); AddressCandidate candidateFromLocalStorage = new AddressCandidate(); // Candidate from local storage have maximum score. candidateFromLocalStorage.Score = MAXIMUM_SCORE; // Set candidate geolocation. candidateFromLocalStorage.GeoLocation = new ESRI.ArcLogistics.Geometry.Point( nameAddressRecord.GeoLocation.X, nameAddressRecord.GeoLocation.Y); // Set candidate address. Address candidateAddress = new Address(); candidateFromLocalStorage.Address = candidateAddress; Address matchedAddress = nameAddressRecord.MatchedAddress; Address address = nameAddressRecord.NameAddress.Address; Address addressToCopy; if (CommonHelpers.IsAllAddressFieldsEmpty(matchedAddress) && string.IsNullOrEmpty(matchedAddress.MatchMethod)) { addressToCopy = address; } else { addressToCopy = matchedAddress; } addressToCopy.CopyTo(candidateAddress); GeocodeHelpers.SetFullAddress(candidateAddress); // Set locator. foreach (LocatorInfo locator in App.Current.Geocoder.Locators) { if (locator.Title.Equals(candidateFromLocalStorage.Address.MatchMethod, System.StringComparison.OrdinalIgnoreCase) || locator.Name.Equals(candidateFromLocalStorage.Address.MatchMethod, System.StringComparison.OrdinalIgnoreCase)) { candidateFromLocalStorage.Locator = locator; break; } } candidateFromLocalStorage.AddressType = ArcGiscomGeocoder.LocalStorageAddressType; return candidateFromLocalStorage; }
/// <summary> /// Try to find candidates in local storage and put in appropriate position in candidates array. /// Leave null if candidate not found. Return addresses, which not exists in local storage. /// </summary> /// <param name="nameAddresses">Name\Address pairs to geocode.</param> /// <param name="candidates">Candidates list.</param> /// <returns>Addresses, which not exists in local storage.</returns> private List<Address> _ProcessLocalBatchGeocoding(NameAddress[] nameAddresses, AddressCandidate[] candidates) { Debug.Assert(nameAddresses != null); Debug.Assert(candidates != null); List<Address> addressesToGeocode = new List<Address>(); for (int index = 0; index < nameAddresses.Length; index++) { AddressCandidate candidate = Geocode(nameAddresses[index]); // If candidate exists in local storage - put it to candidates list. // Otherwise add address to geocode on server. if (candidate != null) { candidates[index] = candidate; } else { addressesToGeocode.Add(nameAddresses[index].Address); } } return addressesToGeocode; }
/// <summary> /// Select candidate. /// </summary> /// <param name="item">Candidate.</param> public void SelectCandidate(AddressCandidate item) { if (item == null) { if (DataGridControl.SelectedItems.Count > 0) { DataGridControl.SelectedItems.Clear(); } Debug.Assert(DataGridControl.SelectedItems.Count == 0); } else { if (DataGridControl.SelectedItems.Count == 0) { DataGridControl.SelectedItems.Add(item); } else { Debug.Assert(DataGridControl.SelectedItems.Count == 1); DataGridControl.SelectedItems.Clear(); DataGridControl.SelectedItems.Add(item); } DataGridControl.BringItemIntoView(item); } _SetButtonApplyIsEnabled(); }