Quantcast
Channel: DotSpatial
Viewing all articles
Browse latest Browse all 3973

New Post: Map Scale in Feets

$
0
0
I have converted the ScaleBar plugin from metric to imperial "Feet" but don't get it working very well. I would be glad if someone would take a look at it for me to know where I am not getting it right.

Please see the code below.

private void ScaleTo(double scale)
    {
        if ((scale == 0 || App.Map.Projection == null)) return;

        var ext = App.Map.ViewExtents;
        Point centerpoint = new Point
        {
            X = (ext.MinX + ext.MaxX) / 2,
            Y = (ext.MinY + ext.MaxY) / 2
        };


        //TODO this works for Feet-based coordinate-systems. 
        //const double dInchesPerMeter = 39.3700787401575;
        const double dInchesPerFoot = 12;
        double dScreenWidthInFeet = (App.Map.BufferedImage.Width / App.Map.BufferedImage.HorizontalResolution) / dInchesPerFoot;
        double newwidth = ((scale * dScreenWidthInFeet) / App.Map.Projection.Unit.Feets) / 2;
        double newheight = ((App.Map.ViewExtents.Height * newwidth) / App.Map.ViewExtents.Width) / 2;
        App.Map.ViewExtents = new Extent(centerpoint.X - newwidth, centerpoint.Y - newheight, centerpoint.X + newwidth, centerpoint.Y + newheight);
        if (_combo.Owner != null) _combo.Owner.Focus(); //Remove focus because users expect focus to leave on pressing enter.


    }

    /// <summary>
    /// Gets the scale of the Maps ViewExtents.
    /// </summary>
    private void ComputeMapScale()
    {
        try
        {
            //Code posted by kellison (https://dotspatial.codeplex.com/discussions/351173)
            //const double dInchesPerMeter = 39.3700787401575;
            const double dInchesPerFeet = 12;
            const double dDegreesPerRadian = 57.2957;
            double dMapWidthInFeet;

            if (App.Map.Projection == null)
                return;

            if (App.Map.Projection.IsLatLon)
            {
                var dMapWidthInRadians = App.Map.ViewExtents.Width * App.Map.Projection.GeographicInfo.Unit.Radians;
                var dMapWidthInDegrees = dMapWidthInRadians * dDegreesPerRadian;
                var dMapLatInRadians = App.Map.ViewExtents.Center.Y * App.Map.Projection.GeographicInfo.Unit.Radians;
                var dMapLatInDegrees = dMapLatInRadians * dDegreesPerRadian;
                dMapWidthInFeet = FeetFromDecimalDegreesPoints(0.0, dMapLatInDegrees, dMapWidthInDegrees, dMapLatInDegrees);
            }
            else
            {
                dMapWidthInFeet = App.Map.ViewExtents.Width * App.Map.Projection.Unit.Feets;
            }

            // Get the number of pixels in one screen inch.
            // get resolution, most screens are 96 dpi, but you never know...
            double dScreenWidthInFeet = (Convert.ToDouble(App.Map.BufferedImage.Width) / App.Map.BufferedImage.HorizontalResolution) / dInchesPerFeet;
            double dFeetPerScreenFoot = (dMapWidthInFeet)  / (dScreenWidthInFeet) ;
            string res = "1 : " + dFeetPerScreenFoot.ToString("n0", CultureInfo.CurrentCulture);
            int index = _combo.Items.IndexOf(res);
            _ignore = true;
            if (index > -1)
            {
                _combo.SelectedIndex = index;
            }
            else
            {
                _combo.Items[0] = "1 : " + dFeetPerScreenFoot.ToString("n02", CultureInfo.CurrentCulture);
                _combo.SelectedIndex = 0;
            }
            _ignore = false;
        }
        catch (Exception)
        {
            // added this catch because in debug mode _combo is accessed from a different threat that causes unwanted errors
            // can this error be removed differently?
        }
    }

    /// <summary>
    /// Uses spherical approximation method to return distance in meters between two decimal degree points.
    /// </summary>
    /// <param name="dDegX1"></param>
    /// <param name="dDegY1"></param>
    /// <param name="dDegX2"></param>
    /// <param name="dDegY2"></param>
    /// <returns></returns>
    private static double FeetFromDecimalDegreesPoints(double dDegX1, double dDegY1, double dDegX2, double dDegY2)
    {
        //Code posted by kellison (https://dotspatial.codeplex.com/discussions/351173)
        try
        {
            const double dRadius = 20925196.85; //6378007;//6378000 // radius of Earth in feets
            const double dCircumference = dRadius * 2 * Math.PI;
            const double dFeetPerLatDd = 364545.6660105;
            //111113.519;// in Meters

            double dDeltaXdd = Math.Abs(dDegX1 - dDegX2);
            double dDeltaYdd = Math.Abs(dDegY1 - dDegY2);
            double dCenterY = (dDegY1 + dDegY2) / 2.0;
            double dFeetPerLongDd = (Math.Cos(dCenterY * (Math.PI / 180.0)) * dCircumference) / 360.0;
            double dDeltaXFeet = dFeetPerLongDd * dDeltaXdd / 0.12;
            double dDeltaYFeet = dFeetPerLatDd * dDeltaYdd / 0.12;

            return Math.Sqrt(Math.Pow(dDeltaXFeet, 2.0) + Math.Pow(dDeltaYFeet, 2.0));
        }
        catch { return 0.0; }
    }

    #endregion
}

Viewing all articles
Browse latest Browse all 3973

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>