예제 #1
0
def create_layer(vector):
    """Create empty layer.

    The CRS and Geometry Type of new layer are the same as of vector layer.
    Attributes of the layer are copied from vector.

    :param vector:  Vector layer
    :type vector:   QgsVectorLayer

    :returns: Empty vector layer (stored in memory)
    :rtype: QgsVectorLayer
    """
    crs = vector.crs().toWkt()
    if vector.geometryType() == 0:
        msg = "Points cant' be split"
        raise WrongDataTypeException(msg)
    elif vector.geometryType() == 1:
        uri = 'LineString?crs=' + crs
    elif vector.geometryType() == 2:
        uri = 'Polygon?crs=' + crs
    else:
        msg = "Received unexpected type of layer geometry: %s" \
              % (vector.geometryType(),)
        raise WrongDataTypeException(msg)

    result_layer = QgsVectorLayer(uri, 'intersected', 'memory')
    result_provider = result_layer.dataProvider()
    result_layer.startEditing()

    # Copy fields from vector
    vector_provider = vector.dataProvider()
    fields = vector_provider.fields()
    result_provider.addAttributes(fields.toList())
    result_layer.commitChanges()

    return result_layer
예제 #2
0
def split_by_polygon(vector,
                     polygon,
                     request=QgsFeatureRequest(),
                     mark_value=None):
    """Split objects from vector layer by polygon.

    If request is specified, filter the objects before splitting.

    If part of vector object lies in the polygon, mark it by mark_value (
    optional).

    :param vector:  Vector layer
    :type vector:   QgsVectorLayer

    :param polygon: Splitting polygon
    :type polygon:  QgsGeometry

    :param request: Filter for vector objects
    :type request:  QgsFeatureRequest

    :param mark_value:  Field value to mark the objects.
    :type mark_value:   (field_name, field_value).or None

    :returns: Vector layer with split geometry
    :rtype: QgsVectorLayer
    """
    def _set_feature(geometry, feature_attributes):
        """
        Helper to create and set up feature
        """
        included_feature = QgsFeature()
        included_feature.setGeometry(geometry)
        included_feature.setAttributes(feature_attributes)
        return included_feature

    def _update_attr_list(attributes, index, value, add_attribute=False):
        """
        Helper for update list of attributes.
        """
        new_attributes = attributes[:]
        if add_attribute:
            new_attributes.append(value)
        else:
            new_attributes[index] = value
        return new_attributes

    # Create layer to store the splitted objects
    result_layer = create_layer(vector)
    result_provider = result_layer.dataProvider()
    fields = result_provider.fields()

    # If target_field does not exist, add it:
    new_field_added = False
    if mark_value is not None:
        target_field = mark_value[0]
        if fields.indexFromName(target_field) == -1:
            result_layer.startEditing()
            result_provider.addAttributes(
                [QgsField(target_field, QVariant.Int)])
            new_field_added = True
            result_layer.commitChanges()
    target_value = None

    if mark_value is not None:
        target_field = mark_value[0]
        target_value = mark_value[1]
        target_field_index = result_provider.fieldNameIndex(target_field)
        if target_field_index == -1:
            raise WrongDataTypeException('Field not found for %s' %
                                         target_field)

    # Start split procedure
    result_layer.startEditing()
    for initial_feature in vector.getFeatures(request):
        initial_geom = initial_feature.geometry()
        attributes = initial_feature.attributes()
        geometry_type = initial_geom.type()
        if polygon.intersects(initial_geom):
            # Find parts of initial_geom, intersecting
            # with the polygon, then mark them if needed
            intersection = QgsGeometry(
                initial_geom.intersection(polygon)).asGeometryCollection()

            for g in intersection:
                if g.type() == geometry_type:
                    if mark_value is not None:
                        new_attributes = _update_attr_list(
                            attributes,
                            target_field_index,
                            target_value,
                            add_attribute=new_field_added)
                    else:
                        new_attributes = attributes
                    feature = _set_feature(g, new_attributes)
                    _ = result_layer.dataProvider().addFeatures([feature])

            # Find parts of the initial_geom that do not lie in the polygon
            diff_geom = QgsGeometry(
                initial_geom.symDifference(polygon)).asGeometryCollection()
            for g in diff_geom:
                if g.type() == geometry_type:
                    if mark_value is not None:
                        new_attributes = _update_attr_list(
                            attributes,
                            target_field_index,
                            0,
                            add_attribute=new_field_added)
                    else:
                        new_attributes = attributes
                    feature = _set_feature(g, new_attributes)
                    _ = result_layer.dataProvider().addFeatures([feature])
        else:
            if mark_value is not None:
                new_attributes = _update_attr_list(
                    attributes,
                    target_field_index,
                    0,
                    add_attribute=new_field_added)
            else:
                new_attributes = attributes
            feature = _set_feature(initial_geom, new_attributes)
            _ = result_layer.dataProvider().addFeatures([feature])
    result_layer.commitChanges()
    result_layer.updateExtents()

    return result_layer
예제 #3
0
def split_by_polygon2(
        vector,
        polygon_layer,
        request=QgsFeatureRequest(),
        use_contains_operation=False,
        mark_value=None):
    """Split objects from vector layer by polygon.

    If request is specified, filter the objects before splitting.

    If part of vector object lies in the polygon, mark it by mark_value (
    optional).

    :param vector:  Vector layer
    :type vector:   QgsVectorLayer

    :param polygon_layer: Splitting polygons layer
    :type polygon_layer:  QgsVectorLayer

    :param request: Filter for vector objects
    :type request:  QgsFeatureRequest

    :param use_contains_operation: Whether to use geometrical containment.
    :type use_contains_operation: bool

    :param mark_value:  Field value to mark the objects.
    :type mark_value:   (field_name, field_value).or None

    :returns: Vector layer with split geometry
    :rtype: QgsVectorLayer
    """

    def _set_feature(geometry, attributes):
        """
        Helper to create and set up feature
        """
        included_feature = QgsFeature()
        included_feature.setGeometry(geometry)
        included_feature.setAttributes(attributes)
        return included_feature

    def _update_attr_list(attributes, index, value, add_attribute=False):
        """
        Helper for update list of attributes.
        """
        new_attributes = attributes[:]
        if add_attribute:
            new_attributes.append(value)
        else:
            new_attributes[index] = value
        return new_attributes

    # Create layer to store the split objects
    result_layer = create_layer(vector)
    result_provider = result_layer.dataProvider()
    fields = result_provider.fields()

    # If target_field does not exist, add it:
    new_field_added = False
    if mark_value is not None:
        target_field = mark_value[0]
        if fields.indexFromName(target_field) == -1:
            result_layer.startEditing()
            result_provider.addAttributes(
                [QgsField(target_field, QVariant.Int)])
            new_field_added = True
            result_layer.commitChanges()
    target_value = None

    if mark_value is not None:
        target_field = mark_value[0]
        target_value = mark_value[1]
        target_field_index = result_provider.fieldNameIndex(target_field)
        if target_field_index == -1:
            raise WrongDataTypeException(
                'Field not found for %s' % target_field)

    # Start split procedure

    line_geoms = []
    line_attributes = []

    for initial_feature in vector.getFeatures(request):
        initial_geom = initial_feature.geometry()
        line_geoms.append(QgsGeometry(initial_geom))
        attributes = initial_feature.attributes()
        line_attributes.append(attributes)
        geometry_type = initial_geom.type()

    poly_geoms = []
    for polygon_feature in polygon_layer.getFeatures(request):
        # Using simplify 1 should remove any pseudonodes on the polygon
        # and speed up polygon operations. TS
        # polygon = polygon_feature.geometry().simplify(1)
        # disabled for now (see #1300 Y.A.)
        polygon = polygon_feature.geometry()
        poly_geoms.append(QgsGeometry(polygon))

    result_layer.startEditing()

    for polygon in poly_geoms:
        for initial_geom, attributes in \
                itertools.izip(line_geoms, line_attributes):

            if use_contains_operation:
                poly_contains = polygon.contains(initial_geom)
            else:
                poly_contains = False

            poly_intersect = False
            if not poly_contains:
                poly_intersect = polygon.intersects(initial_geom)

            if poly_contains or poly_intersect:
                # Find parts of initial_geom, intersecting
                # with the polygon, then mark them if needed
                if poly_contains:
                    g = initial_geom
                    if mark_value is not None:
                        new_attributes = _update_attr_list(
                            attributes,
                            target_field_index,
                            target_value,
                            add_attribute=new_field_added
                        )
                    else:
                        new_attributes = attributes
                    feature = _set_feature(g, new_attributes)
                    _ = result_layer.dataProvider().addFeatures([feature])

                else:
                    intersection = QgsGeometry(
                        initial_geom.intersection(polygon)
                    ).asGeometryCollection()

                    for g in intersection:
                        if g.type() == geometry_type:
                            if mark_value is not None:
                                new_attributes = _update_attr_list(
                                    attributes,
                                    target_field_index,
                                    target_value,
                                    add_attribute=new_field_added
                                )
                            else:
                                new_attributes = attributes
                            feature = _set_feature(g, new_attributes)
                            _ = result_layer.dataProvider().\
                                addFeatures([feature])

    result_layer.commitChanges()
    result_layer.updateExtents()
    return result_layer