Re: gdal-dev Digest, Vol 267, Issue 6
Bhanu Gundugollu via gdal-dev <[email protected]>
| Newsgroups | gmane.comp.gis.gdal.devel |
|---|---|
| Message-ID | <CAHEJf+F1vDaosrb2BX5vDxSURaHZ4VS5rJu64x0HgQf2kfk+2A@mail.gmail.com> |
On Fri, Aug 14, 2026 at 5:58 AM <[email protected]> wrote: > Send gdal-dev mailing list submissions to > [email protected] > > To subscribe or unsubscribe via the World Wide Web, visit > https://lists.osgeo.org/mailman/listinfo/gdal-dev > or, via email, send a message with subject or body 'help' to > [email protected] > > You can reach the person managing the list at > [email protected] > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of gdal-dev digest..." > > > Today's Topics: > > 1. Re: AutoIdentifyEPSG() fails on standard ESRI-dialect > NAD83/UTM .prj (proj_identify succeeds); FindMatches() also > missing from Java bindings (Barry DeZonia) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Thu, 13 Aug 2026 19:28:00 -0500 > From: Barry DeZonia <[email protected]> > To: Tom Moore <[email protected]> > Cc: Even Rouault <[email protected]>, > [email protected] > Subject: Re: [gdal-dev] AutoIdentifyEPSG() fails on standard > ESRI-dialect NAD83/UTM .prj (proj_identify succeeds); FindMatches() > also missing from Java bindings > Message-ID: > <CAKcvfuT0AFzHboG8uiWwkGZ6MowhfjUUtQZPB4gvBmeX= > [email protected]> > Content-Type: text/plain; charset="utf-8" > > One maybe nonsense question: where does panConfidence4 come from? Are you > using an undeclared variable? > > On Thu, Aug 13, 2026 at 7:24?PM Barry DeZonia <[email protected]> wrote: > > > My foggy memory tells me that this looks good. I will let you and > > Even figure out the PR issue. > > > > On Thu, Aug 13, 2026 at 6:56?PM Tom Moore <[email protected]> wrote: > > > >> Thanks for offering to take a look. I have a working draft already, but > >> I'm not sure if I'm taking the right approach and could use a review. > >> > >> The signature translation itself is the easy part. The C# binding in > >> osr.i was an almost perfect example, and this is what I changed it to: > >> > >> #ifdef SWIGJAVA > >> OSRSpatialReferenceShadow** FindMatches( char** options, int* > >> nvalues, int** confidence_values ) > >> { > >> return (OSRSpatialReferenceShadow**) OSRFindMatches(self, > >> options, nvalues, confidence_values); > >> } > >> #endif > >> > >> Everything interesting (haha, challenging) turned out to be in > >> typemaps_java.i, getting SWIG to actually expose that return value and > the > >> two output parameters sensibly in Java. I haven't used swig in a long > >> time, so I had forgotten most of the incantations. Llm to the rescue. > >> > >> Here is the addition to typemaps_java.i: > >> == start == > >> %typemap(in,numinputs=0) int* nvalues (int nMatches = 0) > >> { > >> /* %typemap(in,numinputs=0) int* nvalues */ > >> $1 = &nMatches; > >> } > >> > >> %typemap(in) int** confidence_values (int* panConfidence = NULL) > >> { > >> /* %typemap(in) int** confidence_values. Ignore the input, > >> keep $input around so argout can write the real > >> result into element [0]. */ > >> $1 = &panConfidence; > >> } > >> > >> %typemap(argout) int** confidence_values > >> { > >> /* %typemap(argout) int** confidence_values will fill the caller's > >> int[][] */ > >> if ($input && jenv->GetArrayLength($input) >= 1) { > >> jintArray confArray = jenv->NewIntArray(nMatches3); > >> jenv->SetIntArrayRegion(confArray, 0, nMatches3, > >> (jint*)panConfidence4); > >> jenv->SetObjectArrayElement($input, 0, confArray); > >> jenv->DeleteLocalRef(confArray); > >> } > >> CPLFree(panConfidence4); > >> } > >> > >> %typemap(jni) int** confidence_values "jobjectArray" > >> %typemap(jtype) int** confidence_values "int[][]" > >> %typemap(jstype) int** confidence_values "int[][]" > >> %typemap(javain) int** confidence_values "$javainput" > >> > >> %typemap(out) (OSRSpatialReferenceShadow**) > >> { > >> const jclass srsClass = > >> jenv->FindClass("org/gdal/osr/SpatialReference"); > >> const jmethodID srsCtor = jenv->GetMethodID(srsClass, "<init>", > >> "(JZ)V"); > >> > >> jresult = jenv->NewObjectArray(nMatches3, srsClass, NULL); > >> for (int i = 0; i < nMatches3; i++) { > >> OSRReference(result[i]); > >> jobject srsObj = jenv->NewObject(srsClass, srsCtor, > (jlong)result[i], > >> (jboolean)true); > >> jenv->SetObjectArrayElement(jresult, i, srsObj); > >> jenv->DeleteLocalRef(srsObj); > >> } > >> OSRFreeSRSArray(result); > >> } > >> > >> %typemap(jni) OSRSpatialReferenceShadow** "jobjectArray" > >> %typemap(jtype) OSRSpatialReferenceShadow** > >> "org.gdal.osr.SpatialReference[]" > >> %typemap(jstype) OSRSpatialReferenceShadow** > >> "org.gdal.osr.SpatialReference[]" > >> %typemap(javaout) OSRSpatialReferenceShadow** { > >> return $jnicall; > >> } > >> == end == > >> > >> The nvalues argument stays hidden (numinputs=0), while confidence_values > >> becomes visible as an int[][] out-box, following the same > >> caller-passes-a-1-element-array-and-we-fill-it idiom already used > elsewhere > >> in typemaps_java.i (the GDALDimensionHS** pattern was the model here). > >> > >> SWIG auto-suffixes typemap-declared local variables with the argument's > >> position in the full parameter list to avoid collisions. FOr example, a > >> variable I declared as (int nMatches = 0) inside the nvalues typemap > >> (argument position 3) actually gets emitted into the generated code as > >> nMatches3, not nMatches. This isn't visible from the .i source at all, I > >> only found it by examining the generated osr_wrap.cpp after a failed > >> compile. Any other typemap block that needs to reference that same > variable > >> (the argout/out blocks) has to hardcode the anticipated suffixed name > >> directly because SWIG doesn't rewrite references for you. > >> > >> End result: > >> > >> public SpatialReference[] FindMatches(Vector options, int[][] > >> confidenceValuesOut) > >> > >> The function returns an array of matches (SpatialReference[] as > >> OSRSpatialReferenceShadow**), which is the primary thing that you want > to > >> get from this function. > >> > >> How to use: > >> int[][] confidence = new int[1][]; > >> SpatialReference[] matches = srs.FindMatches(null, confidence); > >> int[] confidenceValues = confidence[0]; > >> > >> Patched against the current master. Tested on against an esri shapefile > >> .prj (ESRI-dialect NAD83 / UTM zone 11N WKT) that AutoIdentifyEPSG() > fails > >> on with 'Unsupported SRS' -- FindMatches() correctly returns a single > >> match, EPSG:26911, with confidence[0][0] = 100, matching projinfo > >> --identify exactly on the same input. Not tested any further than that. > >> > >> How does this look so far? Is this going in the right direction? If > so, > >> what would it take to turn this into an acceptable PR? > >> > >> Thanks again for your help, and full disclosure, thanks to llm for > >> significant assistance on this. > >> Tom > >> > >> On Thu, Aug 13, 2026, at 5:16 PM, Barry DeZonia wrote: > >> > >> AI is helping me remember > >> > >> for the FindMatches() routine would you want it matching as close as > >> possible C types or would you want a simplified API for Java that mogt > >> communicate info via an array of strings (or one formatted string). > Sorry > >> if that sounds out of left field. > >> > >> One AI said this: > >> 2. Handle Java JNI Typemaps > >> Because int** and object arrays (OSRSpatialReferenceShadow***) do not > >> map cleanly to standard Java types, you must ensure your SWIG > configuration > >> or a companion helper helper translates them into manageable objects on > the > >> Java side. > >> Alternatively, if dealing with direct pointer manipulation via SWIG > >> typemaps is too complex, developers routinely implement a *custom C++ > >> wrapper function* inside osr.i that bundles the results into a string > >> format (such as an array of matching EPSG strings and confidences) > before > >> passing it over the JNI boundary: > >> > >> swig > >> > >> %extend OSRSpatialReferenceShadow { > >> // A simplified wrapper returning matches as formatted string > arrays to avoid pointer hell > >> char** FindMatchesSimple(char** options) { > >> int nEntries = 0; > >> int* panConfidence = NULL; > >> OGRSpatialReferenceH* pahSRS = > OGRSpatialReference_FindMatches(self, options, &nEntries, &panConfidence); > >> > >> char** papszResult = NULL; > >> // Construct a structured string array containing > "EPSG:Code,Confidence" > >> for(int i = 0; i < nEntries; i++) { > >> const char* pszAuthName = > OGRSpatialReference_GetAttrValue(pahSRS[i], "AUTHORITY", 0); > >> const char* pszAuthCode = > OGRSpatialReference_GetAttrValue(pahSRS[i], "AUTHORITY", 1); > >> // Format string logic, append to papszResult... > >> // BDZ - TODO - NOTE - This is the real work needed to > finish this method. > >> } > >> > >> OSRFreeSRSArray(pahSRS); > >> CPLFree(panConfidence); > >> return papszResult; > >> } > >> } > >> > >> > >> On Thu, Aug 13, 2026 at 3:08?PM Barry DeZonia <[email protected]> > wrote: > >> > >> I could maybe help here but, good god, it's been a long time since I've > >> worked on the Java bindings and I remember almost nothing. Maybe if I > >> inspect the Java bindings code I will remember some stuff. Naively, the > >> function signature looks pretty simple to translate. > >> > >> On Thu, Aug 13, 2026 at 6:53?AM Even Rouault via gdal-dev < > >> [email protected]> wrote: > >> > >> > >> Tom, > >> > >> yes FindMatches() is what is needed for your use case and it is not > >> currently available in the Java bindings. That would require someone to > >> write the appropriate typemap(s) to map the C types to Java types. > >> > >> Even > >> Le 13/08/2026 ? 13:15, Tom Moore via gdal-dev a ?crit : > >> > >> Hi all, > >> > >> I'm running into a case where SpatialReference.AutoIdentifyEPSG() fails > >> on a completely standard, well-formed ESRI-dialect .prj file, even > though > >> the underlying PROJ identification machinery (proj_identify(), as > exercised > >> via "projinfo --identify") resolves it correctly with 100% confidence. > I'd > >> like to know whether this is a known limitation, and whether there's a > >> recommended workaround for Java bindings users specifically, since > >> FindMatches() isn't exposed there. > >> > >> Environment: > >> - GDAL 3.11.1 (Windows build) > >> - PROJ 9.6.2 > >> - Java bindings (org.gdal.osr / SWIG) > >> > >> Input WKT (contents of a shapefile .prj, ESRI dialect): > >> > >> > >> > PROJCS["NAD_1983_UTM_Zone_11N",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-117.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]] > >> > >> QGIS correctly identifies this as EPSG:26911. > >> > >> What I tried (Java): > >> > >> SpatialReference srs = new SpatialReference(); > >> srs.ImportFromESRI(lines); // also tried plain ImportFromWkt() but > >> got the same result > >> srs.SetAxisMappingStrategy(osrConstants.OAMS_TRADITIONAL_GIS_ORDER); > >> > >> try { > >> srs.AutoIdentifyEPSG(); > >> } catch (Exception ex) { > >> System.out.println("Exception: " + ex.getMessage()); > >> } > >> System.out.println("code = " + srs.GetAuthorityCode(null)); > >> > >> Result: > >> > >> Exception: OGR Error: Unsupported SRS > >> code = null > >> > >> gdal.GetLastErrorType() / GetLastErrorMsg() are empty. No additional > >> diagnostic detail is surfaced beyond the generic exception. > >> > >> I ruled out several things before suspecting this is a > AutoIdentifyEPSG() > >> limitation rather than an environment/config issue on my end: > >> > >> 1. proj.db itself is correct. Confirmed by mounting the exact same > >> proj.db (from the PROJ 9 data directory used by my JAva app) into a > clean > >> ghcr.io/osgeo/gdal:ubuntu-small-latest container and running > >> `gdalsrsinfo -e` against the same .prj file. It resolved to EPSG:26911 > >> correctly, full WKT2 with all authority IDs. > >> 2. PROJ_LIB / PROJ_DATA environment variables are set correctly and > >> confirmed using System.getenv() to be visible to the process > >> 3. Tried MorphFromESRI() (both via ImportFromESRI() alone, and combined > >> with an explicit MorphFromESRI() call) - no change. > >> 4. Tried explicit SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER) > >> before calling AutoIdentifyEPSG() - no change. > >> 5. Ran the projinfo.exe from the gdal build that I am using with the > Java > >> app directly against the same .prj file: > >> > >> projinfo.exe --identify fmu.prj > >> ... > >> Identification match count: 1 > >> EPSG:26911: 100 % > >> > >> So proj_identify() / FindMatches()-equivalent logic resolves this WKT > >> perfectly in the exact same native build, but AutoIdentifyEPSG() fails > on > >> it. > >> > >> This looks consistent with a few things I found in the tracker/mailing > >> list archives while investigating: > >> > >> - https://trac.osgeo.org/gdal/ticket/6188 -- maintainer comment noting > >> AutoIdentifyEPSG() has "very limited capabilities" and would need fuzzy > >> matching to handle inexact datum/ellipsoid names, "especially when > dealing > >> with WKT coming from ESRI." > >> - https://github.com/OSGeo/gdal/issues/4038 -- near-identical repro WKT > >> (ESRI-dialect UTM), with a maintainer noting AutoIdentifyEPSG() can > return > >> OGRERR_UNSUPPORTED_SRS while having still injected partial AUTHORITY > tags > >> into sub-nodes. This matches what I see when printing the WKT after the > >> failed call (DATUM gets EPSG:6269, but the top-level PROJCS never gets > >> an ID). > >> - https://github.com/OSGeo/gdal/issues/2303 -- shows the standard > Python > >> workaround (fall back to FindMatches() when AutoIdentifyEPSG() fails), > >> which leads to my second question below. > >> > >> Questions: > >> > >> 1. Is AutoIdentifyEPSG() failing on this ESRI-dialect NAD83/UTM WKT a > >> known limitation, or does this look like a genuine regression/bug worth > >> filing? > >> 2. FindMatches() does not appear to be exposed in the Java SWIG bindings > >> (org.gdal.osr.SpatialReference). Is that correct, or am I missing > >> something? If it's genuinely absent, is there any appetite for adding > it, > >> given it's the documented fallback for exactly this situation in other > >> language bindings? > >> 3. Short of shelling out to "projinfo --identify" as a subprocess, is > >> there a recommended in-process approach for Java bindings users to reach > >> the same identification logic? > >> > >> Happy to provide a minimal reproducible test case / file a tracker issue > >> if that's useful, but I wanted to check here first in case this is > already > >> understood behavior. > >> > >> Thanks, > >> Tom > >> > >> > >> _______________________________________________ > >> gdal-dev mailing [email protected]:// > lists.osgeo.org/mailman/listinfo/gdal-dev > >> > >> -- http://www.spatialys.com > >> My software is free, but my time generally not. > >> LLMs contribute to global warming and brain rot. > >> Let's guillotine them! "Ah ! ?a ira, ?a ira, ?a ira !" > >> > >> _______________________________________________ > >> gdal-dev mailing list > >> [email protected] > >> https://lists.osgeo.org/mailman/listinfo/gdal-dev > >> > >> > >> -- > >> Tom Moore > >> Spatial Planning Systems > >> 960 Burkes Bluff Lane > >> Deep River ON K0J 1P0 > >> Canada > >> > >> Phone: +1 613 584 9354 > >> > >> > -------------- next part -------------- > An HTML attachment was scrubbed... > URL: < > http://lists.osgeo.org/pipermail/gdal-dev/attachments/20260813/1850b865/attachment.htm > > > > ------------------------------ > > Subject: Digest Footer > > _______________________________________________ > gdal-dev mailing list > [email protected] > https://lists.osgeo.org/mailman/listinfo/gdal-dev > > > ------------------------------ > > End of gdal-dev Digest, Vol 267, Issue 6 > **************************************** > _______________________________________________ gdal-dev mailing list [email protected] https://lists.osgeo.org/mailman/listinfo/gdal-dev