[Qgis-developer] How do you convert a bounding box into the canvas CRS?

Rudi Thiede rudi at linfiniti.com
Thu Mar 1 05:27:56 EST 2012

I need to convert the pixel coordinates of a bounding box to the same CRS
being used by an existing layer. Here's the relevant code so far:

    # First, get the layer-coords version of the bounding box:
    def pixelToCrsBox(self, theClickBox, theCanvas, theLayer):
        Takes a bbox in pixel coords, converts it to a bbox in layer coords.

            The bbox that needs to be converted.
            The current canvas.
            The current layer.
            The converted bbox.
        # converts from screen to map canvas crs
        myMapToPixel = theCanvas.getCoordinateTransform()
        myX1 = theClickBox.xMinimum()
        myY1 = theClickBox.yMinimum()
        myPoint1 = myMapToPixel.toMapCoordinates(myX1, myY1)

        myX2 = theClickBox.xMaximum()
        myY2 = theClickBox.yMaximum()
        myPoint2 = myMapToPixel.toMapCoordinates(myX2, myY2)

        myRectangle = QgsRectangle(myPoint1, myPoint2)

        # converts the click box from canvas crs to the layer's CRS
        myCanvasCrs = theCanvas.mapRenderer().destinationCrs()
        myLayerCrs = theLayer.crs()
        myTransform = QgsCoordinateTransform(myCanvasCrs, myLayerCrs)
        myExtent = myTransform.transform(myRectangle)
        return myExtent

    # Next, get the first feature in the layer using the extents computed
    # (returned as myExtent, but fed to this function as theExtent).
    def getFirstFeature(self, theLayer, theExtent):
        Gets the first feature within the bbox in the active layer.

            The current layer.
            The converted bbox.
            A feature.
            Exception if data could not be loaded.

        myProvider = theLayer.dataProvider()
        if myProvider is None:
            msg = ('Could not obtain data provider from '
               'layer "%s"' % theLayer.source())
            raise Exception(msg)

        #myLayerExtent = theLayer.extent()
        myAttributes = myProvider.attributeIndexes()
        myFetchGeometryFlag = True
        myUseIntersectFlag = True

        mySelection = myProvider.select(myAttributes,
                      theExtent, myFetchGeometryFlag, myUseIntersectFlag)
        print ('SELECTED: %s' % mySelection)
        myFeature = myProvider.nextFeature(mySelection)
        return myFeature

To test this, I have these functions:

    def prepareTestCanvas(self):
        Sets parameters for a test canvas.
        setCanvasCrs(4326, True)

    def testPixelToCrsBox(self):
        Tests that a bbox in pixel coords is converted to map coords
        myPoint = QgsPoint(40, 15)
        myBox = self.bucketFill.getClickBbox(myPoint)
        myLayer = self.bucketFill.getActiveVectorLayer()
        myRectangle = self.bucketFill.pixelToCrsBox(myBox, canvas, myLayer)
        myExpectedBox = QgsRectangle(106.758705784, -6.13591899755,
                                     106.761696484, -6.1329282975)
        myMessage = ('Bounding box was incorrect.\n'
            'Received values %s\n'
            'Expected values %s' % (
            str('%s, %s, %s, %s' % (
                myRectangle.xMinimum(), myRectangle.yMinimum(),
                myRectangle.xMaximum(), myRectangle.yMaximum()
            str('%s, %s, %s, %s' % (
                myExpectedBox.xMinimum(), myExpectedBox.yMinimum(),
                myExpectedBox.xMaximum(), myExpectedBox.yMaximum()
        assert (
            round(myRectangle.xMinimum(), 9) ==
            round(myExpectedBox.xMinimum(), 9) and
            round(myRectangle.xMaximum(), 9) ==
            round(myExpectedBox.xMaximum(), 9) and
            round(myRectangle.yMinimum(), 9) ==
            round(myExpectedBox.yMinimum(), 9) and
            round(myRectangle.yMaximum(), 9) ==
            round(myExpectedBox.yMaximum(), 9)), myMessage

    def testGetFirstFeature(self):
        Tests that a feature is returned.
        myLayer = self.bucketFill.getActiveVectorLayer()
        myTestBox = QgsRectangle(106.758705784, -6.13591899755,
                                 106.761696484, -6.1329282975)
        myFeature = self.bucketFill.getFirstFeature(myLayer, myTestBox)
        print myFeature
        myMessage = ('Returned object was not a feature.')
        assert myFeature.type() == QgsFeature, myMessage

However, the coordinates are not in the right place when they are returned
in the layer CRS. They're supposed to hit the feature I'm trying to select,
but they don't.

The coordinates that get returned (same as those in the test) are way off
base, and it shouldn't be possible to click there if the canvas is zoomed
to the layer extents (there are no other features in the test layer).

So my theory is that the coordinates are transformed incorrectly. What am I
doing wrong?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/qgis-developer/attachments/20120301/bc0663a5/attachment.html

More information about the Qgis-developer mailing list