movnet писал(а):Как определить позицию пикселя в тайле Google Map?
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
namespace SmartSystems.GeoTransform
{
public enum GeoCoordFormat
{
LDD_MM_SSSS,
LDD_MMMMMM,
LDD_DDDDDD,
SDD_MM_SSSS,
SDD_MMMMMM,
SDD_DDDDDD
}
public enum GeoPositionFormat
{
LON_LAT,
LAT_LON
}
public enum GeoHemisphere
{
N_E,
S_W
}
public enum ProjectionType
{
SPHEROID,
KRASSOVSKY_ELLIPSOID
}
public class GeoPosition
{
private double lon;
private double lat;
public double Lon
{
get { return lon; }
set
{
if ((value < -180.0) || (value > 180.0))
{
throw new ArgumentException();
}
lon = value;
}
}
public double Lat
{
get { return lat; }
set
{
if ((value < -90.0) || (value > 90.0))
{
throw new ArgumentException();
}
lat = value;
}
}
public GeoPosition(double lon, double lat)
{
if ((lon > 180.0) || (lat > 90.0))
{
throw new ArgumentOutOfRangeException();
}
this.lon = lon;
this.lat = lat;
}
public GeoPosition(GeoHemisphere lonH, int lonDD, int lonMM, double lonSS, GeoHemisphere latH, int latDD, int latMM, double latSS)
{
if ((lonDD > 180) || (lonDD < 0) || (lonMM > 60) || (lonMM < 0) || (lonSS > 60.0) || (lonSS < 0.0)
|| (latDD > 90) || (latDD < 0) || (latMM > 60) || (latMM < 0) || (latSS > 60.0) || (latSS < 0.0))
{
throw new ArgumentException();
}
if (((lonDD == 180) & ((lonMM > 0) || (lonSS > double.Epsilon)))
|| ((latDD == 90) & ((latMM > 0) || (latSS > double.Epsilon))))
{
throw new ArgumentException();
}
this.lon = (double)lonDD + (double)lonMM / 60.0 + lonSS / 3600.0;
if (lonH == GeoHemisphere.S_W)
{
this.lon = -this.lon;
}
this.lat = (double)latDD + (double)latMM / 60.0 + latSS / 3600.0;
if (latH == GeoHemisphere.S_W)
{
this.lat = -this.lat;
}
}
public GeoPosition() : this(0.0, 0.0)
{
}
public string LonToString(GeoCoordFormat f)
{
GeoHemisphere hs = (lon > 0.0) ? GeoHemisphere.N_E : GeoHemisphere.S_W;
double l = Math.Abs(lon);
switch (f)
{
case GeoCoordFormat.SDD_DDDDDD:
return ((hs == GeoHemisphere.S_W) ? "-" : "") + Math.Round(l, 6).ToString(CultureInfo.CurrentCulture) + "°";
case GeoCoordFormat.SDD_MMMMMM:
return ((hs == GeoHemisphere.S_W) ? "-" : "") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + Math.Round((l - (double)(int)l) * 60, 4).ToString(CultureInfo.CurrentCulture) + "'";
case GeoCoordFormat.SDD_MM_SSSS:
return ((hs == GeoHemisphere.S_W) ? "-" : "") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + ((int)((l - (double)(int)l) * 60)).ToString(CultureInfo.CurrentCulture) + "'" + Math.Round((((l - (double)(int)l) * 60) - (double)(int)((l - (double)(int)l) * 60)) * 60, 2).ToString(CultureInfo.CurrentCulture) + "\"";
case GeoCoordFormat.LDD_DDDDDD:
return ((hs == GeoHemisphere.S_W) ? "W" : "E") + Math.Round(l, 6).ToString(CultureInfo.CurrentCulture) + "°";
case GeoCoordFormat.LDD_MMMMMM:
return ((hs == GeoHemisphere.S_W) ? "W" : "E") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + Math.Round((l - (double)(int)l) * 60, 4).ToString(CultureInfo.CurrentCulture) + "'";
case GeoCoordFormat.LDD_MM_SSSS:
return ((hs == GeoHemisphere.S_W) ? "W" : "E") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + ((int)((l - (double)(int)l) * 60)).ToString(CultureInfo.CurrentCulture) + "'" + Math.Round((((l - (double)(int)l) * 60) - (double)(int)((l - (double)(int)l) * 60)) * 60, 2).ToString(CultureInfo.CurrentCulture) + "\"";
default:
return "";
}
}
public string LatToString(GeoCoordFormat f)
{
GeoHemisphere hs = (lat > 0.0) ? GeoHemisphere.N_E : GeoHemisphere.S_W;
double l = Math.Abs(lat);
switch (f)
{
case GeoCoordFormat.SDD_DDDDDD:
return ((hs == GeoHemisphere.S_W) ? "-" : "") + Math.Round(l, 6).ToString(CultureInfo.CurrentCulture) + "°";
case GeoCoordFormat.SDD_MMMMMM:
return ((hs == GeoHemisphere.S_W) ? "-" : "") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + Math.Round((l - (double)(int)l) * 60, 4).ToString(CultureInfo.CurrentCulture) + "'";
case GeoCoordFormat.SDD_MM_SSSS:
return ((hs == GeoHemisphere.S_W) ? "-" : "") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + ((int)((l - (double)(int)l) * 60)).ToString(CultureInfo.CurrentCulture) + "'" + Math.Round((((l - (double)(int)l) * 60) - (double)(int)((l - (double)(int)l) * 60)) * 60, 2).ToString(CultureInfo.CurrentCulture) + "\"";
case GeoCoordFormat.LDD_DDDDDD:
return ((hs == GeoHemisphere.S_W) ? "S" : "N") + Math.Round(l, 6).ToString(CultureInfo.CurrentCulture) + "°";
case GeoCoordFormat.LDD_MMMMMM:
return ((hs == GeoHemisphere.S_W) ? "S" : "N") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + Math.Round((l - (double)(int)l) * 60, 4).ToString(CultureInfo.CurrentCulture) + "'";
case GeoCoordFormat.LDD_MM_SSSS:
return ((hs == GeoHemisphere.S_W) ? "S" : "N") + ((int)l).ToString(CultureInfo.CurrentCulture) + "°" + ((int)((l - (double)(int)l) * 60)).ToString(CultureInfo.CurrentCulture) + "'" + Math.Round((((l - (double)(int)l) * 60) - (double)(int)((l - (double)(int)l) * 60)) * 60, 2).ToString(CultureInfo.CurrentCulture) + "\"";
default:
return "";
}
}
public string ToString(GeoPositionFormat pf, GeoCoordFormat cf)
{
switch (pf)
{
case GeoPositionFormat.LON_LAT:
return LonToString(cf) + " " + LatToString(cf);
case GeoPositionFormat.LAT_LON:
return LatToString(cf) + " " + LonToString(cf);
default:
return "";
}
}
}
public class GeoTransformation
{
private static readonly double e = 0.081819790992;
public static double GetTileX(double lon, int zoom, ProjectionType pt)
{
switch (pt)
{
case ProjectionType.SPHEROID:
case ProjectionType.KRASSOVSKY_ELLIPSOID:
return Math.Pow(2, (double)(zoom - 2)) * (1 + lon / 180.0);
default:
return 0.0;
}
}
public static double GetTileY(double lat, int zoom, ProjectionType pt)
{
switch (pt)
{
case ProjectionType.SPHEROID:
return Math.Pow(2, (double)(zoom - 2)) * (1 - ((Math.Log((1 + Math.Sin(lat * Math.PI / 180.0)) / (1 - Math.Sin(lat * Math.PI / 180.0)))) / 2.0) / Math.PI);
case ProjectionType.KRASSOVSKY_ELLIPSOID:
return Math.Pow(2, (double)(zoom - 2)) * (1 - ((Math.Log((1 + Math.Sin(lat * Math.PI / 180.0)) / (1 - Math.Sin(lat * Math.PI / 180.0)))) / 2.0 - e * (Math.Log((1 + e * Math.Sin(lat * Math.PI / 180.0)) / (1 - e * Math.Sin(lat * Math.PI / 180.0)))) / 2.0) / Math.PI);
default:
return 0.0;
}
}
public static double GetLon(double tileX, int zoom, ProjectionType pt)
{
switch (pt)
{
case ProjectionType.SPHEROID:
case ProjectionType.KRASSOVSKY_ELLIPSOID:
return (tileX / Math.Pow(2.0, (double)(zoom - 2)) - 1) * 180.0;
default:
return 0.0;
}
}
public static double GetLat(double tileY, int zoom, ProjectionType pt)
{
bool S = false;
if (tileY > Math.Pow(2.0, (double)(zoom - 2)))
{
S = true;
tileY = Math.Pow(2.0, (double)(zoom - 1)) - tileY;
}
double y1 = (1.0 - (tileY / Math.Pow(2.0, (double)(zoom - 2)))) * Math.PI;
double teta0 = 2.0 * Math.Atan(Math.Pow(Math.E, y1)) - Math.PI / 2.0;
switch (pt)
{
case ProjectionType.SPHEROID:
return (S ? -1 : 1) * teta0 * 180.0 / Math.PI;
case ProjectionType.KRASSOVSKY_ELLIPSOID:
double teta = CalcTeta(teta0, y1);
while (Math.Abs(teta - teta0) > 0.0000001)
{
teta0 = teta;
teta = CalcTeta(teta, y1);
}
return (S ? -1 : 1) * teta * 180.0 / Math.PI;
default:
return 0.0;
}
}
private static double CalcTeta(double teta0, double y1)
{
return Math.Asin(1.0 - (1.0 + Math.Sin(teta0)) * Math.Pow(1.0 - e * Math.Sin(teta0), e) / (Math.Pow(Math.E, 2.0 * y1 / 1.0) * Math.Pow(1 + e * Math.Sin(teta0), e)));
}
}
}
zed писал(а):movnet писал(а):Как определить позицию пикселя в тайле Google Map?
Странный вопрос... А какой пиксел интересует? И что значит "позицию"?
Вернуться в Google Maps + Google Earth™
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0