Esempio n. 1
0
    def average_linestrings(line1: QgsLineString,
                            line2: QgsLineString,
                            weight: float = 1) -> QgsLineString:
        """
        Averages two linestring geometries
        """
        g1 = line1.clone()

        # project points from g2 onto g1
        for n in range(line2.numPoints()):
            vertex = line2.pointN(n)
            _, pt, after, _ = g1.closestSegment(vertex)
            g1.insertVertex(QgsVertexId(0, 0, after.vertex), pt)

        # iterate through vertices in g1
        out = []
        for n in range(g1.numPoints()):
            vertex = g1.pointN(n)
            _, pt, after, _ = line2.closestSegment(vertex)

            # average pts
            x = (vertex.x() * weight + pt.x()) / (weight + 1)
            y = (vertex.y() * weight + pt.y()) / (weight + 1)
            out.append(QgsPoint(x, y))

        return QgsLineString(out)
    def validate_constraints(self, sim_geom, first, last):
        """Validate the spatial relationship in order maintain topological structure

        Three distinct spatial relation are tested in order to assure that each bend reduce will continue to maintain
        the topological structure in a feature between the features:
         - Simplicity: Adequate validation is done to make sure that the bend reduction will not cause the feature
                       to cross  itself.
         - Intersection : Adequate validation is done to make sure that a line from other features will not intersect
                          the bend being reduced
         - Sidedness: Adequate validation is done to make sure that a line is not completely contained in the bend.
                      This situation can happen when a ring in a polygon complete;y lie in a bend ans after bend
                      reduction, the the ring falls outside the polygon which make it invalid.

        Note if the topological structure is wrong before the bend correction no correction will be done on these
        errors.

        :param: sim_geom: Geometry used to validate constraints
        :param: first: Index of the start vertice of the subline
        :param: last: Index of the last vertice of the subline
        :return: Flag indicating if the spatial constraints are valid for this subline simplification
        :rtype: Bool
        """

        constraints_valid = True

        qgs_points = [sim_geom.qgs_geom.vertexAt(i) for i in range(first, last+1)]
        qgs_geom_new_subline = QgsGeometry(QgsLineString(qgs_points[0], qgs_points[-1]))
        qgs_geom_old_subline = QgsGeometry(QgsLineString(qgs_points))
        qgs_geoms_with_itself, qgs_geoms_with_others = \
            self.rb_collection.get_segment_intersect(sim_geom.id, qgs_geom_old_subline.boundingBox(),
                                                     qgs_geom_old_subline)

        # First: check if the bend reduce line string is an OGC simple line
        constraints_valid = GeoSimUtil.validate_simplicity(qgs_geoms_with_itself, qgs_geom_new_subline)

        # Second: check that the new line does not intersect with any other line or points
        if constraints_valid and len(qgs_geoms_with_others) >= 1:
            constraints_valid = GeoSimUtil.validate_intersection(qgs_geoms_with_others, qgs_geom_new_subline)

        # Third: check that inside the subline to simplify there is no feature completely inside it.  This would cause a
        # sidedness or relative position error
        if constraints_valid and len(qgs_geoms_with_others) >= 1:
            qgs_ls_old_subline = QgsLineString(qgs_points)
            qgs_ls_old_subline.addVertex(qgs_points[0])  # Close the line with the start point
            qgs_geom_old_subline = QgsGeometry(qgs_ls_old_subline.clone())

            # Next two lines used to transform a self intersecting line into a valid MultiPolygon
            qgs_geom_unary = QgsGeometry.unaryUnion([qgs_geom_old_subline])
            qgs_geom_polygonize = QgsGeometry.polygonize([qgs_geom_unary])

            if qgs_geom_polygonize.isSimple():
                constraints_valid = GeoSimUtil.validate_sidedness(qgs_geoms_with_others, qgs_geom_polygonize)
            else:
                print("Polygonize not valid")
                constraints_valid = False

        return constraints_valid
 def test_case32(self):
     title = "Test 32: Normalization of in vector layer"
     print (title)
     vl = QgsVectorLayer("LineString", "temporary_polygon", "memory")
     pr = vl.dataProvider()
     fet = QgsFeature()
     fet.setId(1)
     qgs_line = QgsLineString((QgsPoint(0,0,0),QgsPoint(10,10,0),QgsPoint(20,20,0)))
     qgs_geom = QgsGeometry(qgs_line.clone())
     fet.setGeometry(qgs_geom)
     pr.addFeatures([fet])
     vl.updateExtents()
     feedback = QgsProcessingFeedback()
     qgs_features, geom_type = ReduceBend.normalize_in_vector_layer(vl, feedback)
     val0 = len(qgs_features) == 1
     qgs_geom = qgs_features[0].geometry()
     val1 = qgs_geom.wkbType() == QgsWkbTypes.LineString
     self.assertTrue(val0 and val1, title)