Hi All, apologies in advance for the long message,
I have many documents that store WKB
(base64-encoded) geometry data (going for speed not readability). I want
to be able to do queries where I can use the geo predicate functions
with the stored WKB geometry and a provided WKT geometry. Example:
Sample document structure: <root><geoWKBdata type=xs:base64Binary/></root>
Sample query: collection()/root[geo:intersects(geo:fromWKB(geoWKBData), geo:fromWKT("LINESTRING((0,0),(1,1))"))
I have looked at the module code and the only problem is
that all methods assume an input of GML. I don't want to just make
functions to convert from WKB/WKT to GML on input because I think that
would be very inefficient (slow).
I could just hack something together for my
own needs, but I would like some input so that ideally I can produce
something good enough to contribute back to the project. Options:
1)
Add copies of all methods to accept each possible encoding type (GML,
WKB, WKT). I don't like this approach because it doesn't scale well, and
I don't even know if it's possible? (Pretty sure you can't overload
functions in XPath/XQuery)
2) Leave the Geo module the way it is and add "sister" modules for the additional encoding types. Yuck.
3) The only thing that makes sense, really. Define 3 new functions, fromGML, fromBinary, and fromText
and change the signatures of all module functions to just accept
Geometry objects. That way you can load your geometry however you want
and then pass it to the desired function. I will also modify the
functions asText and asBinary to accept a Geometry object, and add an additional asGML
so that the many existing functions that already return GML (envelope,
boundary, etc.) can instead return Geometry, and can then be converted
as needed to the desired format. This should scale well too because if
any future encoding formats are desired all you need to do is add fromXYZ and asXYZ functions.
With these functions, you could also string together 2 calls to convert
between any of the supported encoding types. Does this make sense? It
seems easy enough, am I missing anything?
Also, assume for a second that I implement #3.
Refer to my sample document/query above. As I understand it, for each
document in the collection, the back end will have to parse
"LINESTRING((0,0),(1,1))" into a Geometry first in order to compare. Is
there any way to make that happen only once for the duration of the
query? Is it as easy as this?:
let $data = geo:fromText("LINESTRING((0,0),(1,1))");
return collection()/root[geo:intersects(geo:fromWKB(geoWKBData), $data)
This would work, right? (I'm new to XQuery, sorry)
So, am I on the right track with this? Have I overlooked
some absurdly simple solution to my problem? I would appreciate any and
all input. As I said, I would like to go beyond meeting my own needs and
actually get this into the code base.
I'll leave you with this snippet taken from the EXPath Geo Module Spec:
"The data model envisioned by EXPath Geo module is abstract in the sense that it may be
possible for module implementers to support more than one encoding on input. Output data
types are specified in GML and XML Schema, where appropriate. All that is necessary is
that the input geometry be transformable to the model specified by OGC SF and supported
by the EXPath implementation. -SNIP- Implementations are not limited to GML, KML, nor even XML, on input. It is possible that
geometries encoded as “Well Known Text”, GeoJSON, or even “Well Known Binary”, among
other possibilities, could be supported by an implementation."
Thanks,
Zach