ngageoint / geopackage-android

GeoPackage Android Library
http://ngageoint.github.io/geopackage-android
MIT License
94 stars 32 forks source link

Prj4j - problem with some unsupported projection parameters #53

Closed osedok closed 3 years ago

osedok commented 5 years ago

Hi Brian, the project is using prj4j (java version) of the library to do coordinates transformations. In most cases this is fine, however some operations are not supported on Java version e.g.

If you would like to apply EPSG: 3375 which has got the definition:

+proj=omerc +lat_0=4 +lonc=102.25 +alpha=323.0257964666666 +k=0.99984 +x_0=804671 +y_0=0 +no_uoff +gamma=323.1301023611111 +ellps=GRS80 +units=m +no_defs

no_uoff and gamma parameters are not supported by prj4j

Would you consider using Native C++ compilation of Prj4 in the future?

Currently it fails at:

Proj4Parser.java

public CoordinateReferenceSystem parse(String name, String[] args)
  {
    if (args == null)
      return null;

    Map params = createParameterMap(args);
    Proj4Keyword.checkUnsupported(params.keySet());
    DatumParameters datumParam = new DatumParameters();
    parseDatum(params, datumParam);
    parseEllipsoid(params, datumParam);
    Datum datum = datumParam.getDatum();
    Ellipsoid ellipsoid = datum.getEllipsoid(); 
    // TODO: this makes a difference - why?
    // which is better?
//    Ellipsoid ellipsoid = datumParam.getEllipsoid(); 
    Projection proj = parseProjection(params, ellipsoid);
    return new CoordinateReferenceSystem(name, args, datum, proj);
  }

Proj4Keyword.checkUnsupported(params.keySet());

Supported parameters are:

public static synchronized Set supportedParameters()
  {
    if (supportedParams == null) {
      supportedParams = new TreeSet<String>();

      supportedParams.add(a);
      supportedParams.add(rf);
      supportedParams.add(f);
      supportedParams.add(alpha);
      supportedParams.add(es);
      supportedParams.add(b);
      supportedParams.add(datum);
      supportedParams.add(ellps);

      supportedParams.add(R_A);

      supportedParams.add(k);
      supportedParams.add(k_0);
      supportedParams.add(lat_ts);
      supportedParams.add(lat_0);
      supportedParams.add(lat_1);
      supportedParams.add(lat_2);
      supportedParams.add(lon_0);
      supportedParams.add(lonc);

      supportedParams.add(x_0);
      supportedParams.add(y_0);

      supportedParams.add(proj);
      supportedParams.add(south);
      supportedParams.add(towgs84);
      supportedParams.add(to_meter);
      supportedParams.add(units);
      supportedParams.add(zone);

      supportedParams.add(title);       // no-op
      supportedParams.add(no_defs);     // no-op
      supportedParams.add(wktext);      // no-op
      supportedParams.add(nadgrids);    // no-op for now

    }
    return supportedParams;
  }

Kind Regards, Andrzej Bieniek

bosborn commented 5 years ago

The simple-features-proj-java project is currently being swapped to locationtech proj4j. You could try it on their version and submit a pull request or issue if it doesn't work.

osedok commented 5 years ago

Thanks Brian, I will get this checked.

but looks like it should be fine - https://github.com/locationtech/proj4j/blob/master/src/main/java/org/locationtech/proj4j/parser/Proj4Keyword.java:

            .....
            supportedParams.add(gamma);       // Just for Oblique Mercator projection
            supportedParams.add(no_uoff);     // no-op

Kind Regards, Andrzej

bosborn commented 5 years ago

Awesome. @willcohen reached out to me, so seems like they are invested in keeping the project active.

osedok commented 5 years ago

@bosborn Hi Brian, I could use projection 3375, however I am running into similar problem as described here:

https://gis.stackexchange.com/questions/261723/proj4js-gives-wrong-result-for-epsg3375

for: 3.06268465621428, 101.70979078430528 (lat,lon)

I am getting 744626.6428051005, -103618.62269607143 result.

Expected: 412597.532715, 338944.957259

I have raised the issue with locationtech https://github.com/locationtech/proj4j/issues/21 - let's see what they say.

Kind Regards, Andrzej

sunshine0576 commented 5 years ago

主要问题在于投影原点的定义问题,是以赤道为中心,还是以投影点为中心的问题。 java 代码 if (!this.rot) { xy.x = us; xy.y = vs; } else { xy.x = (vs this.cosrot + us this.sinrot); xy.y = (us this.cosrot - vs this.sinrot); } C++ 的代码 if (Q->no_rot) { //u -= Q->u_0;区别于 天宝软件默认这里也要计算一下 xy.x = u; xy.y = v; } else { u -= Q->u_0; xy.x = v Q->cosrot + u Q->sinrot; xy.y = u Q->cosrot - v Q->sinrot; }

其中:u_0 的计算方法 if (no_off) Q->u_0 = 0; else { Q->u_0 = fabs(Q->ArB atan(sqrt(D D - 1.) / cos(alpha_c))); if (P->phi0 < 0.) Q->u_0 = - Q->u_0;

sunshine0576 commented 5 years ago

The main reason for this problem is the problem of defining the origin, and the result differs by only one constant.

dx=u_0 sinrot; dy=u_0 cosrot ;

bosborn commented 3 years ago

Fixed by locationtech proj4j 1.1.3, a sub dependency of release 6.0.0