Details
Description
All classes implementing DistanceBufferOperation are extensions of CartesianDistanceFilter, that does not take into consideration the unit measure.
Unit measure should be taken into account according to the geometry unit measures, which are usually attached to the GeometryAttributeType (inside the CRS), and sometimes to the JTS Geometry itself (the current push towards filters that work against generic objects make unit measure extraction somewhat harder, isn't it?).
If the difference in unit measure is within linear units, a simple algebraic convesion is all that is needed, whilst if we're venturing into lat/lon data versus linear distanceproblem, things become a lot more complex, and needs to be faced both in filter direct evaluation, and filter encoding into database queries (so it becomes a jdbc datastore wide issue).
One has probably to find out projection whose validity area includes the geometries being evaluated, and that provides good distance accuracy, project, and then apply the JTS isWithinDistance algorithm in cartesian space (JTS is not able to work on elissoidic geometry). I don't think we have the tools to implement such an algorithm thought, and it would be approximate anyways.
Mathworks has a function that's really able to compute a buffer around a geometry expressed in lat/lon: http://www.mathworks.com/products/mapping/functionlist.html (but no indication on its implementation).
Issue Links
- is depended upon by
-
GEOS-937
DWithin filters should honour the units set in the distance element
-
{code}
double msInchesPerUnit(int units, double center_lat)
{
double lat_adj = 1.0, ipu = 1.0;
switch (units) {
case(MS_METERS):
case(MS_KILOMETERS):
case(MS_MILES):
case(MS_INCHES):
case(MS_FEET):
ipu = inchesPerUnit[units];
break;
case(MS_DD):
/* With geographical (DD) coordinates, we adjust the inchesPerUnit
* based on the latitude of the center of the view. For this we assume
* we have a perfect sphere and just use cos(lat) in our calculation.
*/
#ifdef ENABLE_VARIABLE_INCHES_PER_DEGREE
if (center_lat != 0.0)
{
double cos_lat;
cos_lat = cos(MS_PI*center_lat/180.0);
lat_adj = sqrt(1+cos_lat*cos_lat)/sqrt(2.0);
}
#endif
ipu = inchesPerUnit[units]*lat_adj;
break;
default:
break;
}
return ipu;
}
{code}