mncheck.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. '''
  2. @author: olivier.massot, 2018
  3. '''
  4. import importlib
  5. import inspect
  6. import logging
  7. import pkgutil
  8. from qgis.core import QgsProject, QgsWkbTypes, QgsGeometry, QgsPoint
  9. from PyQt5.QtCore import QVariant
  10. import yaml
  11. from core.checking import BaseChecker
  12. from core.constants import USER_DATA
  13. from plugins import processing
  14. logger = logging.getLogger("mncheck")
  15. def list_schemas():
  16. import schemas
  17. return [name for _, name, ispkg in pkgutil.iter_modules(schemas.__path__) if not (ispkg or name[0] == '_')]
  18. def get_schema(schema_name):
  19. return importlib.import_module("schemas." + schema_name)
  20. def get_checkers(schema):
  21. return [cls for _, cls in inspect.getmembers(schema, predicate=inspect.isclass) \
  22. if issubclass(cls, BaseChecker) and not cls is BaseChecker]
  23. def get_user_data():
  24. try:
  25. with open(USER_DATA, 'r') as f:
  26. return yaml.load(f.read()) or {}
  27. except FileNotFoundError:
  28. return {}
  29. def dump_user_data(conf):
  30. with open(USER_DATA, 'w+') as f:
  31. return yaml.dump(conf, f)
  32. class QgsModel():
  33. GEOM_UNKNOWN = 0
  34. GEOM_POINT = 1
  35. GEOM_LINE = 2
  36. GEOM_POLYGON = 3
  37. GEOM_MULTIPOINT = 4
  38. GEOM_MULTILINE = 5
  39. GEOM_MULTIPOLYGON = 6
  40. GEOM_NAMES = {0: "(AUCUN)", 1: "POINT", 2: "LIGNE", 3: "POLYGONE",
  41. 4: "MULTI-POINT", 5:"MULTI-LIGNE", 6:"MULTI-POLYGONE"}
  42. layername = ""
  43. geom_type = 0
  44. bounding_box = (0,0,1,1)
  45. schema = {}
  46. pk = ""
  47. def __init__(self, qgs_feature):
  48. self._feature = qgs_feature
  49. for attr, value in self.attributes().items():
  50. if isinstance(value, QVariant):
  51. value = value.value() if not value.isNull() else ""
  52. setattr(self, attr, value)
  53. def __repr__(self):
  54. try:
  55. return "{} {}".format(self.__class__.__name__, getattr(self, self.pk))
  56. except AttributeError:
  57. return f"{self.__class__.__name__} (code manquant)"
  58. @property
  59. def feature(self):
  60. return self._feature
  61. def attributes(self):
  62. return dict(zip([f.name() for f in self._feature.fields()], self._feature.attributes()))
  63. @property
  64. def geom(self):
  65. return self._feature.geometry()
  66. def is_geometry_valid(self):
  67. return self._feature.geometry().isGeosValid()
  68. def get_geom_type(self):
  69. return QgsWkbTypes.singleType(self._feature.geometry().wkbType())
  70. def get_bounding_box(self):
  71. bb = self._feature.geometry().boundingBox()
  72. return (bb.xMinimum(), bb.yMinimum(), bb.xMaximum(), bb.yMaximum())
  73. def get_points(self):
  74. if self.geom.isNull():
  75. return []
  76. multi_geom = QgsGeometry()
  77. temp_geom = []
  78. if self.geom.type() == 0: # it's a point
  79. if self.geom.isMultipart():
  80. temp_geom = self.geom.asMultiPoint()
  81. else:
  82. temp_geom.append(self.geom.asPoint())
  83. elif self.geom.type() == 1: # it's a line
  84. if self.geom.isMultipart():
  85. multi_geom = self.geom.asMultiPolyline() #multi_geog is a multiline
  86. for i in multi_geom: #i is a line
  87. temp_geom.extend( i )
  88. else:
  89. temp_geom = self.geom.asPolyline()
  90. elif self.geom.type() == 2: # it's a polygon
  91. if self.geom.isMultipart():
  92. multi_geom = self.geom.asMultiPolygon() #multi_geom is a multipolygon
  93. for i in multi_geom: #i is a polygon
  94. for j in i: #j is a line
  95. temp_geom.extend( j )
  96. else:
  97. multi_geom = self.geom.asPolygon() #multi_geom is a polygon
  98. for i in multi_geom: #i is a line
  99. temp_geom.extend( i )
  100. return [QgsPoint(p) for p in temp_geom]
  101. @classmethod
  102. def full_buffer(cls, distance):
  103. layer = next((l for l in QgsProject.instance().mapLayers().values() if l.name().lower() == cls.layername.lower()))
  104. result = processing.run("native:buffer", {'INPUT':layer.dataProvider().dataSourceUri(), #@UndefinedVariable
  105. 'DISTANCE':distance,
  106. 'SEGMENTS':5,
  107. 'END_CAP_STYLE':0,
  108. 'JOIN_STYLE':0,
  109. 'MITER_LIMIT':2,
  110. 'DISSOLVE':True,
  111. 'OUTPUT':'memory:mncheck_temp'})
  112. buffer = next((f for f in result['OUTPUT'].getFeatures()))
  113. return buffer.geometry()
  114. def validate(schema_name):
  115. try:
  116. schema = get_schema(schema_name)
  117. except ModuleNotFoundError:
  118. logger.critical(f"Le schéma {schema_name} n'existe pas")
  119. return
  120. results = schema.checker.run()
  121. return results