package com.opendoorlogistics.core.geometry.operations; import com.opendoorlogistics.api.ODLApi; import com.opendoorlogistics.api.Tables; import com.opendoorlogistics.api.tables.ODLColumnType; import com.opendoorlogistics.api.tables.ODLTable; import com.opendoorlogistics.api.tables.ODLTableReadOnly; import com.opendoorlogistics.api.tables.TableQuery.SpatialTableQuery; import com.opendoorlogistics.core.geometry.ODLGeomImpl; import com.opendoorlogistics.core.tables.ColumnValueProcessor; import com.vividsolutions.jts.geom.Envelope; /** * Execute a spatial query on table by examining each row one-by-one. * @author Phil * */ public class OneByOneSpatialQuery { private final ODLApi api; public OneByOneSpatialQuery(ODLApi api) { this.api = api; } /** * Execute a spatial query on table by examining each row one-by-one. * Only a bounding-box query is performed by for geometry, which does * not guarantee the geometry is within the query box (but is much quicker than * a complete geometry intersection query). * @param table * @param query * @return */ public ODLTableReadOnly query(ODLTableReadOnly table, SpatialTableQuery query){ Tables tables = api.tables(); ODLTable ret = (ODLTable)tables.copyTableDefinition(table, tables.createAlterableDs()); Envelope queryEnvelope = createQueryEnvelope(query); int nr = table.getRowCount(); for(int i =0 ; i < nr ; i++){ // has geom? ODLGeomImpl geom =null; boolean inBox=false; if(query.getGeomColumn()!=-1){ geom =(ODLGeomImpl)ColumnValueProcessor.convertToMe(ODLColumnType.GEOM, table.getValueAt(i, query.getGeomColumn())); if(geom!=null){ Envelope envelope = geom.getWGSBounds(); inBox = envelope!=null && queryEnvelope.intersects(envelope); } } // Test latitude and longitude if we didn't have a geometry if(!inBox && geom==null && query.getLatitudeColumn()!=-1 && query.getLongitudeColumn()!=-1){ Long lng =(Long)ColumnValueProcessor.convertToMe(ODLColumnType.LONG, table.getValueAt(i, query.getLongitudeColumn())); Long lat =(Long)ColumnValueProcessor.convertToMe(ODLColumnType.LONG, table.getValueAt(i, query.getLatitudeColumn())); if(lng!=null && lat!=null){ if(query.getMinimum()==null || (lng >= query.getMinimum().getLongitude() && lat>=query.getMinimum().getLatitude())){ if(query.getMaximum()==null || (lng < query.getMaximum().getLongitude() && lat<query.getMaximum().getLatitude())){ inBox = true; } } } } if(inBox){ tables.copyRow(table, i, ret); } } return ret; } private Envelope createQueryEnvelope(SpatialTableQuery query) { double x1,x2,y1,y2; if(query.getMinimum()!=null){ x1 = query.getMinimum().getLongitude(); y1 = query.getMinimum().getLatitude(); }else{ x1 = -Double.MAX_VALUE; y1 = -Double.MAX_VALUE; } if(query.getMaximum()!=null){ x2 = query.getMaximum().getLongitude(); y2 = query.getMaximum().getLatitude(); }else{ x2 = +Double.MAX_VALUE; y2 = +Double.MAX_VALUE; } Envelope queryEnvelope = new Envelope(x1, x2, y1, y2); return queryEnvelope; } }