def get_connected_segments_by_selection(self,
                                            segment,
                                            direction,
                                            index,
                                            dict_features,
                                            items=list(),
                                            count_d=0,
                                            vertex=None):
        geom = segment.geometry()

        if vertex is None:
            if direction == 1:
                vertex = QgsGeometry(geom.vertexAt(0))
            elif direction == -1:
                vertex = QgsGeometry(geom.vertexAt(len(geom.asPolyline()) - 1))

        bbox = vertex.boundingBox()
        candidates_ids = index.intersects(bbox)
        candidate_features = [
            dict_features[candidate_id] for candidate_id in candidates_ids
        ]

        touches = list()
        for candidate_feature in candidate_features:
            if candidate_feature.id() != segment.id():
                if candidate_feature.geometry().touches(vertex):
                    touches.append(candidate_feature)

        if len(touches) == 1:

            # select next vertex
            next_geom = touches[0].geometry()
            start_vertex = QgsGeometry(next_geom.vertexAt(0))
            end_vertex = QgsGeometry(
                next_geom.vertexAt(len(next_geom.asPolyline()) - 1))
            next_vertex = None

            if vertex.asWkt() == start_vertex.asWkt():
                next_vertex = end_vertex
            else:
                next_vertex = start_vertex

            if touches[0].id() not in items:
                items.append(touches[0].id())
                return self.get_connected_segments_by_selection(
                    touches[0], direction, index, dict_features, items,
                    count_d, next_vertex)
            else:
                if count_d < 1:
                    # in circular geometries it can happen that the condition of exit is not satisfied,
                    # reason for which the number of consecutive iterations is counted not to stay in an infinite cycle.
                    count_d += 1
                    return self.get_connected_segments_by_selection(
                        touches[0], direction, index, dict_features, items,
                        count_d, next_vertex)
                else:
                    return items
        else:
            return items
Exemple #2
0
 def findPlots(self):
     vl = self.layerComboBox.currentLayer()
     trans = QgsCoordinateTransform(vl.crs(),
                                    QgsCoordinateReferenceSystem(2180),
                                    QgsProject.instance())
     if not self.selectCheckBox.isChecked():
         geom = QgsGeometry().unaryUnion(
             [QgsGeometry(f.geometry()) for f in vl.getFeatures()])
         geom.transform(trans)
         if geom.isEmpty():
             self.iface.messageBar().pushMessage(
                 'Przeciecia LPIS',
                 u'Brak obiektów na warstwie',
                 level=Qgis.Warning)
             return False
     else:
         geom = QgsGeometry().unaryUnion(
             [QgsGeometry(f.geometry()) for f in vl.selectedFeatures()])
         geom.transform(trans)
         if geom.isEmpty():
             self.iface.messageBar().pushMessage(
                 'Przeciecia LPIS',
                 u'Brak zaznaczonych obiektów',
                 level=Qgis.Warning)
             return False
     params = {'wkt': geom.asWkt(), 'key': self.keyLineEdit.text().strip()}
     data = ''
     try:
         r = urllib.request.urlopen(
             'http://api.gis-support.pl/intersect?key=' + params['key'],
             json.dumps(params).encode('utf-8'))
         if r.getcode() == 403:
             self.iface.messageBar().pushMessage(
                 u'Przecięcia LPIS',
                 u'Nieprawidłowy klucz GIS Support',
                 level=Qgis.Critical)
             return False
         resp = json.loads(r.read().decode())
         data = resp['data']
     except:
         data = 'app connection problem'
     if not data:
         self.iface.messageBar().pushMessage(
             u'Przecięcia LPIS',
             u'Warstwa nie przecina żadnej działki',
             level=Qgis.Warning)
     elif data == 'db connection problem':
         self.iface.messageBar().pushMessage(u'Przecięcia LPIS',
                                             u'Problem połączenia z bazą',
                                             level=Qgis.Critical)
     elif data == 'app connection problem':
         self.iface.messageBar().pushMessage(
             u'Przecięcia LPIS',
             u'Problem połączenia z aplikacją',
             level=Qgis.Critical)
     else:
         self.createOutputLayer(resp)
         return True
     return False
    def set_snap_geometry(self, geom: QgsGeometry):
        '''
        snap lines to outline of given geometry

        Parameters
        ----------
        snap_geometry : QgsGeometry
            geometry to snap lines to
        '''
        if not geom:
            return
        if SHAPELY_LOADED:
            self.snap_geometry = wkt.loads(geom.asWkt()).boundary
        # alternative for MacOS
        else:
            self.snap_geometry = QgsCurvePolygon()
            self.snap_geometry.fromWkt(geom.asWkt())
    def getRings(self, geometry):
        rings = []

        # TODO: remove when the error is resolved
        # Error: The expected object type is a QgsCurvePolygon but it receives a QgsPoint, however the WKT of the
        #        QgsPoint corresponds to either a QgsPolygon or QgsMultiPolygon (yeap, it must be a bug in QGIS)
        if type(geometry) == QgsPoint or type(geometry) == QgsLineString:
            geom = QgsGeometry().fromWkt(geometry.asWkt())
            curve = None
            if geom.isMultipart():
                curve = QgsMultiPolygon()
                curve.fromWkt(geom.asWkt())
            else:
                curve = QgsPolygon()
                curve.fromWkt(geom.asWkt())

            geometry = curve.toCurveType()

        if isinstance(geometry, QgsGeometryCollection):
            # collection
            for i in range(geometry.numGeometries()):
                if QgsWkbTypes.geometryType(geometry.geometryN(
                        i).wkbType()) == QgsWkbTypes.PolygonGeometry:
                    rings.extend(self.getRings(geometry.geometryN(i)))
        else:
            # Converts geometry to curve, because exteriorRing is a method from curve polygons
            if isinstance(geometry, QgsPolygon):
                geom = geometry.toCurveType()
                geometry = geom

            # not collection
            rings.append(geometry.exteriorRing().clone())
            for i in range(geometry.numInteriorRings()):
                rings.append(geometry.interiorRing(i).clone())

        return rings
Exemple #5
0
    def set_user_extent(self, extent, crs):
        """Setter for the user requested extent.

        This function will redraw the rubberband if needed.

        :param extent: The user extent.
        :type extent: QgsGeometry

        :param crs: The CRS of the extent.
        :type crs: QgsCoordinateReferenceSystem
        """
        extent = QgsGeometry(extent)
        transform = QgsCoordinateTransform(crs, self.crs,
                                           QgsProject.instance())
        extent.transform(transform)
        self._user_extent = extent
        set_setting('user_extent', extent.asWkt())
        set_setting('user_extent_crs', crs.authid())
        if self._show_rubber_bands:
            self.display_user_extent()
Exemple #6
0
    def set_user_extent(self, extent, crs):
        """Setter for the user requested extent.

        This function will redraw the rubberband if needed.

        :param extent: The user extent.
        :type extent: QgsGeometry

        :param crs: The CRS of the extent.
        :type crs: QgsCoordinateReferenceSystem
        """
        extent = QgsGeometry(extent)
        transform = QgsCoordinateTransform(
            crs, self.crs, QgsProject.instance())
        extent.transform(transform)
        self._user_extent = extent
        set_setting('user_extent', extent.asWkt())
        set_setting('user_extent_crs', crs.authid())
        if self._show_rubber_bands:
            self.display_user_extent()
Exemple #7
0
    def onGeometryChanged(self, currRestriction):
        # Added by TH to deal with RestrictionsInProposals
        # When a geometry is changed; we need to check whether or not the feature is part of the current proposal
        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged. fid: " + str(currRestriction.id()) + " GeometryID: " + str(currRestriction.attribute("GeometryID")), tag="TOMs panel")

        # disconnect signal for geometryChanged
        #self.origLayer.geometryChanged.disconnect(self.on_cached_geometry_changed)
        #self.proposalsManager.TOMsToolChanged.disconnect()

        #self.currLayer = self.iface.activeLayer()
        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged. Layer: " + str(self.origLayer.name()), tag="TOMs panel")

        #currLayer.geometryChanged.disconnect(self.onGeometryChanged)
        #QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged. geometryChange signal disconnected.", tag="TOMs panel")

        idxRestrictionID = self.origLayer.fields().indexFromName("RestrictionID")
        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged. currProposal: " + str(self.proposalsManager.currentProposal()), tag="TOMs panel")

        # Now obtain the changed feature (not sure which geometry)

        #currFeature = self.THgetFeature(fid, currLayer)
        #self.origFeature.printFeature()

        #currFeature = currRestriction
        newGeometry = QgsGeometry(self.feature_band.asGeometry())

        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - newGeom incoming: " + newGeometry.asWkt(),
                                 tag="TOMs panel")

        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged. currRestrictionID: " + str(currRestriction[idxRestrictionID]), tag="TOMs panel")

        if not self.restrictionInProposal(currRestriction[idxRestrictionID], self.getRestrictionLayerTableID(self.origLayer), self.proposalsManager.currentProposal()):
            QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - adding details to RestrictionsInProposal", tag="TOMs panel")
            #  This one is not in the current Proposal, so now we need to:
            #  - generate a new ID and assign it to the feature for which the geometry has changed
            #  - switch the geometries arround so that the original feature has the original geometry and the new feature has the new geometry
            #  - add the details to RestrictionsInProposal

            originalfeature = self.origFeature.getFeature()

            newFeature = QgsFeature(self.origLayer.fields())

            newFeature.setAttributes(currRestriction.attributes())
            newFeature.setGeometry(newGeometry)
            newRestrictionID = str(uuid.uuid4())

            newFeature[idxRestrictionID] = newRestrictionID

            idxOpenDate = self.origLayer.fields().indexFromName("OpenDate")
            idxGeometryID = self.origLayer.fields().indexFromName("GeometryID")

            newFeature[idxOpenDate] = None
            newFeature[idxGeometryID] = None

            #currLayer.addFeature(newFeature)
            self.origLayer.addFeatures([newFeature])

            QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - attributes: " + str(newFeature.attributes()), tag="TOMs panel")

            QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - newGeom: " + newFeature.geometry().asWkt(), tag="TOMs panel")

            originalGeomBuffer = QgsGeometry(originalfeature.geometry())
            QgsMessageLog.logMessage(
                "In TOMsNodeTool:onGeometryChanged - originalGeom: " + originalGeomBuffer.asWkt(),
                tag="TOMs panel")
            self.origLayer.changeGeometry(currRestriction.id(), originalGeomBuffer)

            QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - geometries switched.", tag="TOMs panel")

            self.addRestrictionToProposal(currRestriction[idxRestrictionID], self.getRestrictionLayerTableID(self.origLayer), self.proposalsManager.currentProposal(), RestrictionAction.OPEN) # close the original feature
            QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - feature closed.", tag="TOMs panel")

            self.addRestrictionToProposal(newRestrictionID, self.getRestrictionLayerTableID(self.origLayer), self.proposalsManager.currentProposal(), RestrictionAction.OPEN) # open the new one
            QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - feature opened.", tag="TOMs panel")

            #self.proposalsManager.updateMapCanvas()

        else:

            # assign the changed geometry to the current feature
            #currRestriction.setGeometry(newGeometry)
            pass


        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - newGeom (2): " + currRestriction.geometry().asWkt(),
                                 tag="TOMs panel")

        # Trying to unset map tool to force updates ...
        #self.iface.mapCanvas().unsetMapTool(self.iface.mapCanvas().mapTool())
        #currMapTool = self.iface.mapCanvas().mapTool()
        #currAction = currMapTool.action()

        #currMapToolAction = self.iface.mapCanvas().mapTool().action().setChecked(False)

        # uncheck current tool


        self.restrictionTransaction.commitTransactionGroup(self.origLayer)
        #self.restrictionTransaction.deleteTransactionGroup()

        self.origLayer.deselect(self.origFeature.getFeature().id())

        self.shutDownNodeTool()

        # **** New
        """"#currRestrictionRestrictionID = currFeature[idxRestrictionID]

        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged. currRestrictionID: " + str(self.currFeature[idxRestrictionID]), tag="TOMs panel")

        self.currFeature.setGeometry(newGeometry)

        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - attributes: " + str(self.currFeature.attributes()),
                                 tag="TOMs panel")

        QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - newGeom: " + self.currFeature.geometry().asWkt(),
                                 tag="TOMs panel")

        # Trying to unset map tool to force updates ...
        #self.iface.mapCanvas().unsetMapTool(self.iface.mapCanvas().mapTool())

        # change active layer
        status = self.iface.setActiveLayer(None)

        self.restrictionTransaction.commitTransactionGroup(self.currLayer)
        #self.restrictionTransaction.deleteTransactionGroup()

        #QTimer.singleShot(0, functools.partial(RestrictionTypeUtils.commitRestrictionChanges, origLayer))

        #QgsMessageLog.logMessage("In TOMsNodeTool:onGeometryChanged - geometry saved.", tag="TOMs panel")"""

        return
Exemple #8
0
    def calcIntersects(self, task):
        try:
            QgsMessageLog.logMessage(
                'Started task {}'.format(task.description()),
                self.MESSAGE_CATEGORY, Qgis.Info)

            self.setFilterLayer(self.inters_layer)

            filters_dict = {}
            if self.settings_layer is not None:
                for fieldname in self.settings_layer.get("filters_fields"):
                    filters_dict[fieldname] = CommonTools.getFilterValues(
                        fieldname, self.filter_layout)

            current_feature_idx = self.map_clicked_dlg.tableClickedWays.currentRow(
            )
            current_feature_id = int(
                self.map_clicked_dlg.tableClickedWays.item(
                    current_feature_idx, 0).text())
            current_feature = self.current_layer.getFeature(current_feature_id)
            current_feature_geom = current_feature.geometry()
            current_feature_length = round(current_feature_geom.length(), 2)
            percent_inters = int(filters_dict.get("_percent", "0"))
            buffer_size = float(filters_dict.get("_buffer_size", "0.01"))
            layer_by_percent = (
                filters_dict.get("_by_addition_layer")
            )  # слой, по пересечению объектов которых будет высчитываться процент пересечения
            current_feature_buf = current_feature_geom.buffer(buffer_size, 5)
            il_objects_result_dict = {
            }  # конечный результат отобранных пересекаемых объектов
            il_fields_aliases_dict = self.inters_layer.attributeAliases(
            )  # алиасы полей слоя
            additional_layers = self.getAdditionalLayerData(
            )  # дополнительные пересекаемые слои (для вычисления количества общих пересечений)

            if layer_by_percent:  # если сравнение по общим объектам дополнительного слоя
                self.dockWidget.labelResult.setText(
                    f"Слой <{self.inters_layer.name()}>.\n"
                    f"Результат отбора по общим объектам в слое <{layer_by_percent.name()}>.\n"
                    f"(Id объекта: {current_feature_id}. Длина объекта: {current_feature_length}) м."
                )
            else:  # если сравнение по длине
                self.dockWidget.labelResult.setText(
                    f"Слой <{self.inters_layer.name()}>.\n"
                    f"Результат отбора по длине пересечений.\n"
                    f"(Id объекта: {current_feature_id}. Длина объекта: {current_feature_length} м.)"
                )

            # генерация фильтра для получения всех объектов слоя
            filter_expression = self.generateFilterExpression(filters_dict)
            if filter_expression:
                expr = QgsExpression(filter_expression)
                request = QgsFeatureRequest(expr)
                inters_layer_features = list(
                    self.inters_layer.getFeatures(request))
            else:
                inters_layer_features = list(self.inters_layer.getFeatures())
            fcnt = (len((inters_layer_features))
                    )  # общее число (отфильтрованных) объектов в слое

            for idx, intfeat in enumerate(inters_layer_features):
                if intfeat.id(
                ) == current_feature_id and self.current_layer == self.inters_layer:  #отсекаем сравниваемую линию
                    continue
                if intfeat.geometry().intersects(current_feature_buf):
                    task.setProgress(idx / float(fcnt) * 100)
                    if task.isCanceled():
                        self.stopped(task)
                        return

                    intfeat_buffer = intfeat.geometry().buffer(
                        buffer_size, 5
                    )  # буфер пересекающихся линий, для отображения пересечений
                    intersection_buffer = QgsGeometry(
                        intfeat_buffer).intersection(
                            current_feature_buf)  # для отображения пересечений
                    intersection_line = QgsGeometry(intfeat.geometry(
                    )).intersection(
                        current_feature_buf
                    )  # части текущей линии, которые попали в буфер сравниваемого объекта

                    intfeat_length = intfeat.geometry().length()
                    intersection_line_length = intersection_line.length()
                    attrs_add_layers_for_intfeat = None  # Количество пересекаемых объектов из дополнительных слоев
                    attrs_add_layers_for_intersection = None  # Количество общих пересекаемых объектов из дополнительных слоев

                    if layer_by_percent:  # если сравнивать по общим пересекаемыым объектам, а не по длине
                        attrs_add_layers_for_intfeat = self.getAdditionalLayersAttrs(
                            additional_layers, intfeat.geometry(),
                            'Объекты в ')
                        attrs_add_layers_for_intersection = self.getAdditionalLayersAttrs(
                            additional_layers, intersection_line, 'Общее в ')
                        cnt_intfeat_by_layer = attrs_add_layers_for_intfeat[
                            'Объекты в ' + layer_by_percent.name()]
                        cnt_intersection_by_layer = attrs_add_layers_for_intersection[
                            'Общее в ' + layer_by_percent.name()]

                        if cnt_intfeat_by_layer == 0:
                            result_percent_inters = 0
                        else:
                            result_percent_inters = (
                                cnt_intersection_by_layer /
                                cnt_intfeat_by_layer) * 100
                    else:  # если сравнивать по длине
                        # процент - отношение длины пересечения к длине пересекаемого пути
                        result_percent_inters = (intersection_line_length /
                                                 intfeat_length) * 100

                    if result_percent_inters >= percent_inters:
                        attrs_sys = {
                            "feature_id": intfeat.id(),
                            "WKT_inters_feature": intfeat.geometry().asWkt(),
                            "WKT_intersection_line": intersection_line.asWkt()
                        }
                        attrs_calculated = {
                            "Длина объекта": round(intfeat_length, 2),
                            "Длина пересечения":
                            round(intersection_line_length, 2),
                            "Процент пересечения":
                            round(result_percent_inters, 2)
                        }
                        attrs_feature_layer = self.getDictFeaturesAttributes(
                            intfeat, il_fields_aliases_dict)

                        if not attrs_add_layers_for_intfeat:
                            attrs_add_layers_for_intfeat = self.getAdditionalLayersAttrs(
                                additional_layers, intfeat.geometry(),
                                'Объекты в ')
                        if not attrs_add_layers_for_intersection:
                            attrs_add_layers_for_intersection = self.getAdditionalLayersAttrs(
                                additional_layers, intersection_line,
                                'Общее в ')
                        feat_attrs = {}
                        feat_attrs = {
                            **attrs_sys,
                            **attrs_feature_layer,
                            **attrs_calculated,
                            **attrs_add_layers_for_intfeat,
                            **attrs_add_layers_for_intersection
                        }  # объединение высчитываемых атрибутов и атрибутов слоя (объекта)

                        il_objects_result_dict[intfeat.id()] = feat_attrs
            il_objects_result_dict = OrderedDict(
                sorted(il_objects_result_dict.items(),
                       key=lambda kv: kv[1]["Процент пересечения"],
                       reverse=True))
            self.setFilterLayer(self.inters_layer,
                                list(il_objects_result_dict.keys()))
            return il_objects_result_dict
        except Exception as e:
            exc_type, exc_obj, exc_tb = os.system.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)
            message = f"{exc_tb.tb_lineno}, {str(e)},  {exc_type}, {fname}"
            QgsMessageLog.logMessage(message, self.MESSAGE_CATEGORY, Qgis.Info)