Jon
Jon

Reputation: 833

MarkLogic search for documents containing polygons

I am trying to write a query against a MarkLogic set of documents that contain geospatial information. Searching for the documents containing points was relatively easy, but I have some documents that define polygons.

<gml:Polygon gml:id="test" srsName="EPSG:4326">
  <gml:exterior>
    <gml:LinearRing>
      <gml:pos>0 5</gml:pos>
      <gml:pos>5 10</gml:pos>
      <gml:pos>10 5</gml:pos>
      <gml:pos>5 0</gml:pos>
      <gml:pos>0 5</gml:pos>
    </gml:LinearRing>
  </gml:exterior>
</gml:Polygon>

My problem is that I cannot find a cts: or gml: type of query that will allow a user to define a polygon to search for a polygon. I can compare polygons using (http://docs.marklogic.com/6.0/cts:polygon-intersects) type of functions, but that doesn't seem to allow me to query for polygons, just compare shape objects.

Any suggestion on how to do this (or confirmation that I cannot do this) would be greatly appreciated.

Upvotes: 2

Views: 175

Answers (3)

TomD
TomD

Reputation: 1

You're close, but there are still cases where your search polygon can overlap the region in the database without covering one of the region's perimiter points.

MarkLogic Professional Services has a library that does the standard geo operations (intersects, disjoint, contains, within, overlaps, etc) over stored polygons, linestrings, boxes, circles, etc. It works by using a pre-filter step that involves a combination of forward and reverse queries based on cts:bounding-boxes and additional decorating points, leveraging the MarkLogic geo indexes. It then has a secondary step that performs fine-grained exact filter on the polygons/regions that survive the first filter, so you wind up with an exact set of matching regions.

It’s not publicly available, but you can contact your MarkLogic account manager if you want to bring in Professional Services to get access to the library.

Upvotes: 0

Jon
Jon

Reputation: 833

After a lot of trial and error trying to create a query that worked as expected, I created a solution that worked for my situation. I had documents in MarkLogic that had a mix of gml:Point and gml:Polygon information. The problem I had was trying to get a query that covered both situations when the user enters any WKT query.

An example gml:Point would be:

<gml:Point srsDimension="2" srsName="http://somesite.com">
  <gml:pos>1 1</gml:pos>
</gml:Point>

Or it could be like the gml:Polygon described in the original question.

My mindset was that I needed to query the gml:Polygon, but in fact, I needed to query the gml:LinearRing using an cts:element-child-geospatial-query query.

My final query looked like (supports both gml and gml32):

cts:or-query((
  cts:element-child-geospatial-query(
    xs:QName("gml:Point"),
    xs:QName("gml:pos"),
    $parsedGeometry
  ), 
  cts:element-child-geospatial-query(
    xs:QName("gml32:Point"),
    xs:QName("gml32:pos"),
    $parsedGeometry
  ),
  cts:element-child-geospatial-query(
    xs:QName("gml:LinearRing"),
    xs:QName("gml:pos"),
    $parsedGeometry
  ), 
  cts:element-child-geospatial-query(
    xs:QName("gml32:LinearRing"),
    xs:QName("gml32:pos"),
    $parsedGeometry
  )
))

Then adding the proper geospatial element child indexes would make the query return what I expect and give sub 0.2 second responses.

Upvotes: 0

mblakele
mblakele

Reputation: 7842

Create a cts:polygon and use it with cts:element-geospatial-query. The $regions parameter takes cts:region*, and cts:polygon is a subtype of cts:region. Once you have a cts:element-geospatial-query you can compose it with other cts:query items and use it with cts:search or search:resolve.

cts:element-geospatial-query(
  xs:QName("gml:Polygon"),
  cts:polygon(10.0, 35.0, 20.0, 40.0))

Upvotes: 2

Related Questions