GeoDjango将MultiPolygon解释为LinearRing

时间:2018-03-15 18:57:36

标签: python django postgis geodjango

我正在将Trimble的一些OSM数据导入PostGIS数据库,以便将其作为Django应用程序的一部分进行处理。这适用于点和线,但我正在与多边形挣扎。

导入似乎工作正常:

C2

Django InspectDB以合理的方式解释数据:

shp2pgsql -d -I aeroway_polygon_polygon.shp aeroway_polygon | psql

models.py内容:

./manage.py inspectdb > models.py

任何从数据库访问对象的尝试都会导致GEOS抱怨LinearRing。

class AerowayPolygon(models.Model):
    gid = models.AutoField(primary_key=True)
    id = models.FloatField(blank=True, null=True)
    osm_id = models.DecimalField(max_digits=65535, decimal_places=65535, blank=True, null=True)
    z_order = models.FloatField(blank=True, null=True)
    aeroway = models.CharField(max_length=80, blank=True, null=True)
    name = models.CharField(max_length=80, blank=True, null=True)
    name_en = models.CharField(db_column='name:en', max_length=80, blank=True, null=True)  # Field renamed to remove unsuitable characters.
    operator = models.CharField(max_length=80, blank=True, null=True)
    ref = models.CharField(max_length=80, blank=True, null=True)
    faa = models.CharField(max_length=80, blank=True, null=True)
    iata = models.CharField(max_length=80, blank=True, null=True)
    icao = models.CharField(max_length=80, blank=True, null=True)
    website = models.CharField(max_length=80, blank=True, null=True)
    contact_we = models.CharField(db_column='contact:we', max_length=80, blank=True, null=True)  # Field renamed to remove unsuitable characters.
    phone = models.CharField(max_length=80, blank=True, null=True)
    contact_ph = models.CharField(db_column='contact:ph', max_length=80, blank=True, null=True)  # Field renamed to remove unsuitable characters.
    ele = models.CharField(max_length=80, blank=True, null=True)
    tower_type = models.CharField(db_column='tower:type', max_length=80, blank=True, null=True)  # Field renamed to remove unsuitable characters.
    geom = models.MultiPolygonField(srid=0, dim=4, blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'aeroway_polygon'

错误没有错,这些点不会关闭LineString。但我很困惑,因为我认为类型应该是MultiPolygon,因此应该可以正常工作。是什么给了什么?

我通过手动尝试从PostGIS中获取几何图形来深入挖掘。

作为一个众所周知的二进制十六进制字符串,我得到了相同的行为:

>>> from data.models import AerowayPolygon
>>> AerowayPolygon.objects.all()[0]
GEOS_ERROR: IllegalArgumentException: Points of LinearRing do not form a closed linestring

但是,如果我使用ST_AsEWKT预先转换为众所周知的文本,那么一切都很好:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> wkb ='01060000C00100000001030000C0020000008E0000000064931E4F47DDBF4020B11AB5BC49400000000000000000FFFFFFFFFFFFEFFF006493B23347DDBF442075F9B7BC494 ...     003C9368871FDDBF4020B193B4BC49400000000000000000FFFFFFFFFFFFEFFF'
>>> GEOSGeometry(wkb)
GEOS_ERROR: IllegalArgumentException: Points of LinearRing do not form a closed linestring

2 个答案:

答案 0 :(得分:2)

MultiPolygon的每个多边形仍应形成闭合的线串。您的数据可能格式错误或已损坏。

您可以尝试使用ST_MakeValid修复此问题。

UPDATE aeroway_polygon
SET geom = ST_Multi(ST_CollectionExtract(ST_Makevalid(geom), 3))
WHERE ST_IsValid(geom) = false;

请注意,我没有测试此查询,我发现它here on gis.stackexchange

答案 1 :(得分:1)

根据定义,

Polygons是封闭的几何图形,这意味着第一个和最后一个Point必须完全相同Point。 对于Multipolygons,存在相同的原则,因此Polygon的每个Multipolygon都必须关闭,并且不得有#34; free"几何内部的边缘。

如果您检查数据集,您会发现其中一些LineStrings没有关闭。

@AntoinePinsard提供了一个很好的PostGIS解决方案 在GeoDjango版本> = 1.10中,MakeValid作为数据库函数存在,我们可以在查询中使用它:

AerowayPolygon.objects.all().update(geom=MakeValid('geom'))

如果你的Django版本< 1.10,我有一套关于如何创建自定义数据库函数的答案,并在上面的示例中使用它:

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

class MyMakeValid(GeoFunc):
      function='ST_MakeValid'

AerowayPolygon.objects.all().update(geom=MyMakeValid('geom'))