def _assertCoordsAlmostEqual(self, pt1: QgsPointXY, pt2: QgsPointXY, places=6): """Assert coordinates are the same within 0.000005 degrees""" self.assertAlmostEqual(pt1.x(), pt2.x(), places=places) self.assertAlmostEqual(pt1.y(), pt2.y(), places=places)
def Draw_Graph(G): # extraire Les Sommets du Graphe G Nodes = list(G.nodes) # extraire Les Segments du Graphe G Segments = list(G.edges()) # creer une couche de Sommets memoire Nodes_layer = QgsVectorLayer('Point', 'Nodes', "memory") Nodes_pr = Nodes_layer.dataProvider() # creer une couche de Segments memoire Segments_layer = QgsVectorLayer('LineString', 'Segments', "memory") Segments_pr = Segments_layer.dataProvider() # les Sommets for i in range(len(Nodes)): Node = QgsPointXY(Nodes[i][0], Nodes[i][1]) # creer et ajouter le Sommet point = QgsFeature() point.setGeometry(QgsGeometry.fromPointXY(Node)) Nodes_pr.addFeatures([point]) # les Segments for i in range(len(Segments)): Start_Node = QgsPointXY(Segments[i][0][0], Segments[i][0][1]) End_Node = QgsPointXY(Segments[i][1][0], Segments[i][1][1]) if Start_Node.x() != End_Node.x() or Start_Node.y() != End_Node.y(): # creer et ajouter la line segment = QgsFeature() segment.setGeometry(QgsGeometry.fromPolylineXY([Start_Node, End_Node])) Segments_pr.addFeatures([segment]) Nodes_layer.updateExtents() Segments_layer.updateExtents() QgsProject.instance().addMapLayers([Nodes_layer, Segments_layer])
def set_point(self, variable: str, point: QgsPointXY, crs: QgsCoordinateReferenceSystem) -> list: """ Produces R code that creates a variable from point input. :param variable: string. Name of the variable. :param point: QgsPointXY. Point to extract x and y coordinates from. :param crs: QgsCoordinateReferenceSystem. Coordinate reference system for the point. :return: string. R code that constructs the point. """ commands = [] if self.use_sf: commands.append('point_crs <- st_crs(\'{}\')'.format(crs.toWkt())) commands.append( '{0} <- st_sfc(st_point(c({1},{2})), crs = point_crs)'.format( variable, point.x(), point.y())) else: commands.append('xy_df <- cbind(c({}), c({}))'.format( point.x(), point.y())) commands.append('point_crs <- CRS(\'{}\')'.format(crs.toProj4())) commands.append( '{} <- SpatialPoints(xy_df, proj4string = point_crs)'.format( variable)) return commands
def transformedCornerCoordinates(self, center, rotation, xScale, yScale): # scale topLeft = QgsPointXY( -self.image.width() / 2.0 * xScale, self.image.height() / 2.0 * yScale ) topRight = QgsPointXY( self.image.width() / 2.0 * xScale, self.image.height() / 2.0 * yScale ) bottomLeft = QgsPointXY( -self.image.width() / 2.0 * xScale, -self.image.height() / 2.0 * yScale ) bottomRight = QgsPointXY( self.image.width() / 2.0 * xScale, -self.image.height() / 2.0 * yScale ) # rotate # minus sign because rotation is CW in this class and Qt) rotationRad = -rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) topLeft = self._rotate(topLeft, cosRot, sinRot) topRight = self._rotate(topRight, cosRot, sinRot) bottomRight = self._rotate(bottomRight, cosRot, sinRot) bottomLeft = self._rotate(bottomLeft, cosRot, sinRot) topLeft.set(topLeft.x() + center.x(), topLeft.y() + center.y()) topRight.set(topRight.x() + center.x(), topRight.y() + center.y()) bottomRight.set(bottomRight.x() + center.x(), bottomRight.y() + center.y()) bottomLeft.set(bottomLeft.x() + center.x(), bottomLeft.y() + center.y()) return (topLeft, topRight, bottomRight, bottomLeft)
def transformedCornerCoordinates(self, center, rotation, xScale, yScale): # scale topLeft = QgsPointXY(-self.image.width() / 2.0 * xScale, self.image.height() / 2.0 * yScale) topRight = QgsPointXY(self.image.width() / 2.0 * xScale, self.image.height() / 2.0 * yScale) bottomLeft = QgsPointXY(-self.image.width() / 2.0 * xScale, - self.image.height() / 2.0 * yScale) bottomRight = QgsPointXY(self.image.width() / 2.0 * xScale, - self.image.height() / 2.0 * yScale) # rotate # minus sign because rotation is CW in this class and Qt) rotationRad = -rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) topLeft = self._rotate(topLeft, cosRot, sinRot) topRight = self._rotate(topRight, cosRot, sinRot) bottomRight = self._rotate(bottomRight, cosRot, sinRot) bottomLeft = self._rotate(bottomLeft, cosRot, sinRot) topLeft.set(topLeft.x() + center.x(), topLeft.y() + center.y()) topRight.set(topRight.x() + center.x(), topRight.y() + center.y()) bottomRight.set(bottomRight.x() + center.x(), bottomRight.y() + center.y()) bottomLeft.set(bottomLeft.x() + center.x(), bottomLeft.y() + center.y()) return (topLeft, topRight, bottomRight, bottomLeft)
def cut_point(self, section, xls_feature, side_dist_field = -1): feat = QgsFeature(xls_feature) points, bst, vst = self.calc_factor(section, xls_feature) p_old = QgsPointXY(points[0]) sum_len = 0 count_points = len(points) for i in range(count_points): p = QgsPointXY(points[i]) dist = self.distanz.measureLine(p_old, p) sum_len += dist # print(str(sum_len) + " > " + str(vst)) if sum_len > vst or i == count_points - 1: part = (sum_len - vst) / dist dx = p.x() - p_old.x() dy = p.y() - p_old.y() side_factor = 0 if side_dist_field >= 0: side_factor = xls_feature[side_dist_field] / dist x = p.x() - part * dx + dy * side_factor y = p.y() - part * dy - dx * side_factor feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y))) return feat p_old = p
def getCell(self, point): """ get local coordinates for point based on baseRaster transform """ topLeft = QgsPointXY(self.transform[0], self.transform[3]) pointInRaster = QgsPointXY(point.x() - topLeft.x(), topLeft.y() - point.y()) # swap axes cell = QgsPointXY(int(pointInRaster.y() / -self.transform[5]), int(pointInRaster.x() / self.transform[1])) return cell
def getGlobalPos(self, localPos): """ get global coordinates for local point based on baseRaster transform """ topLeft = QgsPointXY(self.transform[0], self.transform[3]) # swap axes pos = QgsPointXY(localPos.y() * (-self.transform[5]), localPos.x() * (-self.transform[1])) globalPoint = QgsPointXY(pos.x() + topLeft.x(), pos.y() + topLeft.y()) return globalPoint
def syntheticFeatureSelection(self, startPoint: QgsPointXY, endPoint: QgsPointXY, modifiers: Qt.KeyboardModifiers) -> None: if startPoint is None or endPoint is None: raise Exception( 'Something went very bad, unable to create selection without start or end point' ) assert self.simplifiedSegmentsLayer if self.selectionMode != SelectionModes.LINES: self.simplifiedSegmentsLayer.removeSelection() # check the Shift and Control modifiers to reproduce the navive selection if modifiers & Qt.ShiftModifier: selectBehaviour = QgsVectorLayer.AddToSelection elif modifiers & Qt.ControlModifier: selectBehaviour = QgsVectorLayer.RemoveFromSelection else: selectBehaviour = QgsVectorLayer.SetSelection if startPoint.x() == endPoint.x() and startPoint.y() == endPoint.y(): tolerance = QgsTolerance.defaultTolerance(iface.activeLayer(), QgsMapSettings()) tolerance = tolerance * self.canvas.mapUnitsPerPixel() startPoint = QgsPointXY(startPoint.x() - tolerance, startPoint.y() - tolerance) endPoint = QgsPointXY(endPoint.x() + tolerance, endPoint.y() + tolerance) lines = None rect = QgsRectangle(startPoint, endPoint) if self.selectionMode == SelectionModes.ENCLOSING: lines = self.getLinesSelectionModeEnclosing(selectBehaviour, rect) elif self.selectionMode == SelectionModes.LINES: lines = self.getLinesSelectionModeLines(selectBehaviour, rect) elif self.selectionMode == SelectionModes.NODES: lines = self.getLinesSelectionModeVertices(selectBehaviour, rect) if lines is None: return else: raise Exception( 'Wrong selection mode selected, should never be the case') if not len(lines): show_info(__('No results found!')) self.deleteAllCandidates() return if not self.addCandidates(lines): show_info(__('Unable to add candidates')) return
def get_rect_projection(self, rect_geom, cp, x_length=0, y_length=0): """ Transforms the rectangle geometry to its projection on the real world, making all its angles 90º :param rect_geom: 4 point geometry :param cp: central point of the geometry :param x_length: distance between first and second points of the rect_geom :param y_length: distance between second and third points of the rect_geom :return: geometry projected to map """ if x_length == 0 and y_length == 0: proj_geom = self.get_rect_by3_points(rect_geom.asPolygon()[0][0], rect_geom.asPolygon()[0][1], rect_geom.asPolygon()[0][2]) else: point_two = endpoint( rect_geom.asPolygon()[0][0], x_length, degrees( self.distance.bearing(rect_geom.asPolygon()[0][0], rect_geom.asPolygon()[0][1]))) point_three = endpoint( rect_geom.asPolygon()[0][0], y_length, degrees( self.distance.bearing(rect_geom.asPolygon()[0][1], rect_geom.asPolygon()[0][3]))) proj_geom = self.get_rect_by3_points(rect_geom.asPolygon()[0][0], point_two, point_three, y_length) if proj_geom is not None: p1 = proj_geom.asPolygon()[0][0] p2 = proj_geom.asPolygon()[0][1] p3 = proj_geom.asPolygon()[0][2] p4 = proj_geom.asPolygon()[0][3] px = (p1.x() + p3.x()) / 2.0 py = (p1.y() + p3.y()) / 2.0 p1 = QgsPointXY(p1.x() - px + cp.x(), p1.y() - py + cp.y()) p2 = QgsPointXY(p2.x() - px + cp.x(), p2.y() - py + cp.y()) p3 = QgsPointXY(p3.x() - px + cp.x(), p3.y() - py + cp.y()) p4 = QgsPointXY(p4.x() - px + cp.x(), p4.y() - py + cp.y()) proj_geom = QgsGeometry.fromPolygonXY([[p1, p2, p3, p4]]) return proj_geom else: return rect_geom
def showRect(self, startPoint, param, rotAngle=0): """ Draws a rectangle in the canvas """ self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) x = startPoint.x() # center point x y = startPoint.y() # center point y # rotation angle is always applied in reference to center point # to avoid unnecessary calculations c = cos(rotAngle) s = sin(rotAngle) # translating coordinate system to rubberband centroid point1 = QgsPointXY((-param), (-param)) point2 = QgsPointXY((-param), (param)) point3 = QgsPointXY((param), (param)) point4 = QgsPointXY((param), (-param)) # rotating and moving to original coord. sys. point1_ = QgsPointXY(point1.x() * c - point1.y() * s + x, point1.y() * c + point1.x() * s + y) point2_ = QgsPointXY(point2.x() * c - point2.y() * s + x, point2.y() * c + point2.x() * s + y) point3_ = QgsPointXY(point3.x() * c - point3.y() * s + x, point3.y() * c + point3.x() * s + y) point4_ = QgsPointXY(point4.x() * c - point4.y() * s + x, point4.y() * c + point4.x() * s + y) self.rubberBand.addPoint(point1_, False) self.rubberBand.addPoint(point2_, False) self.rubberBand.addPoint(point3_, False) self.rubberBand.addPoint(point4_, True) self.rubberBand.show() self.currentCentroid = startPoint
def rectangle2pCreate(firstPoint, secondPoint, azimutO): # X1Y2 (1) H2 secondPoint (2) # +---------------------------+ # | | # | | # V1 | | V2 # | | # | H1 | # +---------------------------+ ----------> AzimutO # firstPoint (0 - 4) X2Y1 (3) templinePoint = QgsPointXY(secondPoint.x() + 10 * math.sin(azimutO), secondPoint.y() + 10 * math.cos(azimutO)) p1 = pointToLine2D(firstPoint.x(), firstPoint.y(), secondPoint.x(), secondPoint.y(), templinePoint.x(), templinePoint.y()) ax = p1.x() - secondPoint.x() ay = p1.y() - secondPoint.y() width = math.sqrt(ax**2 + ay**2) ax = p1.x() - firstPoint.x() ay = p1.y() - firstPoint.y() height = math.sqrt(ax**2 + ay**2) centerX = (firstPoint.x() + secondPoint.x()) * 0.5 centerY = (firstPoint.y() + secondPoint.y()) * 0.5 tempLinePoint2 = QgsPointXY(firstPoint.x() + 10 * math.sin(azimutO), firstPoint.y() + 10 * math.cos(azimutO)) p3 = pointToLine2D(secondPoint.x(), secondPoint.y(), firstPoint.x(), firstPoint.y(), tempLinePoint2.x(), tempLinePoint2.y()) azP1 = normalizeAngle(lineAzimut2p(firstPoint, p1)) azP3 = normalizeAngle(lineAzimut2p(firstPoint, p3)) azimut100 = normalizeAngle(azimutO + math.pi * 0.5) if abs(azP3 - azimutO) <= 0.000001: if abs(azP1 - azimut100) <= 0.000001: # Cuadrante 2 return [p1, firstPoint, p3, secondPoint] else: # Cuadrante 1 return [firstPoint, p1, secondPoint, p3] else: if abs(azP1 - azimut100) <= 0.000001: # Cuadrante 3 return [secondPoint, p3, firstPoint, p1] else: # Cuadrante 4 return [p3, secondPoint, p1, firstPoint]
def processAlgorithm(self, parameters, context, feedback): inputFrameLayer = self.parameterAsSource( parameters,self.INPUT_FRAME, context ) boolVar = self.parameterAsBool( parameters,self.INPUT_FRAME, context ) gridScaleParam = self.parameterAsInt(parameters, self.INPUT_SCALE, context) frameLayer = self.runAddCount(inputFrameLayer, boolVar) if (gridScaleParam==0): gridScale = 25000 elif (gridScaleParam==1): gridScale = 50000 if (gridScaleParam==2): gridScale = 100000 elif (gridScaleParam==3): gridScale = 250000 self.runCreateSpatialIndex(frameLayer) # Converter moldura para lat long crs = QgsCoordinateReferenceSystem("EPSG:4326") frameLayer4326 = self.reprojectLayer(frameLayer, crs) # Pegar centro da moldura (se tiver mais de um polígono na camada de moldura pegar o centro dos centros) if frameLayer4326.featureCount()>1: xs=[] ys=[] for poly in frameLayer4326.getFeatures(): centroid=QgsPointXY(poly.geometry().centroid().constGet()) xs.append(centroid.x()) ys.append(centroid.y()) centroid= QgsPointXY(sum(xs)/len(xs), sum(ys)/len(ys)) else: for poly in frameLayer4326.getFeatures(): centroid=QgsPointXY(poly.geometry().centroid().constGet()) # Descobrir o utm utmString = self.getSirgasAuthIdByPointLatLong(centroid.y(), centroid.x()) utm = QgsCoordinateReferenceSystem(utmString) frameLayerReprojected = self.reprojectLayer(frameLayer, utm) # Criar a grade com 4cm (baseado na escala) de distancia entre as linhas no fuso gridSize = 4*gridScale/100 ptLyrExt = frameLayerReprojected.extent() xmin = ptLyrExt.xMinimum() xmax = ptLyrExt.xMaximum() ymin = ptLyrExt.yMinimum() ymax = ptLyrExt.yMaximum() xmin, xmax, ymin, ymax = self.processExtent(xmin, xmax, ymin, ymax, gridSize) grid = self.makeGrid(gridSize, utm, xmin, xmax, ymin, ymax, parameters, context, feedback) # Reprojetar para CRS de destino (moldura) reprojectGrid = self.reprojectLayer(grid,inputFrameLayer.sourceCrs()) lineLayer = self.convertPolygonToLines(reprojectGrid) newLayer = self.outLayer(parameters, context, lineLayer, 2) return {self.OUTPUT: newLayer}
def testPoint(self): point = QgsReferencedPointXY(QgsPointXY(1.0, 2.0), QgsCoordinateReferenceSystem('epsg:3111')) self.assertEqual(point.x(), 1.0) self.assertEqual(point.y(), 2.0) self.assertEqual(point.crs().authid(), 'EPSG:3111') point.setCrs(QgsCoordinateReferenceSystem('epsg:28356')) self.assertEqual(point.crs().authid(), 'EPSG:28356') # in variant v = QVariant( QgsReferencedPointXY(QgsPointXY(3.0, 4.0), QgsCoordinateReferenceSystem('epsg:3111'))) self.assertEqual(v.value().x(), 3.0) self.assertEqual(v.value().y(), 4.0) self.assertEqual(v.value().crs().authid(), 'EPSG:3111') # to QgsPointXY p = QgsPointXY(point) self.assertEqual(p.x(), 1.0) self.assertEqual(p.y(), 2.0) # equality point = QgsReferencedPointXY(QgsPointXY(1.0, 2.0), QgsCoordinateReferenceSystem('epsg:3111')) point2 = QgsReferencedPointXY( QgsPointXY(1.0, 2.0), QgsCoordinateReferenceSystem('epsg:3111')) self.assertEqual(point, point2) point2 = QgsReferencedPointXY( QgsPointXY(1.0, 2.0), QgsCoordinateReferenceSystem('epsg:4326')) self.assertNotEqual(point, point2) point2 = QgsReferencedPointXY( QgsPointXY(1.1, 2.0), QgsCoordinateReferenceSystem('epsg:3111')) self.assertNotEqual(point, point2)
def capture_position(self, event): """ Record the position of the mouse pointer and adjust if keyboard modifier is pressed :type event: qgis.gui.QgsMapMouseEvent """ # adjust dimension on the fly if Shift is pressed if QApplication.keyboardModifiers() == Qt.ShiftModifier: end_point = QgsPointXY(self.toMapCoordinates(event.pos())) rect = QgsRectangle(self.startPoint, end_point) # return if start and endpoint are the same if rect.width() + rect.height() == 0: self.endPoint = self.toMapCoordinates(event.pos()) return if rect.width() > rect.height(): # make height (y) same as width in the correct direction if self.startPoint.y() < end_point.y(): end_point.setY(self.startPoint.y() + rect.width()) else: end_point.setY(self.startPoint.y() - rect.width()) else: # make width (x) same as height in the correct direction if self.startPoint.x() < end_point.x(): end_point.setX(self.startPoint.x() + rect.height()) else: end_point.setX(self.startPoint.x() - rect.height()) self.endPoint = end_point else: self.endPoint = self.toMapCoordinates(event.pos())
def calculate_score(self, a_x, a_y, a_angle, a_scale, b_x, b_y, b_angle, b_scale): """ This calculates the score of this edge with custom parameter values (to be used by optimizer) """ # We get the transform matrix (matrix to transform from A to B, as calculated by imreg_dft) tvec = QgsPointXY(self.tvec[0], self.tvec[1]) tvec *= self.imageA.pixel_size * a_scale / DOWNSCALING_FACTOR edge_matrix = transform_matrix(self.scale, self.angle, tvec.x(), tvec.y()) # We get the point A transform matrix (matrix to transform from local to A coordinates) ptA_matrix = transform_matrix(a_scale, a_angle, a_x, a_y) # We compute the A*edge matrix (matrix to get to B coordinates) ptA_edge_matrix = ptA_matrix * edge_matrix # We get the point B transform matrix (matrix to transform from local to B coordinates) ptB_matrix = transform_matrix(b_scale, b_angle, b_x, b_y) # Now we compare how well ptA_edge_matrix and ptB_matrix are similar using two sample points (in homogeneous coordinates) sample1 = [[10], [0], [1]] sample1_a = ptA_matrix * sample1 sample1_b = ptB_matrix * sample1 sample1_ab = ptA_edge_matrix * sample1 sample2 = [[0], [10], [1]] sample2_a = ptA_matrix * sample2 sample2_b = ptB_matrix * sample2 sample2_ab = ptA_edge_matrix * sample2 # The score is the distance between the two transformed points (summed) score1 = math.sqrt((sample1_b.item(0) - sample1_ab.item(0))**2 + (sample1_b.item(1) - sample1_ab.item(1))**2) score2 = math.sqrt((sample2_b.item(0) - sample2_ab.item(0))**2 + (sample2_b.item(1) - sample2_ab.item(1))**2) return score1 + score2
def update(self, point: QgsPointXY): userCrsPoint = self.transform.transform(point) self.dockwidget.userCrsEdit.setText('{0:.{2}f}, {1:.{2}f}'.format(userCrsPoint.x(), userCrsPoint.y(), self.userCrsDisplayPrecision)) self.dockwidget.canvasCrsEdit.setText('{0:.{2}f}, {1:.{2}f}'.format(point.x(), point.y(), self.canvasCrsDisplayPrecision))
def normalizePoint(self, x, y): """Normalize given point. In result, lower-left is (0, 0) and upper-right is (1, 1).""" pt = QgsPointXY(x, y) if self._rotation: pt = self.rotatePoint(pt, -self._rotation, self._center) rect = self._unrotated_rect return QgsPointXY((pt.x() - rect.xMinimum()) / rect.width(), (pt.y() - rect.yMinimum()) / rect.height())
def testContains(self): rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0) rect2 = QgsRectangle(2.0, 2.0, 7.0, 7.0) pnt1 = QgsPointXY(4.0, 4.0) pnt2 = QgsPointXY(6.0, 2.0) rect3 = rect1.intersect(rect2) self.assertTrue(rect1.contains(rect3)) self.assertTrue(rect2.contains(rect3)) # test for point self.assertTrue(rect1.contains(pnt1)) self.assertTrue(rect1.contains(pnt1.x(), pnt1.y())) self.assertTrue(rect2.contains(pnt1)) self.assertTrue(rect2.contains(pnt1.x(), pnt1.y())) self.assertTrue(rect3.contains(pnt1)) self.assertTrue(rect3.contains(pnt1.x(), pnt1.y())) self.assertFalse(rect1.contains(pnt2)) self.assertFalse(rect1.contains(pnt2.x(), pnt2.y())) self.assertTrue(rect2.contains(pnt2)) self.assertTrue(rect2.contains(pnt2.x(), pnt2.y())) self.assertFalse(rect3.contains(pnt2)) self.assertFalse(rect3.contains(pnt2.x(), pnt2.y())) self.assertTrue(rect3.contains(pnt1)) self.assertTrue(rect3.contains(pnt1.x(), pnt1.y()))
def anglesBetweenLines(self, line1, line2, point): pointB = QgsPointXY(point.asPoint()) pointA = self.adjacentPoint(line1, pointB) pointC = self.adjacentPoint(line2, pointB) angleRad = QgsGeometryUtils().angleBetweenThreePoints( pointA.x(), pointA.y(), pointB.x(), pointB.y(), pointC.x(), pointC.y()) angle = math.degrees(angleRad) return abs(angle)
def calculateSquare(self, point): ''' point in layer coordinates(QgsPoint) ''' mapCrs = self.canvas.mapSettings().destinationCrs() utmCrs = QgsCoordinateReferenceSystem() utmCrs.createFromProj4(self.proj4Utm(point)) ctFwd = QgsCoordinateTransform(mapCrs, utmCrs, QgsProject.instance()) ctBwd = QgsCoordinateTransform(utmCrs, mapCrs, QgsProject.instance()) pointGeom = QgsGeometry.fromPointXY(point) pointGeom.transform(ctFwd) pointUtm = QgsPointXY(pointGeom.asPoint()) # calculate d d = self.diagonal / (2 * (2**0.5)) left = pointUtm.x() - d bottom = pointUtm.y() - d right = pointUtm.x() + d top = pointUtm.y() + d p1 = QgsGeometry.fromPointXY(QgsPointXY(left, bottom)) p2 = QgsGeometry.fromPointXY(QgsPointXY(right, bottom)) p3 = QgsGeometry.fromPointXY(QgsPointXY(right, top)) p4 = QgsGeometry.fromPointXY(QgsPointXY(left, top)) p1.transform(ctBwd) p2.transform(ctBwd) p3.transform(ctBwd) p4.transform(ctBwd) mapPol = [ p1.asPoint(), p2.asPoint(), p3.asPoint(), p4.asPoint(), p1.asPoint() ] return mapPol
def transformedCornerCoordinatesFromPoint( self, startPoint, rotation, xScale, yScale ): # startPoint is a fixed point for this new movement (rotation and # scale) # rotation is the global rotation of the image # xScale is the new xScale factor to be multiplied by self.xScale # idem for yScale # Calculate the coordinate of the center in a startPoint origin # coordinate system and apply scales dX = (self.center.x() - startPoint.x()) * xScale dY = (self.center.y() - startPoint.y()) * yScale # Half width and half height in the current transformation hW = (self.image.width() / 2.0) * self.xScale * xScale hH = (self.image.height() / 2.0) * self.yScale * yScale # Actual rectangle coordinates : pt1 = QgsPointXY(-hW, hH) pt2 = QgsPointXY(hW, hH) pt3 = QgsPointXY(hW, -hH) pt4 = QgsPointXY(-hW, -hH) # Actual rotation from the center # minus sign because rotation is CW in this class and Qt) rotationRad = -self.rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) pt1 = self._rotate(pt1, cosRot, sinRot) pt2 = self._rotate(pt2, cosRot, sinRot) pt3 = self._rotate(pt3, cosRot, sinRot) pt4 = self._rotate(pt4, cosRot, sinRot) # Second transformation # displacement of the origin pt1 = QgsPointXY(pt1.x() + dX, pt1.y() + dY) pt2 = QgsPointXY(pt2.x() + dX, pt2.y() + dY) pt3 = QgsPointXY(pt3.x() + dX, pt3.y() + dY) pt4 = QgsPointXY(pt4.x() + dX, pt4.y() + dY) # Rotation # minus sign because rotation is CW in this class and Qt) rotationRad = -rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) pt1 = self._rotate(pt1, cosRot, sinRot) pt2 = self._rotate(pt2, cosRot, sinRot) pt3 = self._rotate(pt3, cosRot, sinRot) pt4 = self._rotate(pt4, cosRot, sinRot) # translate to startPoint pt1 = QgsPointXY(pt1.x() + startPoint.x(), pt1.y() + startPoint.y()) pt2 = QgsPointXY(pt2.x() + startPoint.x(), pt2.y() + startPoint.y()) pt3 = QgsPointXY(pt3.x() + startPoint.x(), pt3.y() + startPoint.y()) pt4 = QgsPointXY(pt4.x() + startPoint.x(), pt4.y() + startPoint.y()) return (pt1, pt2, pt3, pt4)
def transformedCornerCoordinatesFromPoint(self, startPoint, rotation, xScale, yScale): # startPoint is a fixed point for this new movement (rotation and # scale) # rotation is the global rotation of the image # xScale is the new xScale factor to be multiplied by self.xScale # idem for yScale # Calculate the coordinate of the center in a startPoint origin # coordinate system and apply scales dX = (self.center.x() - startPoint.x()) * xScale dY = (self.center.y() - startPoint.y()) * yScale # Half width and half height in the current transformation hW = (self.image.width() / 2.0) * self.xScale * xScale hH = (self.image.height() / 2.0) * self.yScale * yScale # Actual rectangle coordinates : pt1 = QgsPointXY(-hW, hH) pt2 = QgsPointXY(hW, hH) pt3 = QgsPointXY(hW, -hH) pt4 = QgsPointXY(-hW, -hH) # Actual rotation from the center # minus sign because rotation is CW in this class and Qt) rotationRad = -self.rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) pt1 = self._rotate(pt1, cosRot, sinRot) pt2 = self._rotate(pt2, cosRot, sinRot) pt3 = self._rotate(pt3, cosRot, sinRot) pt4 = self._rotate(pt4, cosRot, sinRot) # Second transformation # displacement of the origin pt1 = QgsPointXY(pt1.x() + dX, pt1.y() + dY) pt2 = QgsPointXY(pt2.x() + dX, pt2.y() + dY) pt3 = QgsPointXY(pt3.x() + dX, pt3.y() + dY) pt4 = QgsPointXY(pt4.x() + dX, pt4.y() + dY) # Rotation # minus sign because rotation is CW in this class and Qt) rotationRad = -rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) pt1 = self._rotate(pt1, cosRot, sinRot) pt2 = self._rotate(pt2, cosRot, sinRot) pt3 = self._rotate(pt3, cosRot, sinRot) pt4 = self._rotate(pt4, cosRot, sinRot) # translate to startPoint pt1 = QgsPointXY(pt1.x() + startPoint.x(), pt1.y() + startPoint.y()) pt2 = QgsPointXY(pt2.x() + startPoint.x(), pt2.y() + startPoint.y()) pt3 = QgsPointXY(pt3.x() + startPoint.x(), pt3.y() + startPoint.y()) pt4 = QgsPointXY(pt4.x() + startPoint.x(), pt4.y() + startPoint.y()) return (pt1, pt2, pt3, pt4)
def set_center_from_canvas_point(self, point: QgsPointXY): """ Sets the widget center point from a canvas point """ ct = QgsCoordinateTransform( self.iface.mapCanvas().mapSettings().destinationCrs(), QgsCoordinateReferenceSystem('EPSG:4326'), QgsProject.instance()) try: point = ct.transform(point) self.circular_lat_spinbox.setValue(point.y()) self.circular_long_spinbox.setValue(point.x()) except QgsCsException: pass
def redrawRubberBand(self): self.canvas.scene().removeItem(self.rubberBand) self.prepareRubberBand() for i in range(len(self.capturedPoints)): point = self.capturedPoints[i] if point.__class__ == QgsPoint: vertexCoord = self.toMapCoordinatesV2(self.layer, self.capturedPoints[i]) vertexCoord = QgsPointXY(vertexCoord.x(), vertexCoord.y()) else: vertexCoord = self.toMapCoordinates(self.layer, self.capturedPoints[i]) self.rubberBand.addPoint(vertexCoord)
def point_clicked(self, point=None, button=None): if self.raster is None: self.uc.bar_warn("Choose a raster to work with...", dur=3) return if self.logger: self.logger.debug(f"Clicked point in canvas CRS: {point if point else self.last_point}") if point is None: ptxy_in_src_crs = self.last_point else: if self.crs_transform: if self.logger: self.logger.debug(f"Transforming clicked point {point}") try: ptxy_in_src_crs = self.crs_transform.transform(point) except QgsCsException as err: self.uc.show_warn( "Point coordinates transformation failed! Check the raster projection:\n\n{}".format(repr(err))) return else: ptxy_in_src_crs = QgsPointXY(point.x(), point.y()) if self.logger: self.logger.debug(f"Clicked point in raster CRS: {ptxy_in_src_crs}") self.last_point = ptxy_in_src_crs ident_vals = self.handler.provider.identify(ptxy_in_src_crs, QgsRaster.IdentifyFormatValue).results() cur_vals = list(ident_vals.values()) # check if the point is within active raster extent if not self.rbounds[0] <= ptxy_in_src_crs.x() <= self.rbounds[2]: self.uc.bar_info("Out of x bounds", dur=3) return if not self.rbounds[1] <= ptxy_in_src_crs.y() <= self.rbounds[3]: self.uc.bar_info("Out of y bounds", dur=3) return if self.mode == 'draw': new_vals = self.spin_boxes.get_values() if self.logger: self.logger.debug(f"Applying const value {new_vals}") self.apply_values_single_cell(new_vals) else: self.spin_boxes.set_values(cur_vals) if 2 < self.handler.bands_nr < 5: self.color_picker_connection(connect=False) self.color_btn.setColor(QColor(*self.spin_boxes.get_values()[:4])) self.color_picker_connection(connect=True)
def test_change_position(self): self.write_temp_mission_xml() self.mission_ctrl.load_mission(self.MISSION_NAME + ".xml") self.mission_track = self.mission_ctrl.mission_list[0] point = QgsPointXY(40.001, 3.002) self.mission_track.change_position(0, point) position = self.mission_track.get_step(0).get_maneuver().get_position() lat = position.get_latitude() lon = position.get_longitude() self.assertEqual(point.x(), lon) self.assertEqual(point.y(), lat) self.assertEqual(self.mission_track.is_modified(), True)
def set_map_state(self, center: QgsPointXY, zoom: float, bearing: int = 0, drag_rotate: bool = False, pitch: int = 0, is_split: bool = False, map_view_mode: str = MapState.map_view_mode): """ Set map state values """ try: self._map_state = MapState(bearing, drag_rotate, center.y(), center.x(), pitch, zoom, is_split, map_view_mode, Globe.create_default()) except Exception as e: raise InvalidInputException( tr('Check the map state configuration values'), bar_msg=bar_msg(e))
def testPoint(self): point = QgsReferencedPointXY(QgsPointXY(1.0, 2.0), QgsCoordinateReferenceSystem('epsg:3111')) self.assertEqual(point.x(), 1.0) self.assertEqual(point.y(), 2.0) self.assertEqual(point.crs().authid(), 'EPSG:3111') point.setCrs(QgsCoordinateReferenceSystem('epsg:28356')) self.assertEqual(point.crs().authid(), 'EPSG:28356') # in variant v = QVariant(QgsReferencedPointXY(QgsPointXY(3.0, 4.0), QgsCoordinateReferenceSystem('epsg:3111'))) self.assertEqual(v.value().x(), 3.0) self.assertEqual(v.value().y(), 4.0) self.assertEqual(v.value().crs().authid(), 'EPSG:3111') # to QgsPointXY p = QgsPointXY(point) self.assertEqual(p.x(), 1.0) self.assertEqual(p.y(), 2.0)
def showRect(self, startPoint: QgsPointXY, endPoint: QgsPointXY) -> None: self.rubberBand.reset(QgsWkbTypes.PolygonGeometry) if startPoint.x() == endPoint.x() or startPoint.y() == endPoint.y(): return point1 = QgsPointXY(startPoint.x(), startPoint.y()) point2 = QgsPointXY(startPoint.x(), endPoint.y()) point3 = QgsPointXY(endPoint.x(), endPoint.y()) point4 = QgsPointXY(endPoint.x(), startPoint.y()) self.rubberBand.addPoint(point1, False) self.rubberBand.addPoint(point2, False) self.rubberBand.addPoint(point3, False) self.rubberBand.addPoint(point4, True) # true to update canvas self.rubberBand.show()
def do_request(self, point: QgsPointXY) -> None: query = QUrlQuery() query.addQueryItem("lat", str(point.y())) query.addQueryItem("lon", str(point.x())) query.addQueryItem("format", "json") url = QUrl(self.URL) url.setQuery(query) request = QNetworkRequest(url) request.setHeader(QNetworkRequest.UserAgentHeader, "*****@*****.**") response = self.nam.blockingGet(request) self._status_code = response.attribute( QNetworkRequest.HttpStatusCodeAttribute) self._content = json.loads(bytes(response.content())) if self._content.get("error"): self._error_string = self._content["error"] return
def accept(self): """ Insert self.pont in the canvas""" self.set_format() if self.point is not None: new_point = QgsPointXY(float(self.get_coordinates()[1]), float(self.get_coordinates()[0])) if self.point_layer is None: self.add_new_landmark(self.point) self.point_layer.startEditing() self.point_layer.beginEditCommand("Move Point") # for undo self.point_layer.moveVertex(new_point.x(), new_point.y(), self.feat.id() + 1, 0) self.point_layer.endEditCommand() self.point_layer.commitChanges() self.finish_add_landmark_signal.emit() super(PointFeatureDlg, self).accept() else: QMessageBox.warning(self, "Invalid Point", "Invalid point, make sure the coordinates are correct.", QMessageBox.Close)
def canvasMoveEvent(self, event): if self.snapCursorRubberBand: self.snapCursorRubberBand.hide() self.snapCursorRubberBand.reset( geometryType=QgsWkbTypes.PointGeometry) self.snapCursorRubberBand = None oldPoint = QgsPointXY(event.mapPoint()) event.snapPoint() point = QgsPointXY(event.mapPoint()) if oldPoint != point: self.createSnapCursor(point) if self.rubberBand: if self.qntPoint == 1: self.distanceToolTip.canvasMoveEvent(self.geometry[0], point) geom = QgsGeometry.fromPolylineXY([self.geometry[0], point]) self.rubberBand.setToGeometry(geom, None) elif self.qntPoint >= 2: if self.free: self.distanceToolTip.canvasMoveEvent( self.geometry[-1], point) geom = QgsGeometry.fromPolygonXY( [self.geometry + [QgsPointXY(point.x(), point.y())]]) self.rubberBand.setToGeometry(geom, None) else: if (self.qntPoint % 2 == 1): self.setAvoidStyleSnapRubberBand() else: self.setAllowedStyleSnapRubberBand() projectedMousePoint = self.projectPoint( self.geometry[-2], self.geometry[-1], point) self.distanceToolTip.canvasMoveEvent( self.geometry[-1], projectedMousePoint) if projectedMousePoint: geom, pf = self.completePolygon( self.geometry, projectedMousePoint) self.rubberBand.setToGeometry(geom, None) else: self.initVariable()
def checkPoint(self, point): state = 'yellow' if type(point) != QgsPointXY: try: if type(point) == list and len(point) == 2: point = QgsPointXY(point[0], point[1]) else: point = QgsPointXY(point) except TypeError: return state, None if self.dhm != {}: extent = self.dhm['extent'] [extLx, extHy, extHx, extLy] = extent if extLx <= float(point.x()) <= extHx \ and extLy <= float(point.y()) <= extHy: state = 'green' else: state = 'red' return state, point
def run(sources_layer_path, receivers_layer_path, emission_pts_layer_path, research_ray): sources_layer = QgsVectorLayer(sources_layer_path, "input layer", "ogr") receivers_layer = QgsVectorLayer(receivers_layer_path, "output layer", "ogr") sources_feat_all = sources_layer.dataProvider().getFeatures() receivers_feat_all_dict = {} receivers_feat_all = receivers_layer.dataProvider().getFeatures() receivers_spIndex = QgsSpatialIndex() for receivers_feat in receivers_feat_all: receivers_spIndex.insertFeature(receivers_feat) receivers_feat_all_dict[receivers_feat.id()] = receivers_feat emission_pts_fields = QgsFields() emission_pts_fields.append(QgsField("id_emi", QVariant.Int)) emission_pts_fields.append(QgsField("id_emi_source", QVariant.Int)) emission_pts_fields.append(QgsField("id_source", QVariant.Int)) emission_pts_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2)) # update for QGIS 3 converting VectorWriter to QgsVectorFileWriter # emission_pts_writer = VectorWriter(emission_pts_layer_path, None, emission_pts_fields, 0, sources_layer.crs()) emission_pts_writer = QgsVectorFileWriter(emission_pts_layer_path, "System", emission_pts_fields, QgsWkbTypes.Point, sources_layer.crs(), "ESRI Shapefile") # initializes ray and emission point id emission_pt_id = 0 for sources_feat in sources_feat_all: # researches the receiver points in a rectangle created by the research_ray # creates the search rectangle rect = QgsRectangle() rect.setXMinimum(sources_feat.geometry().boundingBox().xMinimum() - research_ray) rect.setXMaximum(sources_feat.geometry().boundingBox().xMaximum() + research_ray) rect.setYMinimum(sources_feat.geometry().boundingBox().yMinimum() - research_ray) rect.setYMaximum(sources_feat.geometry().boundingBox().yMaximum() + research_ray) receiver_pts_request = receivers_spIndex.intersects(rect) distance_min = [] for receiver_pts_id in receiver_pts_request: receiver_pts_feat = receivers_feat_all_dict[receiver_pts_id] result = sources_feat.geometry().closestSegmentWithContext(receiver_pts_feat.geometry().asPoint()) distance_min_tmp = sqrt(result[0]) if distance_min_tmp <= research_ray: distance_min.append(distance_min_tmp) # defines segment max length if len(distance_min) >= 1: segment_max = min(distance_min) / 2 if segment_max < 2: segment_max = 2 else: continue # splits the sources line in emission points at a fix distance (minimum distance/2) and create the emission point layer # gets vertex sources_geom = sources_feat.geometry() if sources_geom.isMultipart(): sources_geom.convertToSingleType() sources_feat_vertex_pt_all = sources_geom.asPolyline() emission_pt_id_road = 0 for i in range(0, len(sources_feat_vertex_pt_all)): pt1 = QgsPointXY(sources_feat_vertex_pt_all[i]) add_point_to_layer(emission_pts_writer, pt1, [emission_pt_id, emission_pt_id_road, sources_feat.id(), segment_max]) emission_pt_id = emission_pt_id + 1 emission_pt_id_road = emission_pt_id_road + 1 if i < len(sources_feat_vertex_pt_all) - 1: pt2 = QgsPoint(sources_feat_vertex_pt_all[i + 1]) x1 = pt1.x() y1 = pt1.y() x2 = pt2.x() y2 = pt2.y() if y2 == y1: dx = segment_max dy = 0 m = 0 elif x2 == x1: dx = 0 dy = segment_max else: m = (y2 - y1) / (x2 - x1) dx = sqrt((segment_max ** 2) / (1 + m ** 2)) dy = sqrt(((segment_max ** 2) * (m ** 2)) / (1 + m ** 2)) pt = pt1 while compute_distance(pt, pt2) > segment_max: x_temp = pt.x() y_temp = pt.y() if x_temp < x2: if m > 0: pt = QgsPointXY(x_temp + dx, y_temp + dy) elif m < 0: pt = QgsPointXY(x_temp + dx, y_temp - dy) elif m == 0: pt = QgsPointXY(x_temp + dx, y_temp) elif x_temp > x2: if m > 0: pt = QgsPointXY(x_temp - dx, y_temp - dy) elif m < 0: pt = QgsPointXY(x_temp - dx, y_temp + dy) elif m == 0: pt = QgsPointXY(x_temp - dx, y_temp) elif x_temp == x2: if y2 > y_temp: pt = QgsPointXY(x_temp, y_temp + dy) else: pt = QgsPointXY(x_temp, y_temp - dy) add_point_to_layer(emission_pts_writer, pt, [emission_pt_id, emission_pt_id_road, sources_feat.id(), segment_max]) emission_pt_id = emission_pt_id + 1 emission_pt_id_road = emission_pt_id_road + 1 del emission_pts_writer
class FreehandRasterGeoreferencerLayer(QgsPluginLayer): LAYER_TYPE = "FreehandRasterGeoreferencerLayer" transformParametersChanged = pyqtSignal(tuple) def __init__(self, plugin, filepath, title, screenExtent): QgsPluginLayer.__init__( self, FreehandRasterGeoreferencerLayer.LAYER_TYPE, title) self.plugin = plugin self.iface = plugin.iface self.title = title self.filepath = filepath self.screenExtent = screenExtent self.history = [] # set custom properties self.setCustomProperty("title", title) self.setCustomProperty("filepath", self.filepath) self.setValid(True) self.setTransparency(LayerDefaultSettings.TRANSPARENCY) self.setBlendModeByName(LayerDefaultSettings.BLEND_MODE) # dummy data: real init is done in intializeLayer self.center = QgsPointXY(0, 0) self.rotation = 0.0 self.xScale = 1.0 self.yScale = 1.0 self.error = False self.initializing = False self.initialized = False self.initializeLayer(screenExtent) self._extent = None self.provider = FreehandRasterGeoreferencerLayerProvider(self) def dataProvider(self): # issue with DBManager if the dataProvider of the QgsLayerPlugin # returns None return self.provider def setScale(self, xScale, yScale): self.xScale = xScale self.yScale = yScale def setRotation(self, rotation): rotation = round(rotation, 1) # keep in -180,180 interval if rotation < -180: rotation += 360 if rotation > 180: rotation -= 360 self.rotation = rotation def setCenter(self, center): self.center = center def commitTransformParameters(self): QgsProject.instance().setDirty(True) self._extent = None self.setCustomProperty("xScale", self.xScale) self.setCustomProperty("yScale", self.yScale) self.setCustomProperty("rotation", self.rotation) self.setCustomProperty("xCenter", self.center.x()) self.setCustomProperty("yCenter", self.center.y()) self.transformParametersChanged.emit( (self.xScale, self.yScale, self.rotation, self.center)) def reprojectTransformParameters(self, oldCrs, newCrs): transform = QgsCoordinateTransform(oldCrs, newCrs, QgsProject.instance()) newCenter = transform.transform(self.center) newExtent = transform.transform(self.extent()) # transform the parameters except rotation # TODO rotation could be better handled (maybe check rotation between # old and new extent) # but not really worth the effort ? self.setCrs(newCrs) self.setCenter(newCenter) self.resetScale(newExtent.width(), newExtent.height()) def resetTransformParametersToNewCrs(self): """ Attempts to keep the layer on the same region of the map when the map CRS is changed """ oldCrs = self.crs() newCrs = self.iface.mapCanvas().mapSettings().destinationCrs() self.reprojectTransformParameters(oldCrs, newCrs) self.commitTransformParameters() def setupCrsEvents(self): layerId = self.id() def removeCrsChangeHandler(layerIds): if layerId in layerIds: try: self.iface.mapCanvas().destinationCrsChanged.disconnect( self.resetTransformParametersToNewCrs) except Exception: pass try: QgsProject.instance().disconnect( removeCrsChangeHandler) except Exception: pass self.iface.mapCanvas().destinationCrsChanged.connect( self.resetTransformParametersToNewCrs) QgsProject.instance().layersRemoved.connect( removeCrsChangeHandler) def setupCrs(self): mapCrs = self.iface.mapCanvas().mapSettings().destinationCrs() self.setCrs(mapCrs) self.setupCrsEvents() def repaint(self): self.repaintRequested.emit() def transformParameters(self): return (self.center, self.rotation, self.xScale, self.yScale) def initializeLayer(self, screenExtent=None): if self.error or self.initialized or self.initializing: return if self.filepath is not None: # not safe... self.initializing = True filepath = self.getAbsoluteFilepath() if not os.path.exists(filepath): # TODO integrate with BadLayerHandler ? loadErrorDialog = LoadErrorDialog(filepath) result = loadErrorDialog.exec_() if result == 1: # absolute filepath = loadErrorDialog.lineEditImagePath.text() # to relative if needed self.filepath = utils.toRelativeToQGS(filepath) self.setCustomProperty("filepath", self.filepath) QgsProject.instance().setDirty(True) else: self.error = True del loadErrorDialog fileInfo = QFileInfo(filepath) ext = fileInfo.suffix() if ext == "pdf": s = QSettings() oldValidation = s.value("/Projections/defaultBehavior") s.setValue("/Projections/defaultBehavior", "useGlobal") # for not asking about crs path = fileInfo.filePath() baseName = fileInfo.baseName() layer = QgsRasterLayer(path, baseName) self.image = layer.previewAsImage(QSize(layer.width(),layer.height())) s.setValue("/Projections/defaultBehavior", oldValidation) else: reader = QImageReader(filepath) self.image = reader.read() self.initialized = True self.initializing = False self.setupCrs() if screenExtent: # constructor called from AddLayer action # if not, layer loaded from QGS project file # check if image already has georef info # use GDAL dataset = gdal.Open(filepath, gdal.GA_ReadOnly) georef = None if dataset: georef = dataset.GetGeoTransform() if georef and not self.is_default_geotransform(georef): self.initializeExistingGeoreferencing(dataset, georef) else: # init to default params self.setCenter(screenExtent.center()) self.setRotation(0.0) sw = screenExtent.width() sh = screenExtent.height() self.resetScale(sw, sh) self.commitTransformParameters() def initializeExistingGeoreferencing(self, dataset, georef): # georef can have scaling, rotation or translation rotation = 180 / math.pi * -math.atan2(georef[4], georef[1]) sx = math.sqrt(georef[1] ** 2 + georef[4] ** 2) sy = math.sqrt(georef[2] ** 2 + georef[5] ** 2) i_center_x = self.image.width() / 2 i_center_y = self.image.height() / 2 center = QgsPointXY(georef[0] + georef[1] * i_center_x + georef[2] * i_center_y, georef[3] + georef[4] * i_center_x + georef[5] * i_center_y) qDebug(repr(rotation) + " " + repr((sx, sy)) + " " + repr(center)) self.setRotation(rotation) self.setCenter(center) # keep yScale positive self.setScale(sx, sy) self.commitTransformParameters() crs_wkt = dataset.GetProjection() message_shown = False if crs_wkt: qcrs = QgsCoordinateReferenceSystem(crs_wkt) if qcrs != self.crs(): # reproject try: self.reprojectTransformParameters(qcrs, self.crs()) self.commitTransformParameters() self.showBarMessage( "Transform parameters changed", "Found existing georeferencing in raster but " "its CRS does not match the CRS of the map. " "Reprojected the extent.", Qgis.Warning, 5) message_shown = True except Exception as ex: QgsMessageLog.logMessage(repr(ex)) self.showBarMessage( "CRS does not match", "Found existing georeferencing in raster but " "its CRS does not match the CRS of the map. " "Unable to reproject.", Qgis.Warning, 5) message_shown = True # if no projection info, assume it is the same CRS # as the map and no warning if not message_shown: self.showBarMessage( "Georeferencing loaded", "Found existing georeferencing in raster", Qgis.Info, 3) # zoom (assume the user wants to work on the image) self.iface.mapCanvas().setExtent(self.extent()) def is_default_geotransform(self, georef): """ Check if there is really a transform or if it is just the default made up by GDAL """ return (georef[0] == 0 and georef[3] == 0 and georef[1] == 1 and georef[5] == 1) def resetScale(self, sw, sh): iw = self.image.width() ih = self.image.height() wratio = sw / iw hratio = sh / ih if wratio > hratio: # takes all height of current extent self.setScale(hratio, hratio) else: # all width self.setScale(wratio, wratio) def replaceImage(self, filepath, title): self.title = title self.filepath = filepath # set custom properties self.setCustomProperty("title", title) self.setCustomProperty("filepath", self.filepath) self.setName(title) fileInfo = QFileInfo(filepath) ext = fileInfo.suffix() if ext == "pdf": s = QSettings() oldValidation = s.value("/Projections/defaultBehavior") s.setValue("/Projections/defaultBehavior", "useGlobal") # for not asking about crs path = fileInfo.filePath() baseName = fileInfo.baseName() layer = QgsRasterLayer(path, baseName) self.image = layer.previewAsImage(QSize(layer.width(), layer.height())) s.setValue("/Projections/defaultBehavior", oldValidation) else: reader = QImageReader(filepath) self.image = reader.read() self.repaint() def clone(self): layer = FreehandRasterGeoreferencerLayer(self.plugin, self.filepath, self.title, self.screenExtent) layer.center = self.center layer.rotation = self.rotation layer.xScale = self.xScale layer.yScale = self.yScale layer.commitTransformParameters() return layer def getAbsoluteFilepath(self): if not os.path.isabs(self.filepath): # relative to QGS file qgsPath = QgsProject.instance().fileName() qgsFolder, _ = os.path.split(qgsPath) filepath = os.path.join(qgsFolder, self.filepath) else: filepath = self.filepath return filepath def extent(self): self.initializeLayer() if not self.initialized: qDebug("Not Initialized") return QgsRectangle(0, 0, 1, 1) if self._extent: return self._extent topLeft, topRight, bottomRight, bottomLeft = self.cornerCoordinates() left = min(topLeft.x(), topRight.x(), bottomRight.x(), bottomLeft.x()) right = max(topLeft.x(), topRight.x(), bottomRight.x(), bottomLeft.x()) top = max(topLeft.y(), topRight.y(), bottomRight.y(), bottomLeft.y()) bottom = min(topLeft.y(), topRight.y(), bottomRight.y(), bottomLeft.y()) # recenter + create rectangle self._extent = QgsRectangle(left, bottom, right, top) return self._extent def cornerCoordinates(self): return self.transformedCornerCoordinates(self.center, self.rotation, self.xScale, self.yScale) def transformedCornerCoordinates(self, center, rotation, xScale, yScale): # scale topLeft = QgsPointXY(-self.image.width() / 2.0 * xScale, self.image.height() / 2.0 * yScale) topRight = QgsPointXY(self.image.width() / 2.0 * xScale, self.image.height() / 2.0 * yScale) bottomLeft = QgsPointXY(-self.image.width() / 2.0 * xScale, - self.image.height() / 2.0 * yScale) bottomRight = QgsPointXY(self.image.width() / 2.0 * xScale, - self.image.height() / 2.0 * yScale) # rotate # minus sign because rotation is CW in this class and Qt) rotationRad = -rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) topLeft = self._rotate(topLeft, cosRot, sinRot) topRight = self._rotate(topRight, cosRot, sinRot) bottomRight = self._rotate(bottomRight, cosRot, sinRot) bottomLeft = self._rotate(bottomLeft, cosRot, sinRot) topLeft.set(topLeft.x() + center.x(), topLeft.y() + center.y()) topRight.set(topRight.x() + center.x(), topRight.y() + center.y()) bottomRight.set(bottomRight.x() + center.x(), bottomRight.y() + center.y()) bottomLeft.set(bottomLeft.x() + center.x(), bottomLeft.y() + center.y()) return (topLeft, topRight, bottomRight, bottomLeft) def transformedCornerCoordinatesFromPoint(self, startPoint, rotation, xScale, yScale): # startPoint is a fixed point for this new movement (rotation and # scale) # rotation is the global rotation of the image # xScale is the new xScale factor to be multiplied by self.xScale # idem for yScale # Calculate the coordinate of the center in a startPoint origin # coordinate system and apply scales dX = (self.center.x() - startPoint.x()) * xScale dY = (self.center.y() - startPoint.y()) * yScale # Half width and half height in the current transformation hW = (self.image.width() / 2.0) * self.xScale * xScale hH = (self.image.height() / 2.0) * self.yScale * yScale # Actual rectangle coordinates : pt1 = QgsPointXY(-hW, hH) pt2 = QgsPointXY(hW, hH) pt3 = QgsPointXY(hW, -hH) pt4 = QgsPointXY(-hW, -hH) # Actual rotation from the center # minus sign because rotation is CW in this class and Qt) rotationRad = -self.rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) pt1 = self._rotate(pt1, cosRot, sinRot) pt2 = self._rotate(pt2, cosRot, sinRot) pt3 = self._rotate(pt3, cosRot, sinRot) pt4 = self._rotate(pt4, cosRot, sinRot) # Second transformation # displacement of the origin pt1 = QgsPointXY(pt1.x() + dX, pt1.y() + dY) pt2 = QgsPointXY(pt2.x() + dX, pt2.y() + dY) pt3 = QgsPointXY(pt3.x() + dX, pt3.y() + dY) pt4 = QgsPointXY(pt4.x() + dX, pt4.y() + dY) # Rotation # minus sign because rotation is CW in this class and Qt) rotationRad = -rotation * math.pi / 180 cosRot = math.cos(rotationRad) sinRot = math.sin(rotationRad) pt1 = self._rotate(pt1, cosRot, sinRot) pt2 = self._rotate(pt2, cosRot, sinRot) pt3 = self._rotate(pt3, cosRot, sinRot) pt4 = self._rotate(pt4, cosRot, sinRot) # translate to startPoint pt1 = QgsPointXY(pt1.x() + startPoint.x(), pt1.y() + startPoint.y()) pt2 = QgsPointXY(pt2.x() + startPoint.x(), pt2.y() + startPoint.y()) pt3 = QgsPointXY(pt3.x() + startPoint.x(), pt3.y() + startPoint.y()) pt4 = QgsPointXY(pt4.x() + startPoint.x(), pt4.y() + startPoint.y()) return (pt1, pt2, pt3, pt4) def moveCenterFromPointRotate(self, startPoint, rotation, xScale, yScale): cornerPoints = self.transformedCornerCoordinatesFromPoint( startPoint, rotation, xScale, yScale) self.center = QgsPointXY((cornerPoints[0].x( ) + cornerPoints[2].x()) / 2, (cornerPoints[0].y() + cornerPoints[2].y()) / 2) def _rotate(self, point, cosRot, sinRot): return QgsPointXY(point.x() * cosRot - point.y() * sinRot, point.x() * sinRot + point.y() * cosRot) def createMapRenderer(self, rendererContext): return FreehandRasterGeoreferencerLayerRenderer(self, rendererContext) def setBlendModeByName(self, modeName): self.blendModeName = modeName blendMode = getattr(QPainter, "CompositionMode_" + modeName, 0) self.setBlendMode(blendMode) self.setCustomProperty("blendMode", modeName) def setTransparency(self, transparency): self.transparency = transparency self.setCustomProperty("transparency", transparency) def draw(self, renderContext): if renderContext.extent().isEmpty(): qDebug("Drawing is skipped because map extent is empty.") return True self.initializeLayer() if not self.initialized: qDebug("Drawing is skipped because nothing to draw.") return True painter = renderContext.painter() painter.save() self.prepareStyle(painter) self.drawRaster(renderContext) painter.restore() return True def drawRaster(self, renderContext): painter = renderContext.painter() self.map2pixel = renderContext.mapToPixel() scaleX = self.xScale / self.map2pixel.mapUnitsPerPixel() scaleY = self.yScale / self.map2pixel.mapUnitsPerPixel() rect = QRectF(QPointF(-self.image.width() / 2.0, - self.image.height() / 2.0), QPointF(self.image.width() / 2.0, self.image.height() / 2.0)) mapCenter = self.map2pixel.transform(self.center) # draw the image on the map canvas painter.translate(QPoint(round(mapCenter.x()), round(mapCenter.y()))) painter.rotate(self.rotation) painter.scale(scaleX, scaleY) painter.drawImage(rect, self.image) painter.setBrush(Qt.NoBrush) painter.setPen(QColor(0, 0, 0)) painter.drawRect(rect) def prepareStyle(self, painter): painter.setOpacity(1.0 - self.transparency / 100.0) def readXml(self, node, context): self.readCustomProperties(node) self.title = self.customProperty("title", "") self.filepath = self.customProperty("filepath", "") self.xScale = float(self.customProperty("xScale", 1.0)) self.yScale = float(self.customProperty("yScale", 1.0)) self.rotation = float(self.customProperty("rotation", 0.0)) xCenter = float(self.customProperty("xCenter", 0.0)) yCenter = float(self.customProperty("yCenter", 0.0)) self.center = QgsPointXY(xCenter, yCenter) self.setTransparency(int(self.customProperty( "transparency", LayerDefaultSettings.TRANSPARENCY))) self.setBlendModeByName(self.customProperty( "blendMode", LayerDefaultSettings.BLEND_MODE)) return True def writeXml(self, node, doc, context): element = node.toElement() self.writeCustomProperties(node, doc) element.setAttribute("type", "plugin") element.setAttribute( "name", FreehandRasterGeoreferencerLayer.LAYER_TYPE) return True def metadata(self): lines = [] fmt = "%s:\t%s" lines.append(fmt % (self.tr("Title"), self.title)) filepath = self.getAbsoluteFilepath() filepath = os.path.normpath(filepath) lines.append(fmt % (self.tr("Path"), filepath)) lines.append(fmt % (self.tr("Image Width"), str(self.image.width()))) lines.append(fmt % (self.tr("Image Height"), str(self.image.height()))) lines.append(fmt % (self.tr("Rotation (CW)"), str(self.rotation))) lines.append(fmt % (self.tr("X center"), str(self.center.x()))) lines.append(fmt % (self.tr("Y center"), str(self.center.y()))) lines.append(fmt % (self.tr("X scale"), str(self.xScale))) lines.append(fmt % (self.tr("Y scale"), str(self.yScale))) return "\n".join(lines) def log(self, msg): qDebug(msg) def dump(self, detail=False, bbox=None): pass def showStatusMessage(self, msg, timeout): self.iface.mainWindow().statusBar().showMessage(msg, timeout) def showBarMessage(self, title, text, level, duration): self.iface.messageBar().pushMessage(title, text, level, duration) def transparencyChanged(self, val): QgsProject.instance().setDirty(True) self.setTransparency(val) self.repaintRequested.emit()