public static bool GetGeodesicSizePrecise(this IPrintableMap map, IEnvelope extents, out GeoSize size) { size = null; double width, height; if (map.Projection.HasTransformation) { // the projection supports coordinate tranformation to WGS84 if (CalculateExtentsWidth(map, extents, out width) && CalculateExtentsHeight(map, extents, out height)) { size = new GeoSize(width, height); return(true); } } if (map.Projection.IsGeographic) { // it's WGS84 var center = extents.Center; width = GeodesicDistance(center.Y, extents.MinX, center.Y, extents.MaxX); height = GeodesicDistance(extents.MinY, center.X, extents.MaxY, center.X); size = new GeoSize(width, height); return(true); } return(false); }
/// <summary> /// Recursively calculates new extents of the map ot cover a certain geo size in meters. /// </summary> private static IEnvelope CalcNewExtentsCore( IPrintableMap map, IEnvelope oldExtents, GeoSize newSize, SizeF paperSize, ref int depth) { depth++; GeoSize oldSize; if (map.GetGeodesicSize(oldExtents, out oldSize)) { const int maxDepth = 5; double newScale = CalcMapScale(newSize, paperSize); double oldScale = CalcMapScale(oldSize, paperSize); if (NumericHelper.Equal(newScale, oldScale, 1e-6) || depth > maxDepth) { return(oldExtents); } double ratio = newScale / oldScale - 1; double dx = oldExtents.Width * ratio; double dy = oldExtents.Height * ratio; var extents = oldExtents.Inflate(dx, dy); return(CalcNewExtentsCore(map, extents, newSize, paperSize, ref depth)); } return(null); }
private void Map1_Loaded(object sender, RoutedEventArgs e) { Map1.MapUnit = GeoUnit.Meter; GeoImage image = new GeoImage(@"SampleData/bing-aerial-900913.png"); GeoSize size = image.GetSize(); GeoImageLayer geoImageLayer = new GeoImageLayer(image, new WorldFile(GeoCommonHelper.GetMaxBound(GeoUnit.Meter), (float)size.Width, (float)size.Height)); LayerOverlay layerOverlay = new LayerOverlay(); layerOverlay.Layers.Add(geoImageLayer); Map1.Overlays.Add(layerOverlay); Map1.ZoomToFullBound(); }
/// <summary> /// Calculates the size of specified map extents in meters. /// </summary> public static bool GetGeodesicSize(this IPrintableMap map, IEnvelope extents, out GeoSize size) { bool result = GetGeodesicSizePrecise(map, extents, out size); if (result) { return(true); } // we have nothing better but return width and height of the extents in original // coordinate system; only let's convert them to meters (geodesic size is always in meters) double width = UnitConversionHelper.Convert(map.MapUnits, LengthUnits.Meters, extents.Width); double height = UnitConversionHelper.Convert(map.MapUnits, LengthUnits.Meters, extents.Height); size = new GeoSize(width, height); return(true); }
/// <summary> /// Calculates the size of the map on screen for a given size of map area and scale. /// </summary> /// <param name="mapScale">Map scale.</param> /// <param name="geoSize">Geodesic size of the map area in meters.</param> /// <param name="xyRatio">The X / Y ratio for the extents in original coordinate system.</param> /// <returns>Size of the map on the screen in 1/100 of an inch.</returns> public static SizeF CalcMapSize(int mapScale, GeoSize geoSize, double xyRatio) { double cf = LengthUnits.Meters.GetConversionFactor(); var widthInches = geoSize.Width * cf / mapScale; var heightInches = geoSize.Height * cf / mapScale; // The distortion introduced be orginal map coordinate system may be different along X and Y axes, // so paper size rectangle may no longer have the same X / Y side ratio as original extents. // This will result in adjustment of extents in map projection according to this ratio, which is undesirable. // Let's instead adjust resulting paper size to orignal X / Y ratio. double newRatio = widthInches / heightInches; if (!NumericHelper.Equal(newRatio, xyRatio, 1e-6)) { double correction = Math.Sqrt(newRatio / xyRatio); heightInches *= correction; widthInches /= correction; } return(new SizeF((float)(widthInches * 100.0), (float)(heightInches * 100.0))); }
/// <summary> /// Calculates map scale to fit given extents. /// </summary> /// <param name="geoSize">Geodesic size of mapped area in meters.</param> /// <param name="mapSize">Size of the map on the screen (1/100 of inch).</param> /// <param name="scaleType">The X and Y scale are often different, this parameter tells how to choose the return value from 2 values available.</param> /// <returns>Scale of the map.</returns> public static double CalcMapScale(GeoSize geoSize, SizeF mapSize, ScaleType scaleType = ScaleType.Average) { double cf = LengthUnits.Meters.GetConversionFactor(); double scaleX = geoSize.Width / (mapSize.Width / 100.0 / cf); double scaleY = geoSize.Height / (mapSize.Height / 100.0 / cf); switch (scaleType) { case ScaleType.Average: return((scaleX + scaleY) / 2.0); case ScaleType.Smallest: return(Math.Max(scaleX, scaleY)); case ScaleType.Largest: return(Math.Min(scaleX, scaleY)); default: throw new ArgumentOutOfRangeException("scaleType"); } }
/// <summary> /// Calculates the size of currently selected map extents in meters /// </summary> public static bool GetGeodesicSize(this IPrintableMap map, out GeoSize size) { return(GetGeodesicSize(map, map.Extents, out size)); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 18JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>GeoBounds</code> whose top left corner is * (0, 0) and whose Width and Height are specified * by the <code>GeoSize</code> argument. * @param size a <code>GeoSize</code>, specifying Width and Height */ public GeoLatLngBounds(GeoSize size) : this(0, 0, size.Width, size.Height) { }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 18JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>GeoBounds</code> whose upper-left corner is * specified by the GeoPoint argument, and * whose Width and Height are specified by the * {@link GeoSize} argument. * @param p a <code>GeoPoint</code> that is the upper-left corner of * the <code>GeoBounds</code> * @param size a <code>GeoSize</code>, representing the * Width and Height of the <code>GeoBounds</code> */ public GeoLatLngBounds(GeoPoint p, GeoSize size) : this(p.X, p.Y, size.Width, size.Height) { }
/// <summary> /// Calculates new extents of the map given that they must cover certain geo size in meters. /// </summary> /// <param name="map">The map.</param> /// <param name="oldExtents">The extents.</param> /// <param name="newSize">The new size.</param> /// <param name="paperSize"></param> /// <returns>New extents</returns> public static IEnvelope CalcNewExtents(IPrintableMap map, IEnvelope oldExtents, GeoSize newSize, SizeF paperSize) { int depth = 0; return(CalcNewExtentsCore(map, oldExtents, newSize, paperSize, ref depth)); }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 18JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>GeoBounds</code> whose top left corner is * (0, 0) and whose Width and Height are specified * by the <code>GeoSize</code> argument. * @param size a <code>GeoSize</code>, specifying Width and Height */ public GeoLatLngBounds(GeoSize size) : this(0, 0, size.Width, size.Height) { }
//////////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS ------------------------------ // Date Name Tracking # Description // --------- ------------------- ------------- ---------------------- // 18JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////////// /** * Constructs a new <code>GeoBounds</code> whose upper-left corner is * specified by the GeoPoint argument, and * whose Width and Height are specified by the * {@link GeoSize} argument. * @param p a <code>GeoPoint</code> that is the upper-left corner of * the <code>GeoBounds</code> * @param size a <code>GeoSize</code>, representing the * Width and Height of the <code>GeoBounds</code> */ public GeoLatLngBounds(GeoPoint p, GeoSize size) : this(p.X, p.Y, size.Width, size.Height) { }