def testPktMapInsert(self): vl = QgsVectorLayer('{} table="qgis_test"."{}" key="obj_id" sql='.format(self.dbconn, 'oid_serial_table'), "oid_serial", "postgres") self.assertTrue(vl.isValid()) f = QgsFeature(vl.fields()) f['obj_id'] = vl.dataProvider().defaultValueClause(0) f['name'] = 'Test' r, f = vl.dataProvider().addFeatures([f]) self.assertTrue(r) self.assertNotEqual(f[0]['obj_id'], NULL, f[0].attributes()) vl.deleteFeatures([f[0].id()])
def testPktIntInsert(self): vl = QgsVectorLayer('{} table="qgis_test"."{}" key="pk" sql='.format(self.dbconn, 'bikes_view'), "bikes_view", "postgres") self.assertTrue(vl.isValid()) f = QgsFeature(vl.fields()) f['pk'] = NULL f['name'] = 'Cilo' r, f = vl.dataProvider().addFeatures([f]) self.assertTrue(r) self.assertNotEqual(f[0]['pk'], NULL, f[0].attributes()) vl.deleteFeatures([f[0].id()])
def testStringArray(self): vl = QgsVectorLayer('%s table="qgis_test"."string_array" sql=' % (self.dbconn), "teststringarray", "postgres") self.assertTrue(vl.isValid()) fields = vl.dataProvider().fields() self.assertEqual(fields.at(fields.indexFromName('value')).type(), QVariant.StringList) self.assertEqual(fields.at(fields.indexFromName('value')).subType(), QVariant.String) f = next(vl.getFeatures(QgsFeatureRequest())) value_idx = vl.fields().lookupField('value') self.assertIsInstance(f.attributes()[value_idx], list) self.assertEqual(f.attributes()[value_idx], ['a', 'b', 'c']) new_f = QgsFeature(vl.fields()) new_f['pk'] = NULL new_f['value'] = ['simple', '"doubleQuote"', "'quote'", 'back\\slash'] r, fs = vl.dataProvider().addFeatures([new_f]) self.assertTrue(r) new_pk = fs[0]['pk'] self.assertNotEqual(new_pk, NULL, fs[0].attributes()) try: read_back = vl.getFeature(new_pk) self.assertEqual(read_back['pk'], new_pk) self.assertEqual(read_back['value'], new_f['value']) finally: self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeatures([new_pk])) self.assertTrue(vl.commitChanges())
def testHstore(self): vl = QgsVectorLayer('%s table="qgis_test"."dict" sql=' % (self.dbconn), "testhstore", "postgres") self.assertTrue(vl.isValid()) fields = vl.dataProvider().fields() self.assertEqual(fields.at(fields.indexFromName('value')).type(), QVariant.Map) f = next(vl.getFeatures(QgsFeatureRequest())) value_idx = vl.fields().lookupField('value') self.assertIsInstance(f.attributes()[value_idx], dict) self.assertEqual(f.attributes()[value_idx], {'a': 'b', '1': '2'}) new_f = QgsFeature(vl.fields()) new_f['pk'] = NULL new_f['value'] = {'simple': '1', 'doubleQuote': '"y"', 'quote': "'q'", 'backslash': '\\'} r, fs = vl.dataProvider().addFeatures([new_f]) self.assertTrue(r) new_pk = fs[0]['pk'] self.assertNotEqual(new_pk, NULL, fs[0].attributes()) try: read_back = vl.getFeature(new_pk) self.assertEqual(read_back['pk'], new_pk) self.assertEqual(read_back['value'], new_f['value']) finally: self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeatures([new_pk])) self.assertTrue(vl.commitChanges())
def testHstore(self): vl = QgsVectorLayer('%s table="qgis_test"."dict" sql=' % (self.dbconn), "testhstore", "postgres") self.assertTrue(vl.isValid()) fields = vl.dataProvider().fields() self.assertEqual(fields.at(fields.indexFromName("value")).type(), QVariant.Map) f = next(vl.getFeatures(QgsFeatureRequest())) value_idx = vl.fields().lookupField("value") self.assertIsInstance(f.attributes()[value_idx], dict) self.assertEqual(f.attributes()[value_idx], {"a": "b", "1": "2"}) new_f = QgsFeature(vl.fields()) new_f["pk"] = NULL new_f["value"] = {"simple": "1", "doubleQuote": '"y"', "quote": "'q'", "backslash": "\\"} r, fs = vl.dataProvider().addFeatures([new_f]) self.assertTrue(r) new_pk = fs[0]["pk"] self.assertNotEqual(new_pk, NULL, fs[0].attributes()) try: read_back = vl.getFeature(new_pk) self.assertEqual(read_back["pk"], new_pk) self.assertEqual(read_back["value"], new_f["value"]) finally: self.assertTrue(vl.startEditing()) self.assertTrue(vl.deleteFeatures([new_pk])) self.assertTrue(vl.commitChanges())
class StartDuplic: def __init__(self, iface, layer): self.iface = iface self.layer = layer self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' def run(self, fid=0): ################################## ###### PEGA A LAYER ATIVA ######## ################################## parametros = self.layer.source().split( " " ) # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len( user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage( "Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen( ): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage( "Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = self.layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = self.layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values( ): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([ QgsField("flagId", QVariant.String), QgsField("geomId", QVariant.String), QgsField("motivo", QVariant.String) ]) self.flagsLayer.updateFields() if fid == 0: # Se tiver iniciando limpa, caso não, mantém. self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista. for f in self.layer.getFeatures(): lista_fid.append( str(f.id()) ) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = self.layer.source().split(" ") self.tableName = "" # Inicia vazio. layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[ 1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage( "Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return # Busca através do SQL sql = '''select * from ( SELECT "{3}", ROW_NUMBER() OVER(PARTITION BY "{2}" ORDER BY "{3}" asc) AS Row, ST_AsText(geom) FROM ONLY "{0}"."{1}" where {3} in ({4}) ) dups where dups.Row > 1'''.format(self.tableSchema, self.tableName, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) query = QSqlQuery(sql) self.flagsLayer.startEditing() flagCount = fid # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): id = query.value(0) ord = query.value(1) local = query.value(2) flagId = str(flagCount) flagFeat = QgsFeature() flagFeat.setFields(self.flagsLayer.fields() ) # passa quais atributos serão usados. flagGeom = QgsGeometry.fromWkt( local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.setAttribute( 0, flagId ) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute( 1, id ) # insere o id da geometria para a coluna 1 da layer de memória. flagFeat.setAttribute(2, u'Duplic-Geom') listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração. self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer( self.flagsLayer) # Adicione a camada no mapa. return flagCount
class StartOutofBoundsAngles: def __init__(self, iface): self.iface = iface self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' self.angle = 10 def initGui(self): # cria uma ação que iniciará a configuração do plugin pai = self.iface.mainWindow() icon_path = ':/plugins/StartOutofBoundsAngles/icon.png' self.action = QAction( QIcon(icon_path), u"Acessa banco de dados para encontrar anglos fechados.", pai) self.action.setObjectName("Start database") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.triggered.connect(self.run) # Adicionar o botão icone self.iface.addToolBarIcon(self.action) def unload(self): # remove o item de ícone do QGIS GUI. self.iface.removeToolBarIcon(self.action) def run(self): ################################## ###### PEGA A LAYER ATIVA ######## ################################## layer = self.iface.activeLayer() if not layer: self.iface.messageBar().pushMessage("Erro", u"Esperando uma Active Layer!", level=QgsMessageBar.CRITICAL, duration=4) return if layer.featureCount() == 0: self.iface.messageBar().pushMessage( "Erro", u"a camada não possui feições!", level=QgsMessageBar.CRITICAL, duration=4) return parametros = layer.source().split( " " ) # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len( user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage( "Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen( ): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage( "Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values( ): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([ QgsField("flagId", QVariant.Int), QgsField("geomId", QVariant.String), QgsField("motivo", QVariant.String) ]) self.flagsLayer.updateFields() self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista for f in layer.getFeatures(): lista_fid.append( str(f.id()) ) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = layer.source().split(" ") self.tableName = "" # Inicia vazio layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[ 1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage( "Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return geomType = layer.geometryType() if geomType == QGis.Line: # Busca através do SQL sql = """ WITH result AS (SELECT points."{4}", points.anchor, (degrees ( ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2) )::decimal + 360) % 360 as angle FROM (SELECT ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-2)) as pt1, ST_PointN("{3}", generate_series(2, ST_NPoints("{3}")-1)) as anchor, ST_PointN("{3}", generate_series(3, ST_NPoints("{3}"))) as pt2, linestrings."{4}" as "{4}" FROM (SELECT "{4}" as "{4}", (ST_Dump("{3}")).geom as "{3}" FROM only "{0}"."{1}" ) AS linestrings WHERE ST_NPoints(linestrings."{3}") > 2 ) as points) select distinct "{4}", ST_AsText(anchor), angle from result where (result.angle % 360) < {2} or result.angle > (360.0 - ({2} % 360.0)) and result.{4} in ({5})""".format( self.tableSchema, self.tableName, self.angle, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) elif geomType == QGis.Polygon: sql = """ WITH result AS (SELECT points."{4}", points.anchor, (degrees ( ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2) )::decimal + 360) % 360 as angle FROM (SELECT ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-1)) as pt1, ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-1) % (ST_NPoints("{3}")-1)+1) as anchor, ST_PointN("{3}", generate_series(2, ST_NPoints("{3}")) % (ST_NPoints("{3}")-1)+1) as pt2, linestrings."{4}" as "{4}" FROM (SELECT "{4}" as "{4}", (ST_Dump(ST_Boundary(ST_ForceRHR((ST_Dump("{3}")).geom)))).geom as "{3}" FROM only "{0}"."{1}" ) AS linestrings WHERE ST_NPoints(linestrings."{3}") > 2 ) as points) select distinct "{4}", ST_AsText(anchor), angle from result where (result.angle % 360) < {2} or result.angle > (360.0 - ({2} % 360.0)) and result.{4} in ({5})""".format( self.tableSchema, self.tableName, self.angle, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) query = QSqlQuery(sql) self.flagsLayer.startEditing() flagCount = 0 # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): id = query.value(0) local = query.value(1) angulo = query.value(2) flagId = flagCount print id, local, angulo flagFeat = QgsFeature() flagGeom = QgsGeometry.fromWkt( local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.initAttributes(3) flagFeat.setAttribute( 0, flagId ) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute( 1, id ) # insere o id da geometria para a coluna 1 da layer de memória. flagFeat.setAttribute( 2, u"Ângulo para os vértices adjacentes inferior à tolerância") # TypeError: fromWkt(QString): argument 1 has unexpected type 'long' # Traceback (most recent call last): # File "/home/piangers/.qgis2/python/plugins/StartDuplic/StartDuplic.py", line 177, in run # flagGeom = QgsGeometry.fromWkt(local) # passa o local onde foi localizado o erro. listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer( self.flagsLayer) # Adicione a camada no mapa if flagCount == 0: QgsMapLayerRegistry.instance().removeMapLayer(self.flagsLayer.id()) self.iface.messageBar().pushMessage( "Aviso", u"Não foi encontrado Flags em \"" + layer.name() + "\" !", level=QgsMessageBar.CRITICAL, duration=4) return if len(query.lastError().text()) == 1: self.iface.messageBar().pushMessage( "Aviso", "foram geradas " + str(flagCount) + " flags para a camada \"" + layer.name() + "\" !", level=QgsMessageBar.INFO, duration=4) else: self.iface.messageBar().pushMessage("Erro", u"a geração de flags falhou!", level=QgsMessageBar.CRITICAL, duration=4) print query.lastError().text()
class StartOutofBoundsAngles: def __init__(self, iface, layer): self.iface = iface self.layer = layer self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' self.angle = 10 def run(self, fid = 0): ################################## ###### PEGA A LAYER ATIVA ######## ################################## parametros = self.layer.source().split(" ") # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len(user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage("Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen(): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage("Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = self.layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = self.layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values(): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([QgsField("flagId", QVariant.String), QgsField("geomId", QVariant.String), QgsField("motivo", QVariant.String)]) self.flagsLayer.updateFields() if fid == 0: # Se for 0 então está iniciando e limpa, caso contrário não. self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista for f in self.layer.getFeatures(): lista_fid.append(str(f.id())) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = self.layer.source().split(" ") self.tableName = "" # Inicia vazio layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage("Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return geomType = self.layer.geometryType() if geomType == QGis.Line: # Busca através do SQL sql = """ WITH result AS (SELECT points."{4}", points.anchor, (degrees ( ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2) )::decimal + 360) % 360 as angle FROM (SELECT ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-2)) as pt1, ST_PointN("{3}", generate_series(2, ST_NPoints("{3}")-1)) as anchor, ST_PointN("{3}", generate_series(3, ST_NPoints("{3}"))) as pt2, linestrings."{4}" as "{4}" FROM (SELECT "{4}" as "{4}", (ST_Dump("{3}")).geom as "{3}" FROM only "{0}"."{1}" ) AS linestrings WHERE ST_NPoints(linestrings."{3}") > 2 ) as points) select distinct "{4}", ST_AsText(anchor), angle from result where (result.angle % 360) < {2} or result.angle > (360.0 - ({2} % 360.0)) and result.{4} in ({5})""".format( self.tableSchema, self.tableName, self.angle, self.geometryColumn, self.keyColumn,",".join(lista_fid)) elif geomType == QGis.Polygon: sql = """ WITH result AS (SELECT points."{4}", points.anchor, (degrees ( ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2) )::decimal + 360) % 360 as angle FROM (SELECT ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-1)) as pt1, ST_PointN("{3}", generate_series(1, ST_NPoints("{3}")-1) % (ST_NPoints("{3}")-1)+1) as anchor, ST_PointN("{3}", generate_series(2, ST_NPoints("{3}")) % (ST_NPoints("{3}")-1)+1) as pt2, linestrings."{4}" as "{4}" FROM (SELECT "{4}" as "{4}", (ST_Dump(ST_Boundary(ST_ForceRHR((ST_Dump("{3}")).geom)))).geom as "{3}" FROM only "{0}"."{1}" ) AS linestrings WHERE ST_NPoints(linestrings."{3}") > 2 ) as points) select distinct "{4}", ST_AsText(anchor), angle from result where (result.angle % 360) < {2} or result.angle > (360.0 - ({2} % 360.0)) and result.{4} in ({5})""".format( self.tableSchema, self.tableName, self.angle, self.geometryColumn, self.keyColumn,",".join(lista_fid) ) query = QSqlQuery(sql) self.flagsLayer.startEditing() flagCount = fid # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): id = query.value(0) local = query.value(1) angulo = query.value(2) flagId = str(flagCount) flagFeat = QgsFeature() flagFeat.setFields(self.flagsLayer.fields()) # passa quais atributos serão usados. flagGeom = QgsGeometry.fromWkt(local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.initAttributes(3) flagFeat.setAttribute(0,flagId) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute(1, id) # insere o id da geometria para a coluna 1 da layer de memória. flagFeat.setAttribute(2, u"Ângle-ExcededBound") listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração. self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer(self.flagsLayer) # Adicione a camada no mapa. return flagCount
def launchR2P(self): """Ridge to Point conversion""" layers = self.iface.legendInterface().layers() # Get index of combo box selected_line = self.lineComboBox.currentIndex() selected_dem_layer = self.DEMComboBox.currentIndex() # Get layer that fit with the combo box index self.lines_layer = layers[self.list_vect_ind[selected_line]] self.dem_layer = layers[self.list_rast_ind[selected_dem_layer]] self.min_dist = self.minLengthBox.value() self.id_line = self.idLineComboBox.currentText() self.output_path = self.outputEdit.text() l_done = [] time = Timer() time.start() tmp_path = os.path.dirname(self.lines_layer.source()) # Extract all points of interest (start of line, end of line, peak, pass) from polyline layer pointPassage, crs, self.dem_layer = passPointSeek( self.lines_layer, self.id_line, self.dem_layer, tmp_path) output_filename = os.path.join(os.path.dirname(self.output_path), r'temp.shp') QgsVectorFileWriter.writeAsVectorFormat(pointPassage, output_filename, "utf-8", crs, "ESRI Shapefile") pointPassage = None pointPassage = QgsVectorLayer(output_filename, 'pointpassage', "ogr") print 'R2P: Remove small ridge part' ids_rem = [] orphans = [] for pt in pointPassage.getFeatures(): pt_id = pt.id() pt_geom = pt.geometry().asPoint() pt_x, pt_y = pt_geom bounding_box_buff = QgsRectangle(pt_x - self.min_dist, pt_y - self.min_dist, pt_x + self.min_dist, pt_y + self.min_dist) pts_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff)) for pt_near in pts_near_it: pt_near_id = pt_near.id() if pt_near_id != pt_id: dist = math.sqrt( pt_geom.sqrDist(pt_near.geometry().asPoint())) if dist != 0 and dist < self.min_dist: pt_Tid = pt.attribute('T_id') res = pt_Tid.split('p') l_id1 = res[0] pt_near_Tid = pt_near.attribute('T_id') res = pt_near_Tid.split('p') l_id2 = res[0] if l_id1 == l_id2 and ( (pt_Tid[-1] == 's' and pt_near_Tid[-1] == 'e') or (pt_Tid[-1] == 'e' and pt_near_Tid[-1] == 's')): if pt_id not in ids_rem: ids_rem.append(pt_id) if pt_near_id not in ids_rem: ids_rem.append(pt_near_id) # if pt_Tid in orphans: # orphans.remove(pt_Tid) # if pt_near_Tid in orphans: # orphans.remove(pt_near_Tid) BB1 = pt.geometry().buffer(3, 4).boundingBox() BB2 = pt_near.geometry().buffer(3, 4).boundingBox() for feat1 in pointPassage.getFeatures( QgsFeatureRequest( QgsExpression( "nature='start' or nature='end'")). setFilterRect(BB1)): tid1 = feat1.attribute("T_id") if feat1.id( ) not in ids_rem and tid1 not in orphans: orphans.append(tid1) for feat2 in pointPassage.getFeatures( QgsFeatureRequest( QgsExpression( "nature='start' or nature='end'")). setFilterRect(BB2)): tid2 = feat2.attribute("T_id") if feat2.id( ) not in ids_rem and tid2 not in orphans: orphans.append(tid2) pointPassage.startEditing() pointPassage.dataProvider().deleteFeatures(ids_rem) pointPassage.commitChanges() # Find link point between seperate line print 'R2P: Find link point between seperate line' already_done = [] geom_to_change = [] for pt in pointPassage.getFeatures(): if pt.attribute('T_id') in orphans: pt_id = pt.id() pt_nat = pt.attribute('nature') if pt_nat == 'end': pt_nat_opp = 'start' else: pt_nat_opp = 'end' pt_opp_it = None pt_opp_it = pointPassage.getFeatures( QgsFeatureRequest( QgsExpression("L_id = '%s' and nature='%s'" % (pt.attribute('L_id'), pt_nat_opp)))) pt_opp = next(pt_opp_it) pt_opp_geom = pt_opp.geometry().asPoint() pt_opp_buff = pt_opp.geometry().buffer(1, 4).boundingBox() pt_opp_near_it = pointPassage.getFeatures( QgsFeatureRequest( QgsExpression("L_id != '%s'" % (pt_opp.attribute('L_id'))))) list_opp = [ pt_opp_near.attribute('T_id') for pt_opp_near in pt_opp_near_it ] list_opp.append(pt_opp.attribute('T_id')) pt_geom = pt.geometry().asPoint() pt_x, pt_y = pt_geom bounding_box_buff = QgsRectangle(pt_x - self.min_dist * 2, pt_y - self.min_dist * 2, pt_x + self.min_dist * 2, pt_y + self.min_dist * 2) pts_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff)) list_id = [] w0 = 0 id0 = pt_id act_dist = None list_line = [] for pt_near in pts_near_it: pt_near_id = pt_near.id() pt_near_Tid = pt_near.attribute('T_id') pt_near_geom = pt_near.geometry().asPoint() if pt_near_id != pt_id and pt_near_Tid in orphans and pt_near_geom != pt_opp_geom: dist = math.sqrt(pt_geom.sqrDist(pt_near_geom)) if dist != 0 and dist < self.min_dist * 2: pt_Tid = pt.attribute('T_id') res = pt_Tid.split('p') l_id1 = res[0] res = pt_near_Tid.split('p') l_id2 = res[0] if pt_id not in already_done and l_id1 != l_id2 and l_id2 not in list_line and pt_Tid[ -1] in ['s', 'e'] and pt_near_Tid[-1] in [ 's', 'e' ]: list_id.append(pt_near_id) list_line.append(l_id2) w0 += dist already_done.append(pt_id) for id in list_id: point1 = next( pointPassage.getFeatures( QgsFeatureRequest().setFilterFid(id))) point1_geom = point1.geometry().asPoint() pt1_x, pt1_y = point1_geom bounding_box_buff1 = QgsRectangle(pt_x - self.min_dist * 2, pt_y - self.min_dist * 2, pt_x + self.min_dist * 2, pt_y + self.min_dist * 2) pts1_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff1)) w = 0 for opoint in pts1_near_it: if id != opoint.id() and opoint.attribute( 'T_id') in orphans: opoint_geom = opoint.geometry().asPoint() p = math.sqrt(point1_geom.sqrDist(opoint_geom)) w += p if w < w0: w0 = w id0 = opoint.id() already_done.append(id) list_id.append(pt_id) try: list_id.remove(id0) except ValueError: continue change = [id0, list_id] geom_to_change.append(change) for change in geom_to_change: id_fix = change[0] req = QgsFeatureRequest().setFilterFid(id_fix) point_fix_it = pointPassage.getFeatures(req) try: for point_fix in point_fix_it: geom_fix = point_fix.geometry() # try: # orphans.remove(point_fix.attribute("T_id")) # except ValueError: # continue ids_change = change[1] for id_change in ids_change: req = QgsFeatureRequest().setFilterFid(id_change) point_change_it = pointPassage.getFeatures(req) point_change = next(point_change_it) # try: # orphans.remove(point_change.attribute("T_id")) # except ValueError: # continue pointPassage.startEditing() pointPassage.dataProvider().changeGeometryValues( {id_change: geom_fix}) pointPassage.commitChanges() pointPassage.updateExtents() except StopIteration: pass print 'R2P: Find link point between seperate line' already_done = [] geom_to_change = [] for pt in pointPassage.getFeatures(): pt_id = pt.id() pt_geom = pt.geometry().asPoint() pt_x, pt_y = pt_geom bounding_box_buff = QgsRectangle(pt_x - self.min_dist, pt_y - self.min_dist, pt_x + self.min_dist, pt_y + self.min_dist) pts_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff)) list_id = [] w0 = 0 id0 = pt_id for pt_near in pts_near_it: pt_near_id = pt_near.id() pt_near_Tid = pt_near.attribute('T_id') if pt_near_id != pt_id: dist = math.sqrt( pt_geom.sqrDist(pt_near.geometry().asPoint())) if dist != 0 and dist < self.min_dist: pt_Tid = pt.attribute('T_id') res = pt_Tid.split('p') l_id1 = res[0] res = pt_near_Tid.split('p') l_id2 = res[0] if pt_id not in already_done and l_id1 != l_id2 and pt_Tid[ -1] in ['s', 'e' ] and pt_near_Tid[-1] in ['s', 'e']: list_id.append(pt_near_id) w0 += dist already_done.append(pt_id) for id in list_id: point1 = next( pointPassage.getFeatures( QgsFeatureRequest().setFilterFid(id))) point1_geom = point1.geometry().asPoint() pt1_x, pt1_y = point1_geom bounding_box_buff1 = QgsRectangle(pt_x - self.min_dist, pt_y - self.min_dist, pt_x + self.min_dist, pt_y + self.min_dist) pts1_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff1)) w = 0 for opoint in pts1_near_it: if id != opoint.id(): opoint_geom = opoint.geometry().asPoint() p = math.sqrt(point1_geom.sqrDist(opoint_geom)) w += p if w < w0: w0 = w id0 = opoint.id() already_done.append(id) list_id.append(pt_id) try: list_id.remove(id0) except ValueError: continue change = [id0, list_id] geom_to_change.append(change) for change in geom_to_change: id_fix = change[0] req = QgsFeatureRequest().setFilterFid(id_fix) point_fix_it = pointPassage.getFeatures(req) try: for point_fix in point_fix_it: geom_fix = point_fix.geometry() ids_change = change[1] for id_change in ids_change: pointPassage.startEditing() pointPassage.dataProvider().changeGeometryValues( {id_change: geom_fix}) pointPassage.commitChanges() pointPassage.updateExtents() except StopIteration: pass # Remove small ridge part at the end/start of a line print 'R2P: Remove small ridge part at the end/start of a line' geom_to_change = [] list_id = [] for pt in pointPassage.getFeatures(): pt_id = pt.id() pt_geom = pt.geometry().asPoint() pt_x, pt_y = pt_geom bounding_box_buff = QgsRectangle(pt_x - self.min_dist, pt_y - self.min_dist, pt_x + self.min_dist, pt_y + self.min_dist) pts_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff)) for pt_near in pts_near_it: pt_near_id = pt_near.id() if pt_near_id != pt_id: dist = math.sqrt( pt_geom.sqrDist(pt_near.geometry().asPoint())) if dist != 0 and dist < self.min_dist: pt_Tid = pt.attribute('T_id') res = pt_Tid.split('p') l_id1 = res[0] pt_near_Tid = pt_near.attribute('T_id') res = pt_near_Tid.split('p') l_id2 = res[0] if l_id1 == l_id2 and pt_Tid[-1] in [ 's', 'e' ] and pt_near_Tid[-1] not in [ 's', 'e' ] and pt_near_Tid not in list_id: change = [pt_id, pt_near_id] list_id.append(pt_near_Tid) geom_to_change.append(change) id_rm = [] print 'R2P: geom_to_change: %s' % geom_to_change for change in geom_to_change: id_fix = change[0] req = QgsFeatureRequest().setFilterFid(id_fix) point_fix_it = pointPassage.getFeatures(req) point_fix = next(point_fix_it) try: id_change = change[1] req = QgsFeatureRequest().setFilterFid(id_change) point_ch_it = pointPassage.getFeatures(req) for point_ch in point_ch_it: if point_fix.attribute('T_id')[-1] == 'e': if int(point_ch.attribute('P_id')) < int( point_fix.attribute('P_id')): pointPassage.startEditing() pointPassage.changeAttributeValue( id_fix, 2, point_ch.attribute('P_id')) pointPassage.commitChanges() else: pointPassage.startEditing() pointPassage.changeAttributeValue( id_fix, 2, point_ch.attribute('P_id')) pointPassage.commitChanges() id_rm.append(id_change) except StopIteration: pass pointPassage.startEditing() pointPassage.deleteFeatures(id_rm) pointPassage.commitChanges() pointPassage.updateExtents() # First attempt print 'R2P: First attempt' already_done = [] geom_to_change = [] for pt in pointPassage.getFeatures(): pt_id = pt.id() pt_geom = pt.geometry().asPoint() pt_x, pt_y = pt_geom bounding_box_buff = QgsRectangle(pt_x - self.min_dist, pt_y - self.min_dist, pt_x + self.min_dist, pt_y + self.min_dist) pts_near_it = pointPassage.getFeatures( QgsFeatureRequest().setFilterRect(bounding_box_buff)) list_id = [] w0 = 0 id0 = pt_id for pt_near in pts_near_it: pt_near_id = pt_near.id() if pt_near_id != pt_id: dist = math.sqrt( pt_geom.sqrDist(pt_near.geometry().asPoint())) if dist != 0 and dist < self.min_dist: pt_Tid = pt.attribute('T_id') res = pt_Tid.split('p') l_id1 = res[0] pt_near_Tid = pt_near.attribute('T_id') res = pt_near_Tid.split('p') l_id2 = res[0] if pt_id not in already_done and pt_near_id not in already_done and l_id1 == l_id2: pt1_elev = self.dem_layer.dataProvider().identify( pt_geom, QgsRaster.IdentifyFormatValue) pt2_elev = self.dem_layer.dataProvider().identify( pt_near.geometry().asPoint(), QgsRaster.IdentifyFormatValue) already_done.append(pt_id) already_done.append(pt_near_id) if pt.attribute( 'T_id')[-1] == 'd' and pt_near.attribute( 'T_id') == 'd': if pt1_elev > pt2_elev: change = pt_Tid else: change = pt_near_Tid else: if pt1_elev < pt2_elev: change = pt_Tid else: change = pt_near_Tid geom_to_change.append(change) print 'R2P: geom_to_change: %s' % geom_to_change for change in geom_to_change: print 'R2P: change: %s' % change id_fix = change req = QgsFeatureRequest().setFilterExpression("T_id = '%s'" % (id_fix)) point_rm_it = pointPassage.getFeatures(req) point_rm = point_rm_it.next() id_rm = point_rm.id() line_id = point_rm.attribute('L_id') point_pid = int(point_rm.attribute('P_id')) nat = point_rm.attribute('nature') fin = 0 count = 1 found = False if nat == 'end': fin = 1 else: pointPassage.startEditing() while True: if found: point_pid += 1 req = QgsFeatureRequest().setFilterExpression( "L_id ='%s' and P_id = '%s'" % (line_id, str(point_pid + count))) point_nxt_it = pointPassage.getFeatures(req) found = False point_nxt = None try: point_nxt = next(point_nxt_it) except StopIteration: point_nxt = None continue if point_nxt != None: pointPassage.changeAttributeValue( point_nxt.id(), 2, str(point_pid)) current_id = point_nxt.attribute('T_id') if current_id[-1] == 'e': break print 'R2P: current_id: %s' % current_id found = True count = 1 else: count += 1 found = False pointPassage.deleteFeatures([id_rm]) pointPassage.commitChanges() pointPassage.updateExtents() time.stop() print 'R2P: Processing Time:' time.show() error = QgsVectorFileWriter.writeAsVectorFormat( pointPassage, self.output_path, "utf-8", crs, "ESRI Shapefile") if error == QgsVectorFileWriter.NoError: print "R2P: Success!" out_layer = self.iface.addVectorLayer(self.output_path, "", "ogr") if not out_layer: print "R2P: Layer failed to load!"
def testPktCompositeFloat(self): """ Check that tables with PKs composed of many fields of different types are correctly read and written to """ vl = QgsVectorLayer( '{} type=POINT key=\'"pk1","pk2","pk3"\' table="qgis_test"."tb_test_composite_float_pk" (geom)' .format(self.dbconn), "test_composite_float", "mssql") self.assertTrue(vl.isValid()) fields = vl.fields() f = next( vl.getFeatures( QgsFeatureRequest().setFilterExpression('pk3 = 3.14159274'))) # first of all: we must be able to fetch a valid feature self.assertTrue(f.isValid()) self.assertEqual(f['pk1'], 1) self.assertEqual(f['pk2'], 2) self.assertEqual(round(f['pk3'], 6), round(3.14159274, 6)) self.assertEqual(f['value'], 'test 2') # can we edit a field? vl.startEditing() vl.changeAttributeValue(f.id(), fields.indexOf('value'), 'Edited Test 2') self.assertTrue(vl.commitChanges()) # Did we get it right? Let's create a new QgsVectorLayer and try to read back our changes: vl2 = QgsVectorLayer( '{} sslmode=disable srid=4326 key=\'"pk1","pk2","pk3"\' table="qgis_test"."tb_test_composite_float_pk" (geom)' .format(self.dbconn), "test_composite_float2", "mssql") self.assertTrue(vl2.isValid()) f2 = next( vl.getFeatures( QgsFeatureRequest().setFilterExpression('pk3 = 3.14159274'))) self.assertTrue(f2.isValid()) # just making sure we have the correct feature # Only 6 decimals for PostgreSQL 11. self.assertEqual(round(f2['pk3'], 6), round(3.14159274, 6)) # Then, making sure we really did change our value. self.assertEqual(f2['value'], 'Edited Test 2') # How about inserting a new field? f3 = QgsFeature(vl2.fields()) f3['pk1'] = 4 f3['pk2'] = -9223372036854775800 f3['pk3'] = 7.29154 f3['value'] = 'other test' vl.startEditing() res, f3 = vl.dataProvider().addFeatures([f3]) self.assertTrue(res) self.assertTrue(vl.commitChanges()) # can we catch it on another layer? f4 = next( vl2.getFeatures(QgsFeatureRequest().setFilterExpression( 'pk2 = -9223372036854775800'))) self.assertTrue(f4.isValid()) expected_attrs = [4, -9223372036854775800, 7.29154, 'other test'] gotten_attrs = [f4['pk1'], f4['pk2'], round(f4['pk3'], 5), f4['value']] self.assertEqual(gotten_attrs, expected_attrs) # Finally, let's delete one of the features. f5 = next( vl2.getFeatures( QgsFeatureRequest().setFilterExpression('pk3 = 7.29154'))) vl2.startEditing() vl2.deleteFeatures([f5.id()]) self.assertTrue(vl2.commitChanges()) # did we really delete? f_iterator = vl.getFeatures( QgsFeatureRequest().setFilterExpression('pk3 = 7.29154')) got_feature = True try: f6 = next(f_iterator) got_feature = f6.isValid() except StopIteration: got_feature = False self.assertFalse(got_feature)
class ReorderProcess(): """Along line point reordering according to given destination""" def __init__(self, exutoire, point_reseau): """Set all informations needed to order the network""" self.exutoire_layer = exutoire self.point_reseau_layer = point_reseau self.crs = QgsCoordinateReferenceSystem( self.point_reseau_layer.crs().authid()) # Create ouput self.output = QgsVectorLayer("Point", "point", "memory") self.output.setCrs(self.crs) # Add fields name_T_id = "T_id" name_L_id = "L_id" name_P_id = "P_id" name_nat = "nature" provider = self.output.dataProvider() caps = provider.capabilities() if caps & QgsVectorDataProvider.AddAttributes: res = provider.addAttributes([ QgsField(name_T_id, QVariant.String), QgsField(name_L_id, QVariant.String), QgsField(name_P_id, QVariant.String), QgsField(name_nat, QVariant.String) ]) self.output.updateFields() # Save field index self.index_nat = self.point_reseau_layer.fieldNameIndex('nature') self.index_pid = self.point_reseau_layer.fieldNameIndex('P_id') self.index_order = self.point_reseau_layer.fieldNameIndex('order') self.l_done = [] def reorder(self, pt, count_order): feat = QgsFeature(self.output.pendingFields()) pt_geom = pt.geometry() feat.setGeometry(pt_geom) tid = pt.attribute("T_id") lid = pt.attribute("L_id") ppid = pt.attribute("P_id") nat = pt.attribute("nature") if nat == 'start': self.output.startEditing() feat.setAttributes([tid, str(count_order), ppid, nat]) print 'reorder: %s' % ([tid, lid, ppid, nat, str(count_order)]) self.output.dataProvider().addFeatures([feat]) self.output.commitChanges() self.output.updateExtents() while nat != 'end': expr = QgsExpression('L_id = %s and P_id = %s' % (lid, str(int(ppid) + 1))) req = QgsFeatureRequest(expr) n_pt_it = self.point_reseau_layer.getFeatures(req) n_pt = n_pt_it.next() n_pt_it = None feat = QgsFeature(self.output.pendingFields()) n_pt_geom = n_pt.geometry() feat.setGeometry(n_pt_geom) tid = n_pt.attribute("T_id") lid = n_pt.attribute("L_id") ppid = n_pt.attribute("P_id") nat = n_pt.attribute("nature") self.output.startEditing() feat.setAttributes([tid, str(count_order), ppid, nat]) print[tid, lid, ppid, nat, str(count_order)] self.output.dataProvider().addFeatures([feat]) self.output.commitChanges() self.output.updateExtents() else: pid = 0 self.output.startEditing() feat.setAttributes([tid, str(count_order), str(pid), 'start']) print[tid, lid, str(pid), 'start', str(count_order)] self.output.dataProvider().addFeatures([feat]) self.output.commitChanges() self.output.updateExtents() nat = None feat = None while nat != 'start': ppid = str(int(ppid) - 1) expr = QgsExpression('L_id = %s and P_id = %s' % (lid, ppid)) req = QgsFeatureRequest(expr) n_pt_it = self.point_reseau_layer.getFeatures(req) n_pt = n_pt_it.next() n_pt_it = None feat = QgsFeature(self.output.pendingFields()) n_pt_geom = n_pt.geometry() feat.setGeometry(n_pt_geom) tid = n_pt.attribute("T_id") nat = n_pt.attribute("nature") if nat != 'start': pid += 1 self.output.startEditing() feat.setAttributes([tid, str(count_order), str(pid), nat]) print[tid, lid, str(pid), nat, str(count_order)] self.output.dataProvider().addFeatures([feat]) self.output.commitChanges() self.output.updateExtents() feat = None else: pid += 1 self.output.startEditing() feat.setAttributes( [tid, str(count_order), str(pid), 'end']) print[tid, lid, str(pid), 'end', str(count_order)] self.output.dataProvider().addFeatures([feat]) self.output.commitChanges() self.output.updateExtents() feat = None def executeReorder(self): count_order = 0 # loop over exutoire features to process several network for exutoire in self.exutoire_layer.getFeatures(): exutoire_geom = exutoire.geometry().buffer(1, 4).boundingBox() # Select the start point that intersects the outlet req = QgsFeatureRequest().setFilterRect(exutoire_geom) pts_reseau_sortie = self.point_reseau_layer.getFeatures(req) for pt_sortie in pts_reseau_sortie: count_order += 1 L_id = pt_sortie.attribute("L_id") # Reorder the points of the first line of the network self.reorder(pt_sortie, count_order) nat = 'end' string = "L_id = %s AND nature = '%s'" % (count_order, nat) print string expr = QgsExpression(string) reque = QgsFeatureRequest(expr) # Select the last point of the first line pt_end_it = self.output.getFeatures(reque) pt_end = pt_end_it.next() pt_end_it = None # Make a buffer around the point to define a boundingBox pt_end_geom = pt_end.geometry().buffer(1, 4).boundingBox() req = QgsFeatureRequest( QgsExpression("L_id != %s" % (str(L_id)))).setFilterRect(pt_end_geom) # Select the next points next_ls = self.point_reseau_layer.getFeatures(req) self.l_done.append(L_id) list_next = [] # Fill next_ls list with the next features for next_l in next_ls: list_next.append(next_l) # While there is features in list_next, reorder process continues while len(list_next) != 0: current_list = list_next list_next = [] # Loop over the next features for next_pt in current_list: # Get line id L_id = next_pt.attribute("L_id") print L_id # if the line has not been already reorder if L_id not in self.l_done: count_order += 1 #then reorder self.reorder(next_pt, count_order) string = "L_id = %s AND nature='%s'" % ( count_order, nat) print string expr = QgsExpression(string) req = QgsFeatureRequest(QgsExpression(expr)) pt_end_it = self.output.getFeatures(req) pt_end = pt_end_it.next() pt_end_it = None pt_end_geom = pt_end.geometry().buffer( 1, 4).boundingBox() # Find the next feature reque = QgsFeatureRequest( QgsExpression( "L_id != %s" % (L_id))).setFilterRect(pt_end_geom) next_ls = self.point_reseau_layer.getFeatures( reque) self.l_done.append(L_id) # Fill next_ls list again and loop for next_l in next_ls: list_next.append(next_l) print len(list_next) expr = QgsExpression("nature = 'end'") req = QgsFeatureRequest(expr) end_pts = self.output.getFeatures(req) change_dict = {} change_list = [] rm_ids = [] #clean lines that aren't a cross border anymore because a small part has been removed for end_pt in end_pts: end_pt_geom = end_pt.geometry().buffer(1, 4).boundingBox() end_pt_id = end_pt.id() end_lid = end_pt.attribute("L_id") end_pid = end_pt.attribute("P_id") expr = QgsExpression("L_id != '%s'" % (end_lid)) req = QgsFeatureRequest(expr).setFilterRect(end_pt_geom) int_pts = [] for int_pt in self.output.getFeatures(req): lid_int_pt = int_pt.attribute("L_id") int_pts.append(int_pt) if len(int_pts) == 1: rm_ids.append(end_pt_id) if int(end_lid) in change_dict: change_dict[int(lid_int_pt)] = change_dict[int(end_lid)] else: change_dict[int(lid_int_pt)] = int(end_lid) print change_dict change_dict = sorted(change_dict.items(), key=lambda t: t[0]) for ch_tuple in change_dict: print ch_tuple[0] end_lid = str(ch_tuple[1]) end_pid = None for end_pt in self.output.getFeatures( QgsFeatureRequest( QgsExpression("L_id = '%s' and nature = '%s'" % (end_lid, "end")))): if end_pid is None: end_pid = end_pt.attribute("P_id") elif int(end_pid) < int(end_pt.attribute("P_id")): end_pid = end_pt.attribute("P_id") expr = QgsExpression("L_id = '%s'" % (str(ch_tuple[0]))) req = QgsFeatureRequest(expr) for ch_pt in self.output.getFeatures(req): ch_pt_id = ch_pt.id() if ch_pt.attribute("nature") == "start": rm_ids.append(ch_pt_id) else: ch_tid = ch_pt.attribute("T_id") ch_nature = ch_pt.attribute("nature") self.output.startEditing() self.output.changeAttributeValue(ch_pt_id, 1, end_lid) self.output.changeAttributeValue(ch_pt_id, 2, end_pid) self.output.commitChanges() end_pid = int(end_pid) + 1 self.output.startEditing() self.output.deleteFeatures(rm_ids) self.output.commitChanges() return self.output, self.crs
class StartNotSimple: def __init__(self, iface): self.iface = iface self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' def initGui(self): # cria uma ação que iniciará a configuração do plugin pai = self.iface.mainWindow() icon_path = ':/plugins/StartNotSimple/icon.png' self.action = QAction (QIcon (icon_path),u"Acessa banco de dados para revisão de Geometria Simples", pai) self.action.setObjectName ("Stard database") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.triggered.connect(self.run) # Adicionar o botão icone self.iface.addToolBarIcon (self.action) #Cria uma nova toolbar #self.toolbar = self.iface.addToolBar(u'Validation Tool') #self.toolbar.addAction(self.action) def unload(self): # remove o item de ícone do QGIS GUI. self.iface.removeToolBarIcon (self.action) def run(self): ################################## ###### PEGA A LAYER ATIVA ######## ################################## layer = self.iface.activeLayer() if not layer: self.iface.messageBar().pushMessage("Erro", u"Esperando uma Active Layer!", level=QgsMessageBar.CRITICAL, duration=4) return if layer.featureCount() == 0: self.iface.messageBar().pushMessage("Erro", u"a camada não possui feições!", level=QgsMessageBar.CRITICAL, duration=4) return parametros = layer.source().split(" ") # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len(user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage("Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen(): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage("Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values(): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([QgsField("id", QVariant.Int), QgsField("geomId", QVariant.String), QgsField("motivo", QVariant.String)]) self.flagsLayer.updateFields() self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista for f in layer.getFeatures(): lista_fid.append(str(f.id())) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = layer.source().split(" ") self.tableName = " " # Inicia vazio layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage("Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return ############################## #### Busca através do SQL #### ############################## sql = """select foo."{3}" as "{3}", ST_AsText(ST_MULTI(st_startpoint(foo."{2}"))) as "{2}" from ( select "{3}" as "{3}", (ST_Dump(ST_Node(ST_SetSRID(ST_MakeValid("{2}"),ST_SRID("{2}"))))).geom as "{2}" from "{0}"."{1}" where ST_IsSimple("{2}") = 'f' and {3} in ({4})) as foo where st_equals(st_startpoint(foo."{2}"),st_endpoint(foo."{2}"))""".format(self.tableSchema, self.tableName, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) query = QSqlQuery(sql) self.flagsLayer.startEditing() flagCount = 0 # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): id = query.value(0) # recebendo valores buscados no sql local = query.value(1) # recebendo valores buscados no sql motivo = query.value(2) print local, id, motivo flagId = flagCount flagFeat = QgsFeature() flagFeat.setFields(self.flagsLayer.fields()) # passa quais atributos serão usados. flagGeom = QgsGeometry.fromWkt(local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.setAttribute(0, flagId) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute(1, id) # insere o id da geometria para a coluna 1 da layer de memória. flagFeat.setAttribute(2, u"A geometria não é simples.") listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer(self.flagsLayer) # Adicione a camada no mapa if flagCount == 0: QgsMapLayerRegistry.instance().removeMapLayer(self.flagsLayer.id()) self.iface.messageBar().pushMessage("Aviso", u"Não foi encontrado Flags em \"" + layer.name() + "\" !", level=QgsMessageBar.CRITICAL, duration=4) return if len(query.lastError().text()) == 1: self.iface.messageBar().pushMessage("Aviso", "foram geradas " + str(flagCount) + " flags para a camada \"" + layer.name() + "\" !", level=QgsMessageBar.INFO, duration=4) else: self.iface.messageBar().pushMessage("Erro", u"a geração de flags falhou!", level=QgsMessageBar.CRITICAL, duration=4) print query.lastError().text()
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ source_distance = self.parameterAsDouble(parameters, self.INPUT_DISTANCE, context) source_dem = self.parameterAsRasterLayer(parameters, self.INPUT_DEM, context) source_points = self.parameterAsVectorLayer(parameters, self.INPUT_POINTS, context) source_field = self.parameterAsFields(parameters, self.INPUT_FIELD, context) output_summit = self.parameterAsOutputLayer(parameters, self.OUTPUT_SUMMIT, context) output_folder = self.parameterAsString(parameters, self.OUTPUT_FOLDER, context) results = {} outputs = {} #feedback = QgsProcessingMultiStepFeedback(3, feedback) feedback.pushInfo('Hello World') if not os.path.exists( output_folder): #If the folder indicated is not existing os.makedirs(output_folder) #Creating the folder url_buffer_1 = output_folder + '/buffer.shp' url_buffer_2 = output_folder + '/buffer_overlaping.shp' url_buffer_3 = output_folder + '/buffer_overlaping_summit.shp' url_buffer_4 = output_folder + '/buffer_AUTO.shp' url_buffer_5 = output_folder + '/points_incremented.shp' url_buffer_6 = output_folder + '/summit_process_all.gpkg' liste_url = [ url_buffer_1, url_buffer_2, url_buffer_3, url_buffer_4, url_buffer_5, url_buffer_6 ] for url_buffer in liste_url: if os.path.isfile(url_buffer): #If one of these url already exist os.remove(url_buffer) #Removing the file at this url feedback.pushInfo("Removing: " + url_buffer) if source_field == []: feedback.pushInfo( "Adding auto-incremental field to the point layer") # Add autoincremental field alg_params = { 'FIELD_NAME': 'ID_Point', 'GROUP_FIELDS': None, 'INPUT': source_points, 'SORT_ASCENDING': True, 'SORT_EXPRESSION': '', 'SORT_NULLS_FIRST': False, 'START': 0, 'OUTPUT': url_buffer_5 } outputs['AddAutoincrementalField_start'] = processing.run( 'native:addautoincrementalfield', alg_params, context=context, feedback=feedback) source_field = ['ID_Point'] source_points = outputs['AddAutoincrementalField_start']['OUTPUT'] # Buffer #Buffer polygons have the same attributes as the points alg_params = { 'DISSOLVE': False, 'DISTANCE': source_distance, 'END_CAP_STYLE': 0, 'INPUT': source_points, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'SEGMENTS': 5, 'OUTPUT': url_buffer_1 } outputs['Buffer'] = processing.run('native:buffer', alg_params, context=context, feedback=feedback) # Summit process alg_params = { 'INPUT_AREA': outputs['Buffer']['OUTPUT'], 'INPUT_DEM': source_dem, 'INPUT_FIELD': source_field[0], 'OUTPUT_SUMMIT': url_buffer_6, 'OUTPUT_FOLDER': output_folder + '/Summit_computing_all' } outputs['SummitProcess'] = processing.run('script:summitprocess_2', alg_params, context=context, feedback=feedback) # Extract by location: buffers overlaping between themselves alg_params = { 'INPUT': outputs['Buffer']['OUTPUT'], 'INTERSECT': outputs['Buffer']['OUTPUT'], 'PREDICATE': 5, 'OUTPUT': url_buffer_2 } outputs['ExtractByLocation_1'] = processing.run( 'native:extractbylocation', alg_params, context=context, feedback=feedback) if feedback.isCanceled(): return None # Extract by location: summits which are in a buffer intersecting another buffer polygon alg_params = { 'INPUT': outputs['SummitProcess']['OUTPUT_SUMMIT'], 'INTERSECT': outputs['ExtractByLocation_1']['OUTPUT'], 'PREDICATE': 0, 'OUTPUT': url_buffer_3 } outputs['ExtractByLocation_2'] = processing.run( 'native:extractbylocation', alg_params, context=context, feedback=feedback) if feedback.isCanceled(): return None ###Deletion from the overall summit layer, of summits which are in a buffer intersecting another buffer polygon layer_all_summit = QgsVectorLayer( outputs['SummitProcess']['OUTPUT_SUMMIT'], "layer_all_summit", "ogr" ) #Create as a vector layer, a layer gathering all the summits layer_1 = QgsVectorLayer( outputs['ExtractByLocation_2']['OUTPUT'], "layer_1", "ogr" ) #Create as a vector layer, a layer of the summits which may intersect multiples buffers features_all_summit = layer_all_summit.getFeatures( ) #Getting the features features_1 = layer_1.getFeatures() #Getting the features liste_suppress = [ ] #Initializing a list which will keep in memory the summits whiwh will be deleted fid_max = layer_all_summit.featureCount( ) #Get the number of summit. This value will be used to set the next summits id for index_all_summit, summit_all in enumerate( features_all_summit): #Iterating over all summits layer_summit_buffer_chevauche = QgsVectorLayer( outputs['ExtractByLocation_2']['OUTPUT'], "layer_summit_buffer_chevauche", "ogr") #Create as a vector layer, a layer features_summit_buffer_chevauche = layer_summit_buffer_chevauche.getFeatures( ) #Getting the features for index_summit_buffer_chevauche, summit_buffer_chevauche in enumerate( features_summit_buffer_chevauche ): #Iterating over summits which are in a contentious buffer if summit_all.attributes( ) == summit_buffer_chevauche.attributes( ): #if the contentious summit is in the overall summit layer liste_suppress.append( summit_all.id()) #Add the summit to the suppress list feedback.pushInfo( "Deletion of summits which intersect at least two buffers") layer_all_summit.startEditing() #Enabling edition layer_all_summit.deleteFeatures( liste_suppress ) #Deleting contentious summits of the overall summit layer layer_all_summit.commitChanges() #Commiting the changes feedback.pushInfo(str(layer_all_summit.commitErrors( ))) #Displaying a message about the state of the commit total = 100 / layer_1.featureCount() #Initializing the progress bar for index_1, summit_1 in enumerate( features_1): #Iterating over contentious summits feedback.setProgress(int(index_1 * total)) #Update the progress bar layer_2 = QgsVectorLayer( outputs['ExtractByLocation_2']['OUTPUT'], "layer_2", "ogr") #Create as a vector layer, the contentious summits features_2 = layer_2.getFeatures() #Getting features for index_2, summit_2 in enumerate( features_2 ): #Iterating over contentious summits. These two loops allows to compare summits in the same layer summit_1_geometry = summit_1.geometry().asPoint( ) #Getting the geometry of the summit number 1 summit_2_geometry = summit_2.geometry().asPoint( ) #Getting the geometry of the summit number 2 if summit_1_geometry.toString() == summit_2_geometry.toString( ): #If they have the same geometry (may be optimised by using the function equals()) ID_point_summit_1 = summit_1.attribute( source_field[0] ) #Getting the ID of the buffer polygon of the summit number 1 ID_point_summit_2 = summit_2.attribute( source_field[0] ) #Getting the ID of the buffer polygon of the summit number 2 if ID_point_summit_1 != ID_point_summit_2: #If the two points don't come from the same buffer polygon features_source_points = source_points.getFeatures() for indx, points_source in enumerate( features_source_points ): #Searching in the point layer given by the user, the two current points if points_source.attribute( source_field[0]) == ID_point_summit_1: point_summit_1 = points_source #Getting the point which was be used to create the buffer polygon of the summit number 1 if points_source.attribute( source_field[0]) == ID_point_summit_2: point_summit_2 = points_source #Getting the point which was be used to create the buffer polygon of the summit number 2 #Calculating the minimal distance between the two original points and the summit distance_min = m.sqrt( m.pow( point_summit_1.geometry().asPoint().x() - summit_1_geometry.x(), 2) + m.pow( point_summit_1.geometry().asPoint().y() - summit_1_geometry.y(), 2)) distance = m.sqrt( m.pow( point_summit_2.geometry().asPoint().x() - summit_1_geometry.x(), 2) + m.pow( point_summit_2.geometry().asPoint().y() - summit_1_geometry.y(), 2)) if distance < distance_min: distance_min = distance layer_2_copy = QgsVectorLayer( outputs['ExtractByLocation_2']['OUTPUT'], "layer_2", "ogr" ) #Create as a layer, the contentious summits in order to update the ID features_2_copy = layer_2_copy.getFeatures( ) #Getting features for index_2_copy, summit_2_copy in enumerate( features_2_copy ): #Iterating over the contentious summits if str(summit_2_copy.attributes()) == str( summit_1.attributes() ): #Retrieving the summit number 1 in this layer in order to have the right ID summit_1_in_layer_2 = summit_2_copy feedback.pushInfo("Minimal distance: " + str(distance_min)) feedback.pushInfo("Deleting: " + str( layer_2.getFeature( summit_2.id()).attributes()) + " and " + str( layer_2.getFeature(summit_1_in_layer_2.id( )).attributes())) layer_2.startEditing() #Enabling edition mode layer_2.deleteFeatures( [summit_2.id(), summit_1_in_layer_2.id()] ) #Deleting the two summits which have the same geometry layer_2.commitChanges() #Commiting changes feedback.pushInfo(str(layer_2.commitErrors( ))) #Displaying a message about the commit state #Creating a temporary layer liste_fields = [ ] #Initializing a field list in order to create the summit fields list for i in range( summit_1.fields().size()): #For each fields field_i = summit_1.fields().field(i) liste_fields.append([ field_i.name(), field_i.typeName() ]) #[Name of the field, Type of the field] new_layer = _create_layer( "Point", "32616", liste_fields, "layer_2_points") #Create a new point layer new_layer.startEditing() #Enabling edition mode point_summit_1.setAttributes( [1] + point_summit_1.attributes() ) #Setting the attributes in order to match to a new field "fid" added when the temporary layer was created point_summit_2.setAttributes( [2] + point_summit_2.attributes() ) #Setting the attributes in order to match to a new field "fid" added when the temporary layer was created new_layer.dataProvider().addFeatures( [point_summit_1, point_summit_2] ) #Adding the two summits which have the same geometry new_layer.commitChanges() #Commiting changes #Setting a new folder to save intermediate files for each time when two summits have the same geometry new_folder_string = output_folder + '/Summit_computing_buffer_' + str( ID_point_summit_1) + "_" + str(ID_point_summit_2) if not os.path.exists( new_folder_string ): #If the folder indicated is not existing os.makedirs( new_folder_string) #Creating the folder url_buffer_7 = new_folder_string + '/buffer_2_points.shp' url_buffer_8 = new_folder_string + '/buffer_2_points_without_fid.shp' liste_url = [url_buffer_7, url_buffer_8] for url_buffer in liste_url: if os.path.isfile( url_buffer ): #If one of these url already exist os.remove( url_buffer) #Removing the file at this url #Creating new buffer around the two original points which have their summits identical, but this time with a smaller distance # Buffer alg_params = { 'DISSOLVE': False, 'DISTANCE': distance_min, 'END_CAP_STYLE': 0, 'INPUT': new_layer, 'JOIN_STYLE': 0, 'MITER_LIMIT': 2, 'SEGMENTS': 5, 'OUTPUT': new_folder_string + '/buffer_2_points.shp' } outputs['Buffer_2_points'] = processing.run( 'native:buffer', alg_params, context=context, feedback=feedback) #The "fid" field must be removed # Drop field(s) alg_params = { 'COLUMN': "fid", 'INPUT': outputs['Buffer_2_points']['OUTPUT'], 'OUTPUT': new_folder_string + '/buffer_2_points_without_fid.shp' } outputs['DropFields'] = processing.run( 'qgis:deletecolumn', alg_params, context=context, feedback=feedback, is_child_algorithm=True) if feedback.isCanceled(): return None #Calculating summits in this new area # Summit process alg_params = { 'INPUT_AREA': outputs['DropFields']['OUTPUT'], 'INPUT_DEM': source_dem, 'INPUT_FIELD': source_field[0], 'OUTPUT_SUMMIT': new_folder_string + '/layer_2_points.gpkg', 'OUTPUT_FOLDER': new_folder_string } outputs['SummitProcess_2_points'] = processing.run( 'script:summitprocess_2', alg_params, context=context, feedback=feedback) if feedback.isCanceled(): return None layer_2_points = QgsVectorLayer( outputs['SummitProcess_2_points']['OUTPUT_SUMMIT'], "layer_2_points", "ogr" ) #Create as a vector layer, the new summits which they were identical features_2_points = layer_2_points.getFeatures( ) #Getting features for indx, new_summit in enumerate( features_2_points): #For each new summit layer_1.startEditing() #Enabling edition mode layer_1.dataProvider().addFeatures( [new_summit] ) #Add the new summit to the contentious summit layer layer_1.commitChanges() #Commiting changes layer_output_summit = QgsVectorLayer( url_buffer_6, "layer_output_summit", "ogr") #Create as a vector layer, the output layer features_2 = layer_2.getFeatures( ) #Getting former contentious summits features for indx, summit_2 in enumerate( features_2): #For each former contentious summits layer_output_summit.startEditing() #Enabling edition mode summit_2.setAttributes( [fid_max + indx] + summit_2.attributes()[1:] ) #Setting the attributes in order to give a fid value than isn't already exist layer_output_summit.dataProvider().addFeatures([ summit_2 ]) #Add the former contentious summit to the output summit layer layer_output_summit.commitChanges() #Commiting changes feedback.pushInfo("Point added to the output layer " + str(summit_2.attributes())) layer_output_summit.endEditCommand() writer = QgsVectorFileWriter.writeAsVectorFormat( layer_output_summit, output_summit, "utf-8" ) #Saving the output layer in a vector layer at the path given by the user results['OUTPUT_SUMMIT'] = output_summit return results
def testPktComposite(self): """ Check that tables with PKs composed of many fields of different types are correctly read and written to """ vl = QgsVectorLayer( '{} type=POINT estimatedmetadata=true key=\'"pk1","pk2"\' table="qgis_test"."tb_test_compound_pk" (geom)' .format(self.dbconn), "test_compound", "mssql") self.assertTrue(vl.isValid()) fields = vl.fields() f = next( vl.getFeatures(QgsFeatureRequest().setFilterExpression( 'pk1 = 1 AND pk2 = 2'))) # first of all: we must be able to fetch a valid feature self.assertTrue(f.isValid()) self.assertEqual(f['pk1'], 1) self.assertEqual(f['pk2'], 2) self.assertEqual(f['value'], 'test 2') # can we edit a field? vl.startEditing() vl.changeAttributeValue(f.id(), fields.indexOf('value'), 'Edited Test 2') self.assertTrue(vl.commitChanges()) # Did we get it right? Let's create a new QgsVectorLayer and try to read back our changes: vl2 = QgsVectorLayer( '{} type=POINT estimatedmetadata=true table="qgis_test"."tb_test_compound_pk" (geom) key=\'"pk1","pk2"\' ' .format(self.dbconn), "test_compound2", "mssql") self.assertTrue(vl2.isValid()) f2 = next( vl2.getFeatures(QgsFeatureRequest().setFilterExpression( 'pk1 = 1 AND pk2 = 2'))) self.assertTrue(f2.isValid()) # Then, making sure we really did change our value. self.assertEqual(f2['value'], 'Edited Test 2') # How about inserting a new field? f3 = QgsFeature(vl2.fields()) f3['pk1'] = 4 f3['pk2'] = -9223372036854775800 f3['value'] = 'other test' vl.startEditing() res, f3 = vl.dataProvider().addFeatures([f3]) self.assertTrue(res) self.assertTrue(vl.commitChanges()) # can we catch it on another layer? f4 = next( vl2.getFeatures(QgsFeatureRequest().setFilterExpression( 'pk2 = -9223372036854775800'))) self.assertTrue(f4.isValid()) expected_attrs = [4, -9223372036854775800, 'other test'] self.assertEqual(f4.attributes(), expected_attrs) # Finally, let's delete one of the features. f5 = next( vl2.getFeatures(QgsFeatureRequest().setFilterExpression( 'pk1 = 2 AND pk2 = 1'))) vl2.startEditing() vl2.deleteFeatures([f5.id()]) self.assertTrue(vl2.commitChanges()) # did we really delete? Let's try to get the deleted feature from the first layer. f_iterator = vl.getFeatures( QgsFeatureRequest().setFilterExpression('pk1 = 2 AND pk2 = 1')) got_feature = True try: f6 = next(f_iterator) got_feature = f6.isValid() except StopIteration: got_feature = False self.assertFalse(got_feature)
class StartData: def __init__(self, iface): self.iface = iface self.tableSchema = 'edgv' self.geometryColumn = 'geom' self.keyColumn = 'id' def initGui(self): # cria uma ação que iniciará a configuração do plugin pai = self.iface.mainWindow() icon_path = ':/plugins/StartData/icon.png' self.action = QAction (QIcon (icon_path),u"Acessa banco de dados para revisão", pai) self.action.setObjectName ("Stard database") self.action.setStatusTip(None) self.action.setWhatsThis(None) self.action.triggered.connect(self.run) # Adicionar o botão icone self.iface.addToolBarIcon (self.action) def unload(self): # remove o item de ícone do QGIS GUI. self.iface.removeToolBarIcon (self.action) def run(self): ################################## ###### PEGA A LAYER ATIVA ######## ################################## layer = self.iface.activeLayer() if not layer: self.iface.messageBar().pushMessage("Erro", u"Esperando uma Active Layer!", level=QgsMessageBar.CRITICAL, duration=4) return if layer.featureCount() == 0: self.iface.messageBar().pushMessage("Erro", u"a camada não possui feições!", level=QgsMessageBar.CRITICAL, duration=4) return parametros = layer.source().split(" ") # recebe todos os parametros em uma lista ( senha, porta, password etc..) #################################### ###### INICIANDO CONEXÃO DB ######## #################################### # Outra opção para isso, seria usar ex: self.dbname.. self.host.. etc.. direto dentro do laço for. dbname = "" host = "" port = 0 user = "" password = "" for i in parametros: part = i.split("=") # Recebe os parametros guardados na própria Layer if "dbname" in part[0]: dbname = part[1].replace("'", "") elif "host" in part[0]: host = part[1].replace("'", "") elif "port" in part[0]: port = int(part[1].replace("'", "")) elif "user" in part[0]: user = part[1].replace("'", "") elif "password" in part[0]: password = part[1].split("|")[0].replace("'", "") #print dbname, host, port, user, password # Testa se os parametros receberam os valores pretendidos, caso não, apresenta a mensagem informando.. if len(dbname) == 0 or len(host) == 0 or port == 0 or len(user) == 0 or len(password) == 0: self.iface.messageBar().pushMessage("Erro", u'Um dos parametros não foram devidamente recebidos!', level=QgsMessageBar.CRITICAL, duration=4) return #################################### #### SETA VALORES DE CONEXÃO DB #### #################################### connection = QSqlDatabase.addDatabase('QPSQL') connection.setHostName(host) connection.setPort(port) connection.setUserName(user) connection.setPassword(password) connection.setDatabaseName(dbname) if not connection.isOpen(): # Testa se a conexão esta recebendo os parametros adequadamente. if not connection.open(): print 'Error connecting to database!' self.iface.messageBar().pushMessage("Erro", u'Error connecting to database!', level=QgsMessageBar.CRITICAL, duration=4) print connection.lastError().text() return #################################### ###### CRIAÇÃO DE MEMORY LAYER ##### #################################### layerCrs = layer.crs().authid() # Passa o formato (epsg: numeros) flagsLayerName = layer.name() + "_flags" flagsLayerExists = False for l in QgsMapLayerRegistry.instance().mapLayers().values(): # Recebe todas as camadas que estão abertas if l.name() == flagsLayerName: # ao encontrar o nome pretendido.. self.flagsLayer = l # flagslayer vai receber o nome.. self.flagsLayerProvider = l.dataProvider() flagsLayerExists = True # se encontrado os parametros buscados, recebe True. break if flagsLayerExists == False: # se não encontrado os parametros buscados, recebe False. tempString = "Point?crs=" tempString += str(layerCrs) self.flagsLayer = QgsVectorLayer(tempString, flagsLayerName, "memory") self.flagsLayerProvider = self.flagsLayer.dataProvider() self.flagsLayerProvider.addAttributes([QgsField("id", QVariant.Int), QgsField("motivo", QVariant.String)]) self.flagsLayer.updateFields() self.flagsLayer.startEditing() ids = [feat.id() for feat in self.flagsLayer.getFeatures()] self.flagsLayer.deleteFeatures(ids) self.flagsLayer.commitChanges() lista_fid = [] # Iniciando lista for f in layer.getFeatures(): lista_fid.append(str(f.id())) # Guarda na lista. A lista de Feature ids passa tipo "int", foi convertido e guardado como "str". source = layer.source().split(" ") self.tableName = "" # Inicia vazio layerExistsInDB = False for i in source: if "table=" in i or "layername=" in i: # Se encontrar os atributos pretendidos dentre todos do for self.tableName = source[source.index(i)].split(".")[1] # Faz split em ponto e pega a segunda parte. self.tableName = self.tableName.replace('"', '') layerExistsInDB = True break if layerExistsInDB == False: self.iface.messageBar().pushMessage("Erro", u"Provedor da camada corrente não provem do banco de dados!", level=QgsMessageBar.CRITICAL, duration=4) return # Busca através do SQL query_string = '''select distinct (reason(ST_IsValidDetail(f."{2}",0))) AS motivo, ''' query_string += '''ST_AsText(ST_Multi(ST_SetSrid(location(ST_IsValidDetail(f."{2}",0)), ST_Srid(f.{2})))) as local from ''' query_string += '''(select "{3}", "{2}" from only "{0}"."{1}" where ST_IsValid("{2}") = 'f' and {3} in ({4})) as f''' query_string = query_string.format(self.tableSchema, self.tableName, self.geometryColumn, self.keyColumn, ",".join(lista_fid)) query = QSqlQuery(query_string) self.flagsLayer.startEditing() flagCount = 0 # iniciando contador que será referência para os IDs da camada de memória. listaFeatures = [] while query.next(): motivo = query.value(0) local = query.value(1) flagId = flagCount flagFeat = QgsFeature() flagGeom = QgsGeometry.fromWkt(local) # passa o local onde foi localizado o erro. flagFeat.setGeometry(flagGeom) flagFeat.initAttributes(2) flagFeat.setAttribute(0,flagId) # insere o id definido para a coluna 0 da layer de memória. flagFeat.setAttribute(1, motivo) # insere o motivo/razão pré-definida para a coluna 1 da layer de memória. listaFeatures.append(flagFeat) flagCount += 1 # incrementando o contador a cada iteração self.flagsLayerProvider.addFeatures(listaFeatures) self.flagsLayer.commitChanges() # Aplica as alterações à camada. QgsMapLayerRegistry.instance().addMapLayer(self.flagsLayer) # Adicione a camada no mapa ################################## ##### TROCA MARCADOR DA LAYER #### ################################## # # AQUI PRETENDO PERSONALIZAR O MARCADOR DA MEMORY LAYER, POREM A PRINCIPIO SÓ ESTA ALTERANDO A LAYER ORIGINAL. # for lay in QgsMapLayerRegistry.instance().mapLayers().values(): # if lay == flagsLayerName and not layer.name(): # # Estilo base. # line = QgsLineSymbolV2() # # Crie uma linha de marcadores. # marker_line = QgsMarkerLineSymbolLayerV2() # marker_line.setInterval(10) # # Configure o marcador. # simple_marker = QgsSimpleMarkerSymbolLayerV2() # simple_marker.setShape(QgsSimpleMarkerSymbolLayerBase.HalfSquare) # Formato # simple_marker.setSize(3) # simple_marker.setAngle(180) # simple_marker.setColor(QColor('red')) # cor # simple_marker.setOutlineColor(QColor('red')) # cor # # O marcador tem sua própria camada de símbolo. # marker = QgsMarkerSymbolV2() # marker.changeSymbolLayer(0, simple_marker) # # Adicione a camada à camada do marcador. # marker_line.setSubSymbol(marker) # # Finalmente, substitua a camada de símbolo no estilo base. # line.changeSymbolLayer(0, marker_line) # # Adicione o estilo à camada de linha. # renderer = QgsSingleSymbolRendererV2(line) # layer.setRendererV2(renderer) if flagCount == 0: QgsMapLayerRegistry.instance().removeMapLayer(self.flagsLayer.id()) self.iface.messageBar().pushMessage("Aviso", u"Não foi encontrado Flags em \"" + layer.name() + "\" !", level=QgsMessageBar.CRITICAL, duration=4) return if len(query.lastError().text()) == 1: self.iface.messageBar().pushMessage("Aviso", "foram geradas " + str(flagCount) + " flags para a camada \"" + layer.name() + "\" !", level=QgsMessageBar.INFO, duration=4) else: self.iface.messageBar().pushMessage("Erro", u"a geração de flags falhou!", level=QgsMessageBar.CRITICAL, duration=4) print query.lastError().text()