GeoTools
  1. GeoTools
  2. GEOT-1170

DistanceBufferOperator implementors disregard unit measure

    Details

    • Type: Improvement Improvement
    • Status: Open Open
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 2.7.6
    • Component/s: data, main
    • Labels:
      None

      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

          Activity

          Hide
          Andrea Aime added a comment - - edited
          MapServer source code has an interesting take on this problem, they basically create a rough conversion between meters and degrees based on a reference latitude. Imprecise, but probably better than nothing:

          {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}
          Show
          Andrea Aime added a comment - - edited MapServer source code has an interesting take on this problem, they basically create a rough conversion between meters and degrees based on a reference latitude. Imprecise, but probably better than nothing: {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}
          Hide
          Jody Garnett added a comment -
          So do you want to keep this one? Or ask people to convert prior to use? Probably we want to keep this one - indeed it would be nice with the idea of evaulating an expression into a distance.
          Show
          Jody Garnett added a comment - So do you want to keep this one? Or ask people to convert prior to use? Probably we want to keep this one - indeed it would be nice with the idea of evaulating an expression into a distance.
          Hide
          Andrea Aime added a comment -
          Keep please
          Show
          Andrea Aime added a comment - Keep please

            People

            • Assignee:
              Andrea Aime
              Reporter:
              Andrea Aime
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: