[FWTools] GEOS C API does not include DistanceOp?

Bryan Keith bryan at geomega.com
Wed Jul 5 13:54:19 EDT 2006


Frank Warmerdam wrote:
> Bryan Keith wrote:
>> Hello all,
>>
>> I'm using FWTools1.0.0 on windows.  I'm trying to get the distance from 
>> a point to a polygon (or line), but I get this error using the python 
>> wrapper:
>>
>> GEOS C API does not include DistanceOp
>>
>> Is there a good workaround?  Anyone have a Python algorithm to get the 
>> distance between ogr geometries?
>>
>> I also have FWTools-linux-1.0.0a7 installed on a linux machine, but I 
>> get the same GEOS error.
> 
> Bryan,
> 
> If you file a bug against GDAL/OGR on this, I'll look at correcting the
> problem.  The root of the problem was that the GEOS Distance operation was
> not originally exposed in the GEOS C API, so when I shifted to that it
> was lost.  I gather it is now available in the latest GEOS releases, so
> the problem should be resolvable.

Frank,

Thanks.  I added a bug and assigned it to you:

http://bugzilla.remotesensing.org/show_bug.cgi?id=1227

> 
> I'm afraid I don't have a good workaround suggestion in the meantime.

In the meantime I wrote some Python code that seems to be working for my 
specific situation:  one of my geometries is always a simple point and 
I'm assuming everything is on the same z plane.  I'm attaching the code 
to this e-mail if anyone's interested.  Comments are appreciated.

Bryan

> 
> Best regards,
-------------- next part --------------
import ogr
def ReturnPTLNDistance(mPT, mLN, dDist = "None"):
  #mPT is an ogr point
  #mLN is an ogr polygon or polyline
  #dDist is the current calculated minimum distance, used when this function
  #calls itself; leave dDist out when calling from another function (when no
  #minimum distance is yet determined)
  px = mPT.GetX()
  py = mPT.GetY()
  if (mLN.GetGeometryCount() == 0):
    for j in range(mLN.GetPointCount() - 1):
      X1 = mLN.GetX(j)
      Y1 = mLN.GetY(j)
      X2 = mLN.GetX(j + 1)
      Y2 = mLN.GetY(j + 1)
      d = DistancePointLine(px, py, X1, Y1, X2, Y2)
      if (dDist == "None"):
        dDist = d
      else:
        dDist = min(dDist, d)
  else:
    for i in range(mLN.GetGeometryCount()):
      myGeom = mLN.GetGeometryRef(i)
      dDist = ReturnPTLNDistance(mPT, myGeom, dDist)
  return dDist
def ReturnDistance(x1, x2, y1, y2, z1 = 0, z2 = 0):
  return ((x2 - x1) ** 2 + (y2 - y1) ** 2 + (z2 - z1) ** 2) ** 0.5
def DistancePointLine(px, py, x1, y1, x2, y2):
  #px,py is the point to test.
  #x1,y1,x2,y2 is the line to check distance.
  #Returns distance from the line, or if the intersecting point on the line
  #nearest the point tested is outside the endpoints of the line, the distance to
  #the nearest endpoint.
  #code taken from VB code from here:
  #http://astronomy.swin.edu.au/~pbourke/geometry/pointline/source.vba
  LineMag = ReturnDistance(x1, x2, y1, y2)
  if (LineMag < 0.00000001):
    return ReturnDistance(x1, px, y1, py)
  u = ((px - x1) * (x2 - x1)) + ((py - y1) * (y2 - y1))
  u = u / (LineMag ** 2)
  if ((u < 0.00001) or (u > 1)):
    #closest point does not fall within the line segment, take the shorter
    #distance to an endpoint
    ix = ReturnDistance(px, x1, py, y1)
    iy = ReturnDistance(px, x2, py, y2)
    if (ix > iy):
      return iy
    else:
      return ix
  else:
    #Intersecting point is on the line, use the formula
    #see http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
    ix = x1 + u * (x2 - x1)
    iy = y1 + u * (y2 - y1)
    return ReturnDistance(px, ix, py, iy)


More information about the FWTools mailing list