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