Skip to content

Instantly share code, notes, and snippets.

@3nids
Created June 27, 2019 09:52
Show Gist options
  • Save 3nids/3c9f7e9aeed45b4cee526f728b73c12c to your computer and use it in GitHub Desktop.
Save 3nids/3c9f7e9aeed45b4cee526f728b73c12c to your computer and use it in GitHub Desktop.
Action to resize rectangles in QGIS 3
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