Next script works for me.
layer=iface.activeLayer()
myGrayRenderer = QgsSingleBandGrayRenderer(layer.dataProvider(),
1)
layer.setRenderer(myGrayRenderer)
renderer = layer.renderer()
provider = layer.dataProvider()
layer_extent = layer.extent()
uses_band = renderer.usesBands()
myType = renderer.dataType(uses_band[0])
stats = provider.bandStatistics(uses_band[0],
QgsRasterBandStats.All,
layer_extent,
0)
myEnhancement = QgsContrastEnhancement(myType)
contrast_enhancement = QgsContrastEnhancement.StretchToMinimumMaximum
myEnhancement.setContrastEnhancementAlgorithm(contrast_enhancement,True)
myEnhancement.setMinimumValue(stats.minimumValue)
myEnhancement.setMaximumValue(stats.maximumValue)
layer.renderer().setContrastEnhancement(myEnhancement)
layer.triggerRepaint()
I tested it for changing an object of QgsSingleBandPseudoColorRenderer class (in your case it would be a QgsPalettedRasterRenderer object) in a QgsSingleBandGrayRenderer class object.
Before running the script at the Python Console:
After running the script:
Editing Note:
I tested the script with the same raster and a paletted render type (see next image) and it worked too.
You can use closestSegmentWithContext
from QgsGeometry
. The argument is the cut nearest QgsPoint
and, it produces a tuple with the squared Cartesian distance from closest segment to polyline, the nearest point on the segment and, finally, the index of the vertex (at polyline) after the closest segment.
To illustrate the approach, I used next shapefiles for only cutting in two features the polyline layer.
PyQGIS 2 code is:
registry = QgsMapLayerRegistry.instance()
my_border = registry.mapLayersByName('my_border')
my_point = registry.mapLayersByName('my_point')
feats_my_border = [ feat for feat in my_border[0].getFeatures() ]
feats_my_point = [ feat for feat in my_point[0].getFeatures() ]
my_tupla = feats_my_border[0].geometry().closestSegmentWithContext(feats_my_point[0].geometry().asPoint())
my_line = [ feat.geometry().asPolyline() for feat in feats_my_border ]
first_segment = []
second_segment = [my_tupla[1]]
for line in my_line:
for i, point in enumerate(line):
if i < my_tupla[2]:
first_segment.append(point)
else:
second_segment.append(point)
first_segment.append(my_tupla[1])
epsg = my_border[0].crs().postgisSrid()
uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"
mem_layer = QgsVectorLayer(uri,
'split_line',
'memory')
prov = mem_layer.dataProvider()
feat = QgsFeature()
feat.setAttributes([0])
feat.setGeometry(QgsGeometry.fromPolyline(first_segment))
prov.addFeatures([feat])
feat.setAttributes([1])
feat.setGeometry(QgsGeometry.fromPolyline(second_segment))
prov.addFeatures([feat])
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
After running it, at the Python Console of QGIS, I got:
It can be observed the first selected feature at the created memory layer.
PyQGIS 3 code is:
registry = QgsProject.instance()
my_border = registry.mapLayersByName('my_border')
my_point = registry.mapLayersByName('my_point')
feats_my_border = [ feat for feat in my_border[0].getFeatures() ]
feats_my_point = [ feat for feat in my_point[0].getFeatures() ]
my_tupla = feats_my_border[0].geometry().closestSegmentWithContext(feats_my_point[0].geometry().asPoint())
my_line = [ feat.geometry().asMultiPolyline() for feat in feats_my_border ]
first_segment = []
second_segment = [my_tupla[1]]
for line in my_line[0]:
for i, point in enumerate(line):
if i < my_tupla[2]:
first_segment.append(point)
else:
second_segment.append(point)
first_segment.append(my_tupla[1])
epsg = my_border[0].crs().postgisSrid()
uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"
mem_layer = QgsVectorLayer(uri,
'split_line',
'memory')
prov = mem_layer.dataProvider()
feat = QgsFeature()
feat.setAttributes([0])
feat.setGeometry(QgsGeometry.fromPolylineXY(first_segment))
prov.addFeatures([feat])
feat.setAttributes([1])
feat.setGeometry(QgsGeometry.fromPolylineXY(second_segment))
prov.addFeatures([feat])
QgsProject.instance().addMapLayer(mem_layer)
Editing Note:
When there are more than one cut point, next code (PyQGIS 2) works well:
registry = QgsMapLayerRegistry.instance()
my_border = registry.mapLayersByName('my_border')
my_point = registry.mapLayersByName('my_point')
feats_my_border = [ feat for feat in my_border[0].getFeatures() ]
feats_my_points = [ feat for feat in my_point[0].getFeatures() ]
points = [ feat.geometry().asPoint() for feat in feats_my_points ]
my_tuplas = []
for point in points:
tupla = feats_my_border[0].geometry().closestSegmentWithContext(point)
my_tuplas.append(tupla)
my_line = [ feat.geometry().asPolyline() for feat in feats_my_border ]
new_line = []
k = 0
try:
for i, line in enumerate(my_line):
for j, point in enumerate(line):
new_line.append(point)
if j == my_tuplas[k][2] - 1:
new_line.append(my_tuplas[k][1])
k += 1
except IndexError:
pass
k = 0
lines = [ [] for i in range(len(points) + 1) ]
epsg = my_border[0].crs().postgisSrid()
uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"
mem_layer = QgsVectorLayer(uri,
'split_line',
'memory')
prov = mem_layer.dataProvider()
try:
for point in new_line:
lines[k].append(point)
if point == my_tuplas[k][1]:
k += 1
lines[k].append(point)
except IndexError:
pass
for i, line in enumerate(lines):
feat = QgsFeature()
feat.setAttributes([i])
feat.setGeometry(QgsGeometry.fromPolyline(line))
prov.addFeatures([feat])
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
After running above code at the Python Console of QGIS, I got:
At the image, it was selected only the second feature of polyline memory layer.
With QGIS 3 following code also works:
registry = QgsProject.instance()
my_border = registry.mapLayersByName('my_border')
my_point = registry.mapLayersByName('my_points')
feats_my_border = [ feat for feat in my_border[0].getFeatures() ]
feats_my_points = [ feat for feat in my_point[0].getFeatures() ]
points = [ feat.geometry().asPoint() for feat in feats_my_points ]
my_tuplas = []
for point in points:
tupla = feats_my_border[0].geometry().closestSegmentWithContext(point)
my_tuplas.append(tupla)
my_line = [ feat.geometry().asMultiPolyline()[0] for feat in feats_my_border ]
new_line = []
k = 0
try:
for i, line in enumerate(my_line):
for j, point in enumerate(line):
new_line.append(point)
if j == my_tuplas[k][2] - 1:
new_line.append(my_tuplas[k][1])
k += 1
except IndexError:
pass
k = 0
lines = [ [] for i in range(len(points) + 1) ]
epsg = my_border[0].crs().postgisSrid()
uri = "LineString?crs=epsg:" + str(epsg) + "&field=id:integer""&index=yes"
mem_layer = QgsVectorLayer(uri,
'split_line',
'memory')
prov = mem_layer.dataProvider()
try:
for point in new_line:
lines[k].append(point)
if point == my_tuplas[k][1]:
k += 1
lines[k].append(point)
except IndexError:
pass
for i, line in enumerate(lines):
feat = QgsFeature()
feat.setAttributes([i])
feat.setGeometry(QgsGeometry.fromPolylineXY(line))
prov.addFeatures([feat])
QgsProject.instance().addMapLayer(mem_layer)
Best Answer
You need to iterate over the vector layer after your signal.