Overview
The Open Mobile Maps SDK supports multiple coordinate systems and provides seamless conversion between them. Understanding coordinate systems is essential for working with different data sources, rendering, and spatial calculations.
Coordinate Systems
The SDK supports several standard coordinate systems through CoordinateSystemIdentifiers:
Internal rendering coordinate system used by the map engine
Unit Sphere Polar coordinates (phi, theta, radius) with Earth as a unit sphere
Coord Structure
All coordinates are represented using the Coord struct:
struct Coord {
int32_t systemIdentifier; // Which coordinate system
double x; // Longitude, easting, or phi
double y; // Latitude, northing, or theta
double z; // Elevation or radius
Coord ( int32_t system , double x , double y , double z )
: systemIdentifier (system), x (x), y (y), z (z) {}
};
Common Coordinate Examples
// WGS84 (GPS coordinates) - New York City
Coord nyc_wgs84 (
CoordinateSystemIdentifiers :: EPSG4326 (),
- 74.006 , // longitude
40.7128 , // latitude
0.0 // elevation
);
// Web Mercator - Same location
Coord nyc_mercator (
CoordinateSystemIdentifiers :: EPSG3857 (),
- 8238310.0 , // x in meters
4970241.0 , // y in meters
0.0
);
// Swiss LV03+ - Zurich
Coord zurich (
CoordinateSystemIdentifiers :: EPSG2056 (),
2683141.0 , // easting
1247952.0 , // northing
408.0 // elevation
);
CoordinateConversionHelperInterface
The main interface for coordinate conversion:
class CoordinateConversionHelperInterface {
public:
// Create independent instance (not tied to map)
static std :: shared_ptr < CoordinateConversionHelperInterface > independentInstance ();
// Register custom coordinate converter
virtual void registerConverter (
const std :: shared_ptr < CoordinateConverterInterface > & converter
) = 0 ;
// Convert single coordinate
virtual Coord convert ( int32_t to , const Coord & coordinate ) = 0 ;
// Convert bounding box
virtual RectCoord convertRect ( int32_t to , const RectCoord & rect ) = 0 ;
// Convert to render system
virtual Coord convertToRenderSystem ( const Coord & coordinate ) = 0 ;
virtual RectCoord convertRectToRenderSystem ( const RectCoord & rect ) = 0 ;
// Convert quadrilateral
virtual QuadCoord convertQuad ( int32_t to , const QuadCoord & quad ) = 0 ;
virtual QuadCoord convertQuadToRenderSystem ( const QuadCoord & quad ) = 0 ;
};
Basic Coordinate Conversion
Converting Between Systems
// Create conversion helper
auto converter = CoordinateConversionHelperInterface :: independentInstance ();
// Convert WGS84 to Web Mercator
Coord wgs84 ( - 74.006 , 40.7128 , 0.0 , CoordinateSystemIdentifiers :: EPSG4326 ());
Coord mercator = converter -> convert (
CoordinateSystemIdentifiers :: EPSG3857 (),
wgs84
);
// Convert back to WGS84
Coord backToWgs84 = converter -> convert (
CoordinateSystemIdentifiers :: EPSG4326 (),
mercator
);
Converting to Render System
The render system is the internal coordinate space used by the map:
// Get conversion helper from map
auto mapConverter = mapInterface -> getCoordinateConverterHelper ();
// Convert to render coordinates
Coord worldCoord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 74.006 , 40.7128 , 0.0 );
Coord renderCoord = mapConverter -> convertToRenderSystem (worldCoord);
// Use render coordinates for low-level rendering
The render system is map-specific and optimized for the map’s projection. Always use the map’s converter when converting to render coordinates.
Converting Rectangles
RectCoord Structure
struct RectCoord {
Coord bottomLeft; // Southwest corner
Coord topRight; // Northeast corner
};
Rectangle Conversion
// Define bounding box in WGS84
RectCoord bbox_wgs84 (
Coord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 74.05 , 40.68 , 0.0 ), // SW
Coord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 73.90 , 40.85 , 0.0 ) // NE
);
// Convert to Web Mercator
RectCoord bbox_mercator = converter -> convertRect (
CoordinateSystemIdentifiers :: EPSG3857 (),
bbox_wgs84
);
// Convert to render system
RectCoord renderBounds = mapConverter -> convertRectToRenderSystem (bbox_wgs84);
Converting Quadrilaterals
QuadCoord Structure
struct QuadCoord {
Coord topLeft;
Coord topRight;
Coord bottomRight;
Coord bottomLeft;
};
Quad Conversion
QuadCoord quad_wgs84 (
Coord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 74.0 , 40.8 , 0.0 ), // TL
Coord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 73.9 , 40.8 , 0.0 ), // TR
Coord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 73.9 , 40.7 , 0.0 ), // BR
Coord ( CoordinateSystemIdentifiers :: EPSG4326 (), - 74.0 , 40.7 , 0.0 ) // BL
);
QuadCoord quad_mercator = converter -> convertQuad (
CoordinateSystemIdentifiers :: EPSG3857 (),
quad_wgs84
);
Custom Coordinate Systems
From CRS Identifier
Parse coordinate system from URN identifier:
// Parse EPSG identifier
std ::string crsUrn = "urn:ogc:def:crs:EPSG::4326" ;
int32_t systemId = CoordinateSystemIdentifiers :: fromCrsIdentifier (crsUrn);
Coord coord ( systemId , - 74.006 , 40.7128 , 0.0 );
Registering Custom Converters
Implement CoordinateConverterInterface for custom projections:
class CustomConverter : public CoordinateConverterInterface {
public:
int32_t getFrom () override {
return MY_CUSTOM_SYSTEM_ID;
}
int32_t getTo () override {
return CoordinateSystemIdentifiers :: EPSG3857 ();
}
Coord convert ( const Coord & coordinate ) override {
// Implement conversion logic
double newX = transformX ( coordinate . x , coordinate . y );
double newY = transformY ( coordinate . x , coordinate . y );
return Coord ( getTo (), newX, newY, coordinate . z );
}
};
// Register converter
auto customConverter = std :: make_shared < CustomConverter >();
converter -> registerConverter (customConverter);
Utility Functions
Unit Conversion
Get conversion factor from coordinate units to meters:
// Get meters per unit for a coordinate system
double factor = CoordinateSystemIdentifiers :: unitToMeterFactor (
CoordinateSystemIdentifiers :: EPSG3857 ()
);
// Use for distance calculations
double distanceInUnits = 1000.0 ;
double distanceInMeters = distanceInUnits * factor;
Coordinate System Factory
Create coordinate system instances:
#include "CoordinateSystemFactory.h"
// Create coordinate system
auto coordSystem = CoordinateSystemFactory :: createEpsg3857 ();
auto wgs84System = CoordinateSystemFactory :: createEpsg4326 ();
Working with Map Coordinates
Getting Map’s Coordinate System
auto mapCoordSystem = mapInterface -> getCoordinateSystem ();
int32_t systemId = mapCoordSystem . identifier ;
// User provides GPS coordinates
double userLat = 40.7128 ;
double userLon = - 74.006 ;
// Create coordinate in WGS84
Coord userCoord (
CoordinateSystemIdentifiers :: EPSG4326 (),
userLon ,
userLat ,
0.0
);
// Convert to map's coordinate system
auto mapConverter = mapInterface -> getCoordinateConverterHelper ();
Coord mapCoord = mapConverter -> convert (
mapInterface -> getCoordinateSystem (). identifier ,
userCoord
);
// Use with camera
camera -> moveToCenterPosition (mapCoord, true );
Coordinate Utilities
The SDK provides CoordinatesUtil helper functions:
#include "CoordinatesUtil.h"
// Check if coordinates are valid
bool isValid = CoordinatesUtil :: isValidCoordinate (coord);
// Normalize longitude to [-180, 180]
double normalized = CoordinatesUtil :: normalizeLongitude (longitude);
// Calculate distance between coordinates (in same system)
double distance = CoordinatesUtil :: distance (coord1, coord2);
Common Use Cases
GPS to Map Coordinates
void showGpsLocation ( double latitude , double longitude ) {
Coord gpsCoord (
CoordinateSystemIdentifiers :: EPSG4326 (),
longitude,
latitude,
0.0
);
auto converter = mapInterface -> getCoordinateConverterHelper ();
auto mapSystem = mapInterface -> getCoordinateSystem (). identifier ;
Coord mapCoord = converter -> convert (mapSystem, gpsCoord);
camera -> moveToCenterPosition (mapCoord, true );
}
Converting Layer Data
void addPointsFromExternalSource (
const std :: vector < Point > & points ,
int32_t sourceSystem
) {
auto converter = CoordinateConversionHelperInterface :: independentInstance ();
auto targetSystem = mapInterface -> getCoordinateSystem (). identifier ;
for ( const auto & point : points) {
Coord sourceCoord (sourceSystem, point . x , point . y , 0.0 );
Coord mapCoord = converter -> convert (targetSystem, sourceCoord);
// Add to map layer
layer -> addPoint (mapCoord);
}
}
Multi-System Data Sources
class MultiSourceLayer : public LayerInterface {
private:
std ::shared_ptr < CoordinateConversionHelperInterface > converter;
int32_t targetSystem;
public:
void onAdded ( const std :: shared_ptr < MapInterface > & map , int32_t index ) override {
converter = map -> getCoordinateConverterHelper ();
targetSystem = map -> getCoordinateSystem (). identifier ;
}
void addDataFromSource ( const Data & data , int32_t sourceSystem ) {
// Convert all coordinates to map system
for ( const auto & item : data . items ) {
Coord sourceCoord (sourceSystem, item . x , item . y , item . z );
Coord mapCoord = converter -> convert (targetSystem, sourceCoord);
processItem (mapCoord, item);
}
}
};
Best Practices
Use independent instance for non-map conversions
When converting coordinates outside of map context (e.g., preprocessing data), use independentInstance() instead of the map’s converter.
Cache converted coordinates when possible
Coordinate conversion involves mathematical transformations. Cache results when the same coordinates are used multiple times.
Always specify the correct source system
Incorrect source coordinate system will produce wrong results. Double-check your data source’s coordinate system before converting.
Use consistent coordinate systems within layers
Keep all coordinates within a layer in the same system to avoid repeated conversions during rendering.
Be aware of coordinate system units
Some systems use degrees (EPSG4326), others use meters (EPSG3857, EPSG2056). Use unitToMeterFactor() for distance calculations.
Common Pitfalls
Longitude/Latitude order : EPSG4326 uses (longitude, latitude), not (latitude, longitude)
Elevation handling : Z-coordinate may have different meanings in different systems
Polar regions : Some projections (like Web Mercator) don’t work well near poles
Antimeridian : Coordinates near ±180° longitude require special handling
Convert coordinates once during data loading, not every frame
Batch conversions when possible to reduce function call overhead
Use render system coordinates for performance-critical rendering
Consider preprocessing data to the map’s coordinate system
Next Steps
Camera Controls Use converted coordinates with camera navigation
Custom Layers Build layers with multi-system coordinate support