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