Perform ST_Buffer query on geography point

51 views
Skip to first unread message

Eric Reichwaldt

unread,
Sep 9, 2019, 7:12:00 AM9/9/19
to GeoAlchemy
New to GeoAlchemy, but enjoying it so far. I am trying to do a radial search for items in my database and would like the precision offered by native geography objects in PostGIS instead of geometry. I am struggling to get my query to work correctly, and was hoping someone could help steer me in the right direction.

The PostGIS docs and the GeoAlchemy docs both state that when geometry is used with ST_Buffer the native projection coordinates are used and when geography is used it should be in meters.


geometry ST_Buffer(geometry g1, float radius_of_buffer);
geometry ST_Buffer(geometry g1, float radius_of_buffer, integer num_seg_quarter_circle);
geometry ST_Buffer(geometry g1, float radius_of_buffer, text buffer_style_parameters);
geography ST_Buffer(geography g1, float radius_of_buffer_in_meters);
geography ST_Buffer(geography g1, float radius_of_buffer, integer num_seg_quarter_circle);
geography ST_Buffer(geography g1, float radius_of_buffer, text buffer_style_parameters);

class Metar(Base):
    __tablename__ = 'metars'
    id = Column(Integer, primary_key=True)
    station = Column(String)
    location = Column(Geography('POINT'))
    valid_time = Column(DateTime)
    observation = Column(String)

### This is my observation in the database
koff = Metar(station='KOFF', location='POINT(-95.9146 41.1243)', valid_time=time, observation='KOFF 082325 18005KT 9999 OVC030 QNH29.97INS')

### This is my search location
search_location = 'POINT(-95 41)'

results = session.query(Metar).filter(Metar.location.contained(func.ST_Buffer(search_location, 1)))

for result in results:
    print(result.station)
    distance = session.scalar(func.ST_Distance_Sphere(search_location, result.location))
    print(distance)

for result in results:
    print(result.station)
    distance = session.scalar(func.ST_Distance(search_location, result.location))
    print(distance)


Returns:

KOFF
> 77916.10753074

> KOFF
> 0.923007936043882

The top distance is correct, at roughly 78 km, and the second is in what I assume is CRS:84 degrees.
If I change my search to .9 distance, it no longer returns any station.

results = session.query(Metar).filter(Metar.location.contained(func.ST_Buffer(search_location, .9)))

This tells me that when I call ST_Buffer (like below) it is using the Geometry method by default, and not the Geography. I have had success running it on a point that was written to the database as a Geography and retrieved via the query, but this does not help me trying to find all points within a user-defined point. 

I was struggling to understand how to manually create the WKBElement as a Geography point to call the function and wanted to see if I am making it too complex and what anyone might be able to offer before I hack something together. Ultimately, I believe it will work fine if I can just create an instance of Geography without pulling from the database for my variable search_location but maybe there is an easier way?

func.ST_Buffer('POINT(-95 41)', 1)

Any help is much appreciated!
Reply all
Reply to author
Forward
0 new messages