Using a map tool to draw polygons or lines on the canvas

In this recipe, we'll create a tool to draw polygons on the canvas. This tool is an important tool because it opens the doors to even more advanced tools. Once you have a polygon on the canvas, you can do all sorts of operations that involve querying and geometry.

Getting ready

We will use the application framework from the Adding standard map tools to the canvas recipe, so complete that recipe. We will extend that application with a new tool. The complete version of this application is available in the code samples provided with this book.

How to do it...

We will add a new tool to the toolbar and also create a class that describes our polygon tool, as follows:

  1. First, we define our polygon tool's button in the actions portion of our application. Place this line after the QAction("Pan") method:
    actionPoly = QAction("Polygon", self)
    
  2. In the next section, we make sure that when we click on the button, it stays selected:
    actionPoly.setCheckable(True)
    
  3. In the section after that, we define the method used when the button is triggered:
    self.connect(actionPoly, SIGNAL("triggered()"), self.poly)
    
  4. Now, we add the button to the toolbar along with the other buttons:
    self.toolbar.addAction(actionPoly)
    
  5. Then, we link the application to our specialized tool class:
    self.toolPoly = PolyMapTool(self.canvas)
    self.toolPoly.setAction(actionPoly)
    
  6. We set the point tool to be selected when the application loads:
    self.poly()
    
  7. Now, we define the method in the main application class for our tool:
    def poly(self):
    self.canvas.setMapTool(self.toolPoly)
    

Now, we create a class that describes the type of tool we have and the output it provides. The output is a point on the canvas defined in the canvasPressEvent method, which receives the button-click event and the showPoly method. We will inherit from a generic tool in order to create points called the QgsMapToolEmitPoint; we will also use an object called QgsRubberBand for handling polygons:

classPolyMapTool(QgsMapToolEmitPoint):
def __init__(self, canvas):
self.canvas = canvas
QgsMapToolEmitPoint.__init__(self, self.canvas)
self.rubberband = QgsRubberBand(self.canvas, QGis.Polygon)
self.rubberband.setColor(Qt.red)
self.rubberband.setWidth(1)
self.point = None
self.points = []

defcanvasPressEvent(self, e):
self.point = self.toMapCoordinates(e.pos())
m = QgsVertexMarker(self.canvas)
m.setCenter(self.point)
m.setColor(QColor(0,255,0))
m.setIconSize(5)
m.setIconType(QgsVertexMarker.ICON_BOX)
m.setPenWidth(3) 
self.points.append(self.point)
self.isEmittingPoint = True
self.showPoly()

defshowPoly(self):
self.rubberband.reset(QGis.Polygon)
for point in self.points[:-1]:
self.rubberband.addPoint(point, False)
self.rubberband.addPoint(self.points[-1], True)
self.rubberband.show()

How it works...

All the settings for the polygon are contained in the custom class. There is a key property, called EmittingPoint, which we use to detect whether we are still adding points to the polygon. This value starts out as false. If this is the case, we reset our polygon object and begin drawing a new one. The following screenshot shows a polygon drawn with this tool on a map:

How it works...
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset