Created
June 27, 2019 09:52
-
-
Save 3nids/3c9f7e9aeed45b4cee526f728b73c12c to your computer and use it in GitHub Desktop.
Action to resize rectangles in QGIS 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
layer = QgsProject.instance().mapLayer('[% @layer_id %]') | |
from math import sqrt | |
from PyQt5.QtWidgets import QDialog, QFormLayout, QLabel, QDoubleSpinBox, QComboBox, QDialogButtonBox | |
class RectDialog(QDialog): | |
def __init__(self, width, length): | |
QDialog.__init__(self) | |
self.layout = QFormLayout(self) | |
self.wLabel = QLabel("largeur") | |
self.lLabel = QLabel("longueur") | |
self.wSpinBox = QDoubleSpinBox(self) | |
self.lSpinBox = QDoubleSpinBox(self) | |
self.wSpinBox.setMinimum(-1000) | |
self.lSpinBox.setMinimum(-1000) | |
self.wSpinBox.setMaximum(1000) | |
self.lSpinBox.setMaximum(1000) | |
self.wSpinBox.setValue(width) | |
self.lSpinBox.setValue(length) | |
self.rCombo = QComboBox(self) | |
self.rCombo.addItem("absolu") | |
self.rCombo.addItem("relatif") | |
self.buttonBox = QDialogButtonBox(self) | |
self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) | |
self.layout.setWidget(0, QFormLayout.LabelRole, self.wLabel) | |
self.layout.setWidget(0, QFormLayout.FieldRole, self.wSpinBox) | |
self.layout.setWidget(1, QFormLayout.LabelRole, self.lLabel) | |
self.layout.setWidget(1, QFormLayout.FieldRole, self.lSpinBox) | |
self.layout.setWidget(2, QFormLayout.FieldRole, self.rCombo) | |
self.layout.setWidget(3, QFormLayout.SpanningRole, self.buttonBox) | |
self.initialWidth = width | |
self.initialLength = length | |
self.buttonBox.accepted.connect(self.accept) | |
self.buttonBox.rejected.connect(self.reject) | |
self.rCombo.currentIndexChanged.connect(self.relativeChanged) | |
def relativeChanged(self, idx): | |
if idx == 0: # absolu | |
self.lSpinBox.setValue( self.initialLength + self.lSpinBox.value() ) | |
self.wSpinBox.setValue( self.initialWidth + self.wSpinBox.value() ) | |
else: # relatif | |
self.lSpinBox.setValue( -self.initialLength + self.lSpinBox.value() ) | |
self.wSpinBox.setValue( -self.initialWidth + self.wSpinBox.value() ) | |
def width(self): | |
if self.rCombo.currentIndex() == 0: | |
return self.wSpinBox.value() | |
else: | |
return self.initialWidth + self.wSpinBox.value() | |
def length(self): | |
if self.rCombo.currentIndex() == 0: | |
return self.lSpinBox.value() | |
else: | |
return self.initialLength + self.lSpinBox.value() | |
# code | |
# code | |
r = QgsFeatureRequest([% $id %]) | |
f = QgsFeature() | |
if layer.getFeatures(r).nextFeature(f): | |
geom = f.geometry().asPolygon() | |
if len(geom) != 1 and len(geom[0]) != 4: | |
qgis.utils.iface.messageBar().pushMessage("Geometry is not a 4 points polygon.", Qgis.Warning, 3) | |
else: | |
geom = geom[0] | |
dist = [] | |
geom.append(geom[3]) # re-append first point to calculate distance | |
for p in range(0,4): | |
dist.append( sqrt(geom[p].sqrDist(geom[p+1])) ) | |
isRectangle = sqrt(geom[0].sqrDist(geom[2])) -sqrt(geom[1].sqrDist(geom[3])) < 0.000001 # check diagonals | |
if not isRectangle: | |
print("dist: ", dist) | |
print("diag: ", geom[0].sqrDist(geom[2]), geom[1].sqrDist(geom[3])) | |
qgis.utils.iface.messageBar().pushMessage("Geometry is not a rectangle.", Qgis.Warning, 3) | |
else: | |
if dist[0] < dist[1]: | |
w = dist[0] | |
l = dist[1] | |
else: | |
w = dist[1] | |
l = dist[0] | |
dlg = RectDialog(w, l) | |
if dlg.exec_(): | |
if dist[0] < dist[1]: | |
d0 = dlg.width()-w | |
d1 = dlg.length()-l | |
else: | |
d1 = dlg.width()-w | |
d0 = dlg.length()-l | |
v0 = [geom[1].x()-geom[0].x(), geom[1].y()-geom[0].y()] | |
v1 = [geom[2].x()-geom[1].x(), geom[2].y()-geom[1].y()] | |
v0 = [coord / (sqrt(v0[0]*v0[0]+v0[1]*v0[1])) for coord in v0] | |
v1 = [coord / (sqrt(v1[0]*v1[0]+v1[1]*v1[1])) for coord in v1] | |
p0 = QgsPointXY( geom[0].x() -d0/2 * v0[0] -d1/2 * v1[0], geom[0].y() -d0/2 * v0[1] -d1/2 * v1[1] ) | |
p1 = QgsPointXY( geom[1].x() +d0/2 * v0[0] -d1/2 * v1[0], geom[1].y() +d0/2 * v0[1] -d1/2 * v1[1] ) | |
p2 = QgsPointXY( geom[2].x() +d0/2 * v0[0] +d1/2 * v1[0], geom[2].y() +d0/2 * v0[1] +d1/2 * v1[1] ) | |
p3 = QgsPointXY( geom[3].x() -d0/2 * v0[0] +d1/2 * v1[0], geom[3].y() -d0/2 * v0[1] +d1/2 * v1[1] ) | |
geom = [[p0,p1,p2,p3]] | |
geom = QgsGeometry.fromPolygonXY(geom) | |
if layer.changeGeometry([% $id %], geom): | |
qgis.utils.iface.messageBar().pushMessage("Geométry edited", Qgis.Info, 1) | |
qgis.utils.iface.mapCanvas().refresh() | |
else: | |
qgis.utils.iface.messageBar().pushMessage("Geometry could not be edited. Turn on editing.", Qgis.Warning, 3) | |
else: | |
qgis.utils.iface.messageBar().pushMessage("Could not fetch feature.", Qgis.Critical, 3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment