/// <summary> /// Try to initialize the map units /// </summary> private void InitializeMapUnit() { if (Map == null || Map.SpatialReference == null) { return; } // First test the well know spatial references if (Map.SpatialReference.WKID == 4326) { MapUnit = ScaleLineUnit.DecimalDegrees; } else if (_webMercSref.Equals(Map.SpatialReference)) { MapUnit = ScaleLineUnit.Meters; } else { Layer layer = Map.Layers == null ? null : Map.Layers.FirstOrDefault(l => l.SpatialReference != null && l.SpatialReference.Equals(Map.SpatialReference)); string layerUnits; if (layer is ArcGISDynamicMapServiceLayer) { layerUnits = ((ArcGISDynamicMapServiceLayer)layer).Units; } else if (layer is ArcGISTiledMapServiceLayer) { layerUnits = ((ArcGISTiledMapServiceLayer)layer).Units; } else { layerUnits = null; } if (!string.IsNullOrEmpty(layerUnits)) { // Remove leading 'esri' to layerUnits if (layerUnits.StartsWith("esri")) { layerUnits = layerUnits.Substring(4); } try { ScaleLineUnit unit = (ScaleLineUnit)Enum.Parse(typeof(ScaleLineUnit), layerUnits, true); MapUnit = unit; } catch (ArgumentException) // layersUnits is not one of the named constants defined for the enumeration { } } } }
private double GetBestEstimateOfValue(double resolution, ScaleLineUnit displayUnit, out ScaleLineUnit unit, out double outResolution) { unit = displayUnit; double rounded = 0; double originalRes = resolution; while (rounded < 0.5) { resolution = originalRes; if (MapUnit == ScaleLineUnit.DecimalDegrees) { resolution = GetResolutionForGeographic(Map.Extent.GetCenter(), resolution); resolution = resolution * (int)ScaleLineUnit.Meters / (int)unit; } else if (_webMercSref.Equals(Map.SpatialReference)) { //WebMercator double mercatorStretch = 1 / Math.Cosh(Map.Extent.GetCenter().Y / earthRadius); // = Cos(lat) resolution = mercatorStretch * originalRes * (int)ScaleLineUnit.Meters / (int)unit; } else if (MapUnit != ScaleLineUnit.Undefined) { resolution = resolution * (int)MapUnit / (int)unit; } double val = TargetWidth * resolution; val = RoundToSignificant(val, resolution); double noFrac = Math.Round(val); // to get rid of the fraction if (val < 0.5) { ScaleLineUnit newUnit = ScaleLineUnit.Undefined; // Automatically switch unit to a lower one if (unit == ScaleLineUnit.Kilometers) { newUnit = ScaleLineUnit.Meters; } else if (unit == ScaleLineUnit.Miles) { newUnit = ScaleLineUnit.Feet; } if (newUnit == ScaleLineUnit.Undefined) { break; } //no lower unit unit = newUnit; } else if (noFrac > 1) { rounded = noFrac; var len = noFrac.ToString("F0").Length; // Format F0 prevents from using exponential notation for big numbers if (len <= 2) { // single/double digits ... make it a multiple of 5 ..or 1,2,3,4 if (noFrac > 5) { rounded -= noFrac % 5; } while (rounded > 1 && (rounded / resolution) > TargetWidth) { // exceeded maxWidth .. decrement by 1 or by 5 double decr = noFrac > 5 ? 5 : 1; rounded = rounded - decr; } } else if (len > 2) { rounded = Math.Round(noFrac / Math.Pow(10, len - 1)) * Math.Pow(10, len - 1); if ((rounded / resolution) > TargetWidth) { // exceeded maxWidth .. use the lower bound instead rounded = Math.Floor(noFrac / Math.Pow(10, len - 1)) * Math.Pow(10, len - 1); } } } else { // anything between 0.5 and 1 rounded = Math.Floor(val); if (rounded == 0) { //val >= 0.5 but < 1 so round up rounded = (val == 0.5) ? 0.5 : 1; if ((rounded / resolution) > TargetWidth) { // exceeded maxWidth .. re-try by switching to lower unit rounded = 0; ScaleLineUnit newUnit = ScaleLineUnit.Undefined; // Automatically switch unit to a lower one if (unit == ScaleLineUnit.Kilometers) { newUnit = ScaleLineUnit.Meters; } else if (unit == ScaleLineUnit.Miles) { newUnit = ScaleLineUnit.Feet; } if (newUnit == ScaleLineUnit.Undefined) { break; } //no lower unit unit = newUnit; } } } } outResolution = resolution; return(rounded); }
private double GetBestEstimateOfValue(double resolution, ScaleLineUnit displayUnit, out ScaleLineUnit unit, out double outResolution) { unit = displayUnit; double rounded = 0; double originalRes = resolution; while (rounded < 0.5) { resolution = originalRes; if (MapUnit == ScaleLineUnit.DecimalDegrees) { resolution = GetResolutionForGeographic(Map.Extent.GetCenter(), resolution); resolution = resolution * (int)ScaleLineUnit.Meters / (int)unit; } else if (_webMercSref.Equals(Map.SpatialReference)) { //WebMercator double mercatorStretch = 1 / Math.Cosh(Map.Extent.GetCenter().Y / earthRadius); // = Cos(lat) resolution = mercatorStretch * originalRes * (int)ScaleLineUnit.Meters / (int)unit; } else if (MapUnit != ScaleLineUnit.Undefined) { resolution = resolution * (int)MapUnit / (int)unit; } double val = TargetWidth * resolution; val = RoundToSignificant(val, resolution); double noFrac = Math.Round(val); // to get rid of the fraction if (val < 0.5) { ScaleLineUnit newUnit = ScaleLineUnit.Undefined; // Automatically switch unit to a lower one if (unit == ScaleLineUnit.Kilometers) newUnit = ScaleLineUnit.Meters; else if (unit == ScaleLineUnit.Miles) newUnit = ScaleLineUnit.Feet; if (newUnit == ScaleLineUnit.Undefined) { break; } //no lower unit unit = newUnit; } else if (noFrac > 1) { rounded = noFrac; var len = noFrac.ToString().Length; if (len <= 2) { // single/double digits ... make it a multiple of 5 ..or 1,2,3,4 if (noFrac > 5) { rounded -= noFrac % 5; } while (rounded > 1 && (rounded / resolution) > TargetWidth) { // exceeded maxWidth .. decrement by 1 or by 5 double decr = noFrac > 5 ? 5 : 1; rounded = rounded - decr; } } else if (len > 2) { rounded = Math.Round(noFrac / Math.Pow(10, len - 1)) * Math.Pow(10, len - 1); if ((rounded / resolution) > TargetWidth) { // exceeded maxWidth .. use the lower bound instead rounded = Math.Floor(noFrac / Math.Pow(10, len - 1)) * Math.Pow(10, len - 1); } } } else { // anything between 0.5 and 1 rounded = Math.Floor(val); if (rounded == 0) { //val >= 0.5 but < 1 so round up rounded = (val == 0.5) ? 0.5 : 1; if ((rounded / resolution) > TargetWidth) { // exceeded maxWidth .. re-try by switching to lower unit rounded = 0; ScaleLineUnit newUnit = ScaleLineUnit.Undefined; // Automatically switch unit to a lower one if (unit == ScaleLineUnit.Kilometers) newUnit = ScaleLineUnit.Meters; else if (unit == ScaleLineUnit.Miles) newUnit = ScaleLineUnit.Feet; if (newUnit == ScaleLineUnit.Undefined) { break; } //no lower unit unit = newUnit; } } } } outResolution = resolution; return rounded; }