# $.geo.proj object

The $.geo namespace has a property named proj which is a JavaScript object having four functions: fromGeodetic, fromGeodeticPos, toGeodetic, and toGeodeticPos. These four functions allow all $.geo static bbox/geometry functions, geomap widget properties, geomap widget events & geomap widget methods (collectively referred to as plugin functions from now on) to work in geodetic (lon, lat) coordinates.

Consider the following example:

- assume you are using the default map service
- you call $.geo.distance passing two geodetic Point objects, i.e., the GeoJSON position in each point is an array where coordinates[0] is the longitude and coordinates[1] is latitude

jQuery Geo will first convert the points to map units, a process called projection. jQuery Geo needs projected coordinates to properly calculate some relationships between shapes. After converting the points, $.geo.distance can then calculate the distance between them. This distance will be in meters because the default map service is web mercator meters.

In order to work directly in map units, you used to have to set $.geo.proj to null. While still valid, you no longer have to do this. You can leave $.geo.proj set to, e.g., web mercator meters and send either projected web mercator GeoJSON geometry objects or geodetic (lon, lat) objects to $.geo functions. The return value will depend on the type of arguments passed.

The geomap widget keeps track of how you set options. For example, if you set the map's center using geodetic coordinates, geodetic coordinates will then be returned when you ask for the center later. They will also be used when the geomap widget triggers events such as bboxchange or shape.

The default $.geo.proj object comes pre-built with functions that quickly convert between geodetic coordinates and web mercator meters so you can start using lon, lat right away with the default OpenStreetMap-based tiles. If your map service uses a different projection you can roll your own $.geo.proj object and continue to have the option to use geodetic coordinates. Read Other projections below for information on how to do that.

### Usage

The two base functions, fromGeodetic and toGeodetic, can take and return: a single bounding box, a single GeoJSON position (Point.coordinates), an array of GeoJSON positions (MultiPoint.coordinates or LineString.coordinates), an array of arrays of positions (MultiLineString.coordinates or Polygon.coordinates) or an array of arrays of arrays of positions (MultiPolygon.coordinates). In other words, the $.geo.proj functions convert the coordinates property of any of the GeoJSON geometry types. For example, you can use the following to convert the position contained in a GeoJSON point object:

    var geodeticPoint = {
      type: "Point",
      coordinates: [ -73.5100, 41.3500 ]
    };

    var projectedCoords = $.geo.proj.fromGeodetic( geodeticPoint.coordinates );

However, a LineString's coordinates property is an array of positions which you can also pass to the fromGeodetic method to get an array converted positions

    var projectedLineStringCoords = $.geo.proj.fromGeodetic( geodeticLineString.coordinates );

To convert a set of projected GeoJSON positions back to web mercator, call toGeodetic.

    var geodeticLineString = {
      type: "LineString",
      coordinates: $.geo.proj.toGeodetic( projectedLineStringCoords  )
    };

### Other projections

The $.geo.proj object allows you to use geodetic coordinates with whichever coordinate system or projection you want in any plugin function. If you pass a geodetic Polygon to $.geo.bbox, the returned bounding box will be in geodetic coordinates.

If you are working in a projection other than the default web mercator meters but still wish to use geodetic coordinates, you will have to update the $.geo.proj object so that it can convert between geodetic coordinates and ones in your projection.

However, if you don't need to work in longitude, latitude at all, you can ignore $.geo.proj and use projected coordinates throughout your project. You also still have the option to set $.geo.proj to null for completeness and remind yourself that you are limited to projected coordinates. If you are working in Massachusetts Mainland State Plane meters for example, you can pass a Polygon of that projection to any plugin function and you will get results in that projection. This includes all $.geo functions and geomap options & methods.

    $.geo.proj = null; // not required but reminds us that jQuery Geo can't use lon, lat in this project

    $('map').geomap( {
      tilingScheme: null,
      bboxMax: [ 31790, 790195, 337250, 961865 ],
      bbox: [ 235644, 894775, 237775, 898523 ],
      services: [ /* service object that supports MA State Plane */ ]
    } );

jQuery Geo uses the four $.geo.proj functions throughout to convert between geodetic and projected coordinates. However, fromGeodeticPos and toGeodeticPos handle the conversion of individual GeoJSON positions and are used by fromGeodetic and toGeodetic. You can extend $.geo.proj with your own implementations of fromGeodeticPos and toGeodeticPos to change the internal projection used by all plugin functions and still use geodetic (lon, lat) coordinates as arguments and return values.

Please note that you must extend $.geo.proj with new functionality instead of replacing it wholesale with a new object. You need to keep the original fromGeodetic and toGeodetic functions intact.

    $.extend($.geo.proj, {
      fromGeodeticPos: function( coordinate ) {
        var converted = [];
        // convert the GeoJSON lon/lat position to MA State Plane
        return converted;
      },

      toGeodeticPos: function( coordinate ) {
        var converted = [];
        // convert the GeoJSON MA State Plane position to lon/lat
        return converted;
      }
    });

    $('map').geomap( {
      tilingScheme: null,

      // notice that with a custom $.geo.proj object,
      // these properties can be in geodetic coordinates
      bboxMax: [ -73.5100, 41.3500, -69.8600, 42.8900 ],
      bbox: [ -71.098709, 42.330322, -71.072617, 42.351608 ],

      // the services option must still be in map coordinates
      // see geomap's services property docs for more info
      services: [ /* service object that supports MA State Plane */ ]
    } );

Implementing custom from/to GeodeticPos functions is currently beyond the scope of this documentation but reading up on Proj4js is a good start.