Geodjango:如何从点开始缓冲

问题描述 投票:0回答:3

我想要进行基于半径的距离搜索。为此,我想在点对象周围创建一个缓冲区,以便过滤其中的对象。

这就是我的情况:

>>> lat = 37.7762179974
>>> lon = -122.411562492
>>> from django.contrib.gis.geos import Point
>>> pnt = Point(lat, lon)
>>> buf = pnt.buffer(0.0001)

但是我在根据

Thing
对象是否位于缓冲区内来过滤它们时遇到问题:

>>> z = Thing.objects.filter(pnt__intersects=buf) 

我知道上面的内容是不正确的,但我用它来阐述我想要做的事情。

如何在

Point
周围创建缓冲区,然后过滤
Things
内的
buffer


编辑:

models.py

class Thing(models.Model):
    lat = models.FloatField()
    lon = models.FloatField()

如何根据这两个模型字段的组合组成的点进行过滤?
这显然不起作用,因为我的模型中没有

pnt
字段:

>>> pnt = Point(lat, lon)
>>> z = Thing.objects.filter(pnt__intersects=buf) 

但是我怎样才能做类似的事情呢?

python django filter buffer geodjango
3个回答
1
投票

PostGIS 有一个名为

ST_MakePoint
的方法,可以创建 2D、3D 或 4D 点。

之前的答案中,我们看到可以从现有的PostGIS函数创建自定义数据库函数:

from django.contrib.gis.db.models.functions import GeoFunc

class MakePoint(GeoFunc):
    function='ST_MakePoint'

现在我们可以通过

annotate()
ing 创建一个点并在其上应用
intersects

z = Thing.objects.annotate(pnt=MakePoint('lat', 'lon'))
                 .filter(pnt__intersects=buf)

您可以使用

GeoFunc()
F()
表达式达到相同的效果:

from django.contrib.gis.db.models.functions import GeoFunc

z = Thing.objects.annotate(pnt=GeoFunc(
        F('lat'), F('lon'),
        function='ST_MakePoint'
    )).filter(pnt__intersects=buf)

注意: 您可以考虑在

pnt
模型中添加
Thing
字段并避免上述情况。


0
投票

我不确定“缓冲区”是什么意思,但如果您想要基于半径的距离搜索,您可以尝试使用...距离!

这是一个以公里为单位的示例:

from django.contrib.gis.measure import D

Thing.objects.filter(pnt__distance_lte=(pnt,D(km=distance)))

您当然应该查看文档:https://docs.djangoproject.com/en/dev/ref/contrib/gis/db-api/#distance-lookups


0
投票

更新...em 2023 django==4.2


     from django.contrib.gis.geos import GEOSGeometry

    In [1]: p = GEOSGeometry("POINT (-45.8872 -23.1791)") #

    In [2]: RAIOKM = 40

    In [3]: KM_GRAD_TAXA = 111.32

    In [4]: b = p.buffer(RAIOKM/KM_GRAD_TAXA, 16) # com um poly de 16 vertex

    In [5]: b.json
    Out[5]: '{ "type": "Polygon", "coordinates": [ [ [ -45.527875530003591, -23.1791 ], [ -45.529605775539991, -23.214319956999482 ], [ -45.534779848938832, -23.24920072655987 ], [ -45.543347921044841, -23.283406387802536 ], [ -45.555227476639857, -23.316607521510988 ], [ -45.570304109109465, -23.348484382618036 ], [ -45.588432622241271, -23.378729979525549 ], [ -45.609438428543754, -23.407053030601379 ], [ -45.633119230619279, -23.433180769380719 ], [ -45.659246969398616, -23.456861571456244 ], [ -45.687570020474453, -23.477867377758727 ], [ -45.717815617381966, -23.49599589089053 ], [ -45.74969247848901, -23.511072523360145 ], [ -45.782893612197462, -23.522952078955157 ], [ -45.817099273440128, -23.531520151061166 ], [ -45.851980043000516, -23.536694224460003 ], [ -45.8872, -23.538424469996404 ], [ -45.922419956999484, -23.536694224460003 ], [ -45.957300726559872, -23.531520151061166 ], [ -45.991506387802538, -23.522952078955157 ], [ -46.02470752151099, -23.511072523360145 ], [ -46.056584382618034, -23.495995890890534 ], [ -46.086829979525547, -23.477867377758727 ], [ -46.115153030601384, -23.456861571456248 ], [ -46.141280769380721, -23.433180769380719 ], [ -46.164961571456246, -23.407053030601382 ], [ -46.185967377758729, -23.378729979525549 ], [ -46.204095890890535, -23.348484382618036 ], [ -46.219172523360143, -23.316607521510992 ], [ -46.231052078955159, -23.283406387802536 ], [ -46.239620151061168, -23.249200726559874 ], [ -46.244794224460009, -23.214319956999482 ], [ -46.246524469996409, -23.1791 ], [ -46.244794224460009, -23.143880043000514 ], [ -46.239620151061168, -23.108999273440126 ], [ -46.231052078955159, -23.07479361219746 ], [ -46.219172523360143, -23.041592478489008 ], [ -46.204095890890535, -23.009715617381961 ], [ -46.185967377758729, -22.979470020474448 ], [ -46.164961571456246, -22.951146969398618 ], [ -46.141280769380721, -22.925019230619277 ], [ -46.115153030601384, -22.901338428543752 ], [ -46.086829979525547, -22.880332622241269 ], [ -46.056584382618034, -22.862204109109467 ], [ -46.02470752151099, -22.847127476639852 ], [ -45.991506387802538, -22.835247921044839 ], [ -45.957300726559872, -22.826679848938831 ], [ -45.922419956999484, -22.821505775539993 ], [ -45.8872, -22.819775530003593 ], [ -45.851980043000516, -22.821505775539993 ], [ -45.817099273440128, -22.826679848938831 ], [ -45.782893612197462, -22.835247921044839 ], [ -45.74969247848901, -22.847127476639852 ], [ -45.717815617381966, -22.862204109109463 ], [ -45.687570020474453, -22.880332622241266 ], [ -45.659246969398623, -22.901338428543749 ], [ -45.633119230619279, -22.925019230619277 ], [ -45.609438428543754, -22.951146969398614 ], [ -45.588432622241271, -22.979470020474448 ], [ -45.570304109109465, -23.009715617381961 ], [ -45.555227476639857, -23.041592478489004 ], [ -45.543347921044841, -23.074793612197457 ], [ -45.534779848938832, -23.108999273440123 ], [ -45.529605775539991, -23.143880043000511 ], [ -45.527875530003591, -23.1791 ], [ -45.527875530003591, -23.1791 ] ] ] }'

...您正在使用 Django,您可能有 PostGIS 扩展

 SELECT jsonb_build_object(
       'type',     'FeatureCollection', 
       'features', jsonb_agg(features.feature) 
    ) 
    FROM ( 
       SELECT jsonb_build_object( 
          'type',       'Feature', 
          'id',         id, 
          'geometry',   ST_AsGeoJSON(buffer)::jsonb, 
          'properties', to_jsonb(inputs) - 'id' - 'buffer' 
       ) AS feature 
       FROM ( 
          SELECT  
             *, ST_Buffer( 
                 geography( ST_Transform( ponto_geo, 4326 )), 10000 
            )::geometry as buffer 
          FROM tabela1 
          where ponto_geo is not null 
       ) inputs 
        ) features; 

    /*  
    tabela1 - table
    ponto_geo - field `ponto_geo public.geometry(point, 4326) NULL,`
    
    */

查询生成完美的 GeoJson 兼容,但您可以直接在查询中使用

ST_Buffer
;)

© www.soinside.com 2019 - 2024. All rights reserved.