First you can get the latest version (1.0.6) of PROJ4Java from this link. The size of the library is very small and lightweight with only 1.17MB for complete source code and 247KB for compiled jar file. If you’re familiar with PROJ.4 itself then this Java version should be quite straight forward, otherwise there isn’t much sample code or tutorial on its homepage. But the basic workflow is quite simple as described by its project homepage:
To use the library, you need to create a projection, either directly by calling its constructor or via one of the factory methods. Once you have a Projection, you can use it to convert between latitude/longitude and projected map units (by default, metres) by calling the transform and transformInverse methods.A major issue of using PROJ4Java on Android is that out of box it can’t be run due to the fact that it is using some classes in java.awt.geom.* which is not available in Android SDK. But since the only major AWT class used by PROJ4Java is Point2D, it’s not difficult at all to work around by replacing it with your own 2D point class. In my case I use the point class from JTS library. After taking out all Java awt class references from source code and replacing them with JTS class, everything works pretty well on Android.
Another thing I modifies on the source code is to get rid of those projection implementations I don’t need. Mercator projection is the only one I need so far so that I am able to reduce the size of compile jar file to only 168KB. Here is a list of classes I extracted from original source code to support only Mercator projection:
- com.jhlabs.map.*
- com.jhlabs.map.proj.CylindricalProjection
- com.jhlabs.map.proj.Ellipsoid
- com.jhlabs.map.proj.MercatorProjection
- com.jhlabs.map.proj.Projection
- com.jhlabs.map.proj.ProjectionFactory
- com.jhlabs.map.proj.ProjectionException
- com.jhlabs.map.proj.Ellipsoid
(1) ProjectionFactory.getNamedPROJ4CoordinateSystem(String name) takes a well-known projection code like “epsg:4326” and returns a Projection:
(2) ProjectionFactory.fromPROJ4Specification(String[] params) takes a set of PROJ.4 parameters and returns a Projection:1: String name = "epsg:3785";
2: Projection proj = ProjectionFactory.getNamedPROJ4CoordinateSystem(name);
(3) Create an instance of customized projection. All supported projection definition strings (PROJ.4 parameters for ) for PROJ4Java are listed in text files under folder “nad” that is coming with the library. These files are “epsg”, “esri”, “nad27”, “nad83”, and “world”, and a sample projection definition string is like below:1: String[] params = {2: "proj=tmerc",
3: "lat_0=37.5",
4: "lon_0=-85.66666666666667",
5: "k=0.999966667",
6: "x_0=99999.99989839978",
7: "y_0=249999.9998983998",
8: "ellps=GRS80",
9: "datum=NAD83",
10: "to_meter=0.3048006096012192",
11: "no_defs"
12: };13: ProjectionFactory.fromPROJ4Specification(params);
To add a new customized projection just create a definition string (usually modify certain parameter values upon an existing projection) and add it into one of those files, or create a new text file under “nad” folder with the definition string, then use the code below:1: <2965> +proj=tmerc +lat_0=37.5 +lon_0=-85.66666666666667 +k=0.999966667 +x_0=99999.99989839978 +y_0=249999.9998983998 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs2:
(4) Transform between lat/lon and projection units with a Projection instance:1: Projection proj = null;
2: try {
3: // assume that "epsg:900913" projection defintion
4: // has been added in text file "others"
5: proj = ProjectionFactory.readProjectionFile("others", "900913");6: } catch(IOException e) {
7: e.printStackTrace();8: }
1: Projection epsg3785 = ProjectionFactory.getNamedPROJ4CoordinateSystem("epsg:3785");
2:3: System.out.println("transform from latlon to epsg:3785");
4: System.out.println("latlon: -117.5931084, 34.1063989");
5: Point pEpsg3785 = epsg3785.transform(-117.5931084, 34.1063989);6: System.out.println("epsg:3785: " + pEpsg3785.getX() + ", " + pEpsg3785.getY());7:8: System.out.println("transform from epsg:3785 to latlon");
9: System.out.println("epsg:3785: " + pEpsg3785.getX() + ", " + pEpsg3785.getY());10: Point latlon = epsg3785.inverseTransform(pEpsg3785);11: System.out.println("latlon: " + latlon.getX() + ", " + latlon.getY());12:13: