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:
String [] proj4_w = new String [] {
ReplyDelete"+ Proj = tmerc",
"+ Lat_0 = 38N",
"+ Lon_0 = 127.00289027777777777776E",
"+ Ellps = bessel",
"+ Units = m",
"+ X_0 = 200000",
"+ Y_0 = 500000",
"+ K = 1.0"
;}
Point2D.Double srcProjec = null;
Point2D.Double dstProjec = null;
Projection proj = ProjectionFactory.fromPROJ4Specification (proj4_w);
srcProjec = new Point2D.Double (132,37);
dstProjec = proj.transform (srcProjec, new Point2D.Double ());
System.out.println ("TM:" + dstProjec);
/ / TM: Point2D.Double [644904.399587292, 400717.8948938238]
srcProjec = new Point2D.Double (644904.399587292, 400717.8948938238);
dstProjec = proj.inverseTransform (srcProjec, new Point2D.Double ());
I am using the above code to convert the lat/lon to another projection , but while passing the params it is givving error as a null pointer exception , could u tell me whatis the mistake
I have made available a JAR compatible with Android with references to AWT classes removed. It contains source as well as .class files and is available at
ReplyDeletehttp://www.free-map.org.uk/downloads/javalib/javaproj-1.0.6-noawt.jar.
Hi,
ReplyDeleteI am facing an issue in my app i.e. suppose i have a map view and a list view, i select an area to be searched in map view but do the actual search in list view, now i get lots of deal in response but only those POIs will be displayed which fall under the currently selected area in map view, i dont want to use the mapview projection because it can change even if someone zoom and pan around but dint select the area to search (or the final area to be searched is not changed for me but the projections has changed) so now it can affect my POIs to be displayed in list view.
please help me in this regard.
Thanks
DC
I can't get the library to work (com.jhlabs.map.proj)
ReplyDeleteUsing this info:
West_Bounding_Coordinate: -86.595961
East_Bounding_Coordinate: -77.718276
North_Bounding_Coordinate: 40.301023
South_Bounding_Coordinate: 37.815679
Map_Projection_Name: Lambert Conformal Conic
Lambert_Conformal_Conic:
Standard_Parallel: 38.666667
Standard_Parallel: 33.333333
Longitude_of_Central_Meridian: -81.450000
Latitude_of_Projection_Origin: 38.116667
False_Easting: 0.000000
False_Northing: 0.000000
I came up with this:
String[] params = {
"+proj=lcc", "+lat_1=38.666667", "+lat_2=33.333333",
"+lat_0=38.116667", "+lon_0=-81.450000", "+x_0=0", "+y_0=0",
"+ellps=GRS80", "+units=m", "+no_defs", "+datum=NAD83" };
Projection lccProjection = ProjectionFactory.fromPROJ4Specification(params);
lccProjection.initialize();
point = new Point2D.Double(5000d, 500d);
System.out.println("transform from point to latlon");
System.out.println("point: " + point.getX() + ", " + point.getY());
Point2D.Double latlon = lccDirect.inverseTransform(point, new Point2D.Double());
System.out.println("latlon: " + latlon.getX() + ", " + latlon.getY());
I chose the point (5000, 500) because when I view the TIFF there's an airport at that spot.
The airport has GPS coordinates of - 82.89188888, 39.99797222 but the inverseTransform is returning -81.3929566, 38.12116.
Any ideas what I'm doing wrong?
Hi,
ReplyDeletei have the same problem as you Doug.
The inverseTransform method return wrong value.
Have you find a solution to fixe it ?
hello,
ReplyDeletedo you know how to create the transform point, because when i define the point var the softwre calls a library that not recognize.
import com.jhlabs.map.Point2D;
import com.jhlabs.map.proj.Projection;
import com.jhlabs.map.proj.ProjectionFactory;
import com.vividsolutions.jts.geom.Point;
public class Conversion {
String name = "epsg:3785";
Projection origen = ProjectionFactory.getNamedPROJ4CoordinateSystem(name);
Point pEpsg3785 = origen.transform(-117.5931084, 34.1063989); //here's the wrong.....
public double x(){
}
}
thank's
All Proj4 libraries are SHIT and are probably untested.
ReplyDelete