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]https://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 >> >>
_______________________________________________ gdal-dev mailing list [email protected] https://lists.osgeo.org/mailman/listinfo/gdal-dev
