Convet tile to LatLon

209 views
Skip to first unread message

M@nu

unread,
Dec 31, 2008, 8:02:22 AM12/31/08
to route-me
Hi,

I'm trying to add a tilesource as an overlay to display a trafic maps.
I sublcass RMAbstractMecatorWebSource to get the tiles but I need to
convert the tile coordinates to EPSG : 3785 coordinates as my server
only understand this kind of coordinates (EPSG:
3785&BBOX=0.592188,47.323665,4.107812,50.33118).

Thanks for you help.
M@nu.

M@nu

unread,
Jan 5, 2009, 7:22:32 PM1/5/09
to route-me
Hi,

After looking for a way to convert tile to LatLong on this amazing
framework I found nothing , so I wrote some méthods to do this.
I subclass RMAbstractMecatorWebSource and add those methods to
convert the tiles coordinates to latlong coordinates.
If someone is interrested let me know.

M@nu.

John Baker

unread,
Jan 10, 2009, 7:30:47 PM1/10/09
to route-...@googlegroups.com
This may be helpful for my effort...

Thanks.

Joseph Gentle

unread,
Jan 11, 2009, 9:04:38 AM1/11/09
to route-...@googlegroups.com
Erm, convert a tile to mercator (xy) using RMMercatorToTileProjection,
then convert from that to latlong / whatever using RMProjection
(- (RMLatLong)pointToLatLong:(RMXYPoint)aPoint;
- (RMXYPoint)latLongToPoint:(RMLatLong)aLatLong;).

call the methods on these objects in RMMapContents:
RMProjection *projection;
id<RMMercatorToTileProjection> mercatorToTileProjection;


-J

Joseph Gentle

unread,
Jan 11, 2009, 9:05:06 AM1/11/09
to route-...@googlegroups.com
If its useful, add a method in RMMapContents to do it and share it :)

-J

M@nu

unread,
Jan 11, 2009, 3:16:20 PM1/11/09
to route-me
I need LatLong coordinates in a RMAbstractMecatorWebSource subclasss,
I tried to pass the mapview to the sublcass to call pointToLatLong
method but the results were not always accurate, so I wrote the
following code.

//
// myTraficMapsSource.m


#import "myTraficMapsSource.h"
#import "RMFractalTileProjection.h"
CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI /
180;};
CGFloat RadiansToDegrees(CGFloat radians) {return radians * 180/
M_PI;};

typedef struct {
CGPoint min;
CGPoint max;
} CGXYRect;

@implementation myTraficMapsSource

-(id) init
{
if (![super init])
return nil;
initialResolution = 2 * M_PI * 6378137 / [[self class]
tileSideLength];
//156543.03392804062 for sideLength 256 pixels
originShift = 2 * M_PI * 6378137 / 2.0;
// 20037508.342789244
return self;
}

-(NSString*) tileURL: (RMTile) tile
{
int sideLength = [[self class] tileSideLength];
RMLatLongBounds tileBounds = [self TileLatLonBounds:tile];
NSString *urlID = @"";//@"&id=1230918265386";
NSLog(@"%@ %s %f %f %f %f", [self class],_cmd,
tileBounds.northWest.longitude,tileBounds.southEast.latitude,tileBounds.southEast.longitude,tileBounds.northWest.latitude);
NSString *url = [NSString stringWithFormat:@"http://
mytrafic.beesurf.com/MapServer/SIM.aspx?CRS=EPSG:3785&BBOX=%f,%f,%f,
%f&WIDTH=%d&HEIGHT=%d
%@",tileBounds.northWest.longitude,tileBounds.southEast.latitude,tileBounds.southEast.longitude,tileBounds.northWest.latitude,sideLength,sideLength,urlID];
//NSLog(@"%@",url);
return url;
}

-(NSString*) description
{
return @"mytraficMaps";
}

// Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator
EPSG:900913
-(CGPoint) LatLonToMeters: (CLLocationCoordinate2D) latlon
{
CGPoint meters;
meters.x = latlon.longitude * originShift / 180.0;
meters.y = (log( tan((90 + latlon.latitude) * M_PI / 360.0 )) /
(M_PI / 180.0)) * originShift / 180.0;
return meters;
}

//Resolution (meters/pixel) for given zoom level (measured at Equator)
-(float) ResolutionAtZoom : (int) zoom
{
return initialResolution /pow (2,zoom);
}

// Converts pixel coordinates in given zoom level of pyramid to EPSG:
900913
-(CGPoint) PixelsToMetersAtZoom: (int) px PixelY:(int)py atZoom:(int)
zoom
{
float resolution = [self ResolutionAtZoom: zoom];
CGPoint meters;
meters.x = px * resolution - originShift;
meters.y = py * resolution - originShift;
return meters;
}

//Converts XY point from Spherical Mercator EPSG:900913 to lat/lon in
WGS84 Datum
-(CLLocationCoordinate2D) MetersToLatLon: (CGPoint) meters
{
CLLocationCoordinate2D latlon;
latlon.longitude = (meters.x / originShift) * 180.0;
latlon.latitude = (meters.y / originShift) * 180.0;

latlon.latitude = - 180 /M_PI * (2 * atan( exp( latlon.latitude *
M_PI / 180.0)) - M_PI / 2.0);
return latlon;
}

//Returns bounds of the given tile in EPSG:900913 coordinates
-(CGXYRect) TileBounds: (RMTile) tile
{
int sideLength = [[self class] tileSideLength];
CGXYRect tileBounds;
tileBounds.min = [self PixelsToMetersAtZoom: (tile.x * sideLength)
PixelY:(tile.y * sideLength) atZoom: tile.zoom ];
tileBounds.max = [self PixelsToMetersAtZoom: ((tile.x+1) *
sideLength) PixelY: ((tile.y+1) * sideLength) atZoom:tile.zoom];
return tileBounds;
}

/* Returns bounds of the given tile in latutude/longitude using WGS84
datum
* returns a Rectangle2D with x = lon degrees , y = lat degrees,
* width=lonSpan, height=latSpan
* for an x,y,zoom as used by google.
*/
-(RMLatLongBounds) TileLatLonBounds: (RMTile) tile
{
CGXYRect tileBounds =[ self TileBounds: tile];
RMLatLongBounds result;
result.northWest = [self MetersToLatLon: tileBounds.min];
result.southEast = [self MetersToLatLon: tileBounds.max];
return result;
}

@end

Joseph Gentle

unread,
Jan 11, 2009, 5:36:06 PM1/11/09
to route-...@googlegroups.com
Oh, nice.
Reply all
Reply to author
Forward
0 new messages