gis_.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. '''
  2. @author: olivier.massot, 2018
  3. '''
  4. from osgeo import ogr, osr
  5. from path import Path
  6. GEOM_UNKNOWN = 0
  7. GEOM_POINT = 1
  8. GEOM_LINE = 2
  9. GEOM_POLYGON = 3
  10. GEOM_MULTIPOINT = 4
  11. GEOM_MULTILINE = 5
  12. GEOM_MULTIPOLYGON = 6
  13. GEOM_NAMES = {0: "(AUCUN)",
  14. 1: "POINT",
  15. 2: "LIGNE",
  16. 3: "POLYGONE",
  17. 4: "MULTI-POINT",
  18. 5:"MULTI-LIGNE",
  19. 6:"MULTI-POLYGONE",
  20. }
  21. class Datasource():
  22. DRIVER_NAME = "ESRI Shapefile"
  23. def __init__(self, filename, readonly=True):
  24. self.filename = Path(filename)
  25. driver = ogr.GetDriverByName(self.DRIVER_NAME)
  26. self._ogr_datasource = driver.Open(filename, 0 if readonly else 1)
  27. if not self._ogr_datasource:
  28. raise IOError("Unable to read the file {}".format(filename))
  29. @property
  30. def layer(self):
  31. return Layer(self._ogr_datasource.GetLayer())
  32. class LayerField():
  33. def __init__(self, ogr_field):
  34. self.name = ogr_field.GetName()
  35. self.type_ = ogr_field.GetType()
  36. self.type_name = ogr_field.GetFieldTypeName(self.type_)
  37. self.width = ogr_field.GetWidth()
  38. self.precision = ogr_field.GetPrecision()
  39. def __repr__(self):
  40. return "<Field: nom={}, type={}, longueur={}>".format(self.name, self.type_name, self.width)
  41. class Layer():
  42. def __init__(self, ogr_layer):
  43. self._ogr_layer = ogr_layer
  44. self.name = ogr_layer.GetName()
  45. self.srid = ogr_layer.GetSpatialRef().GetAttrValue('AUTHORITY',1)
  46. self.geom_type = ogr_layer.GetGeomType()
  47. _layer_def = self._ogr_layer.GetLayerDefn()
  48. self.fields = [LayerField(_layer_def.GetFieldDefn(i)) for i in range(_layer_def.GetFieldCount())]
  49. @property
  50. def geom_name(self):
  51. return GEOM_NAMES[self._ogr_layer.GetGeomType()]
  52. def __len__(self):
  53. return self._ogr_layer.GetFeatureCount()
  54. def __iter__(self):
  55. for f in self._ogr_layer.__iter__():
  56. yield Feature(f)
  57. self._ogr_layer.ResetReading()
  58. def __getitem__(self, i):
  59. return Feature(self._ogr_layer.GetFeature(i))
  60. class Feature():
  61. def __init__(self, ogr_feature):
  62. self._ogr_feature = ogr_feature
  63. self.geom = self._ogr_feature.GetGeometryRef()
  64. self.geom_type = self.geom.GetGeometryType()
  65. xmin, xmax, ymin, ymax = self.geom.GetEnvelope()
  66. self.bounding_box = (xmin, ymin, xmax, ymax)
  67. _def = ogr_feature.GetDefnRef()
  68. for i in range(_def.GetFieldCount()):
  69. field = _def.GetFieldDefn(i)
  70. value = ogr_feature[i]
  71. if value is None and field.GetType() == ogr.OFTString:
  72. value = ""
  73. self.__setattr__(field.GetName(), value)
  74. @property
  75. def geom_name(self):
  76. return GEOM_NAMES[self.geom.GetGeometryType()]
  77. def fields(self):
  78. layerDefinition = self._ogr_layer.GetLayerDefn()
  79. return [LayerField(layerDefinition.GetFieldDefn(i)) for i in range(layerDefinition.GetFieldCount())]
  80. @property
  81. def valid(self):
  82. return self.geom.IsValid()
  83. def __repr__(self):
  84. return "<Feature: type={}, bounding_box={}>".format(self.geom_name, self.bounding_box)
  85. @property
  86. def points(self):
  87. return [p for p in self.geom.GetPoints()]
  88. def almost_equal(self, feature, buffer_dist=1):
  89. if feature.geom_type == self.geom_type:
  90. buffer = self.geom.Buffer(buffer_dist)
  91. if buffer.Contains(feature.geom):
  92. return True
  93. return False
  94. @classmethod
  95. def union(cls, features):
  96. g = features[0].geom.Clone()
  97. for f in features[1:]:
  98. g = g.Union(f.geom)
  99. return g
  100. @classmethod
  101. def buffered_union(cls, features, buffer_dist=1):
  102. multi = ogr.Geometry(ogr.wkbMultiPolygon)
  103. for f in features:
  104. multi.AddGeometry(f.geom.Buffer(buffer_dist))
  105. return multi.UnionCascaded()
  106. if __name__ == "__main__":
  107. ds = Datasource(r"C:\dev\python\datacheck\work\STURNO_178AP1_REC_171121_OK\ARTERE_GEO.shp")
  108. layer = ds.layer
  109. print(layer.fields)
  110. # for f in layer:
  111. # print(f)
  112. f = layer[4]
  113. f2 = layer[5]
  114. f3 = layer[4]
  115. print(f)
  116. print(f.geom)
  117. print(f.AR_ID_INSE)
  118. gf = Feature.union(list(layer))
  119. print(gf)
  120. # gf = Feature.buffered_union(list(layer), 0.5)
  121. # print(gf)
  122. # save to file
  123. result_file = Path(r"C:\dev\python\datacheck\work\result.shp")
  124. driver = ogr.GetDriverByName("ESRI Shapefile")
  125. if result_file.exists():
  126. driver.DeleteDataSource(result_file)
  127. data_source = driver.CreateDataSource(result_file)
  128. srs = osr.SpatialReference()
  129. srs.ImportFromEPSG(3949)
  130. layer = data_source.CreateLayer("result", srs, gf.GetGeometryType())
  131. feature = ogr.Feature(layer.GetLayerDefn())
  132. feature.SetGeometry(gf)
  133. layer.CreateFeature(feature)