Exemplo n.º 1
0
    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()))
Exemplo n.º 2
0
    def getBlockRecAndItemFromPointInRaster(self, layer, p):
        pt = p  # QgsCoordinateTransform(QgsProject.instance().crs(),layer.crs(),QgsProject.instance()).transform(p)
        dp = layer.dataProvider()
        finalExtent = dp.extent()

        # Calculate the row / column where the point falls
        xres = layer.rasterUnitsPerPixelX()
        yres = layer.rasterUnitsPerPixelY()

        from math import floor
        col = abs(floor((pt.x() - finalExtent.xMinimum()) / xres))
        row = abs(floor((finalExtent.yMaximum() - pt.y()) / yres))

        xMin = finalExtent.xMinimum() + col * xres
        xMax = xMin + xres
        yMax = finalExtent.yMaximum() - row * yres
        yMin = yMax - yres
        pixelExtent = QgsRectangle(xMin, yMin, xMax, yMax)
        # 1 is referring to band 1
        if not (self.LAYER is None
                or self.BLOCK is None) and layer == self.LAYER:
            block = self.BLOCK
        else:
            block = dp.block(1, finalExtent, layer.width(), layer.height())
            self.BLOCK = block
            self.LAYER = layer

        del dp

        if pixelExtent.contains(pt):
            return block, pixelExtent, row, col
        else:
            return False, False, False, False
Exemplo n.º 3
0
    def testUnion(self):
        rect1 = QgsRectangle( 0.0, 0.0, 5.0, 5.0)
        rect2 = QgsRectangle( 2.0, 2.0, 7.0, 7.0)
        pnt1 = QgsPoint(6.0, 2.0)

        rect1.combineExtentWith(rect2)
        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect1.contains(rect2)))
        assert rect1.contains(rect2), myMessage

        print rect1.toString()
        assert rect1 == QgsRectangle(0.0, 0.0, 7.0, 7.0), "Wrong combine with rectangle result"

        rect1 = QgsRectangle( 0.0, 0.0, 5.0, 5.0)
        rect1.combineExtentWith(6.0, 2.0)
        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect1.contains(pnt1)))
        assert rect1.contains(pnt1), myMessage

        myExpectedResult = QgsRectangle(0.0, 0.0, 6.0, 5.0).toString()
        myResult = rect1.toString()
        myMessage = ('Expected: %s\nGot: %s\n' %
                      (myExpectedResult, myResult))
        self.assertEquals(myResult, myExpectedResult, myMessage)

        rect1 = QgsRectangle( 0.0, 0.0, 5.0, 5.0)
        rect1.unionRect(rect2)
        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect1.contains(rect2)))
        assert rect1.contains(rect2), myMessage

        assert rect1 == QgsRectangle(0.0, 0.0, 7.0, 7.0), "Wrong union result"
Exemplo n.º 4
0
    def testUnion(self):
        rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0)
        rect2 = QgsRectangle(2.0, 2.0, 7.0, 7.0)
        pnt1 = QgsPointXY(6.0, 2.0)

        rect1.combineExtentWith(rect2)
        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect1.contains(rect2)))
        assert rect1.contains(rect2), myMessage

        print((rect1.toString()))
        assert rect1 == QgsRectangle(
            0.0, 0.0, 7.0, 7.0), 'Wrong combine with rectangle result'

        rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0)
        rect1.combineExtentWith(6.0, 2.0)
        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect1.contains(pnt1)))
        assert rect1.contains(pnt1), myMessage

        myExpectedResult = QgsRectangle(0.0, 0.0, 6.0, 5.0).toString()
        myResult = rect1.toString()
        myMessage = ('Expected: %s\nGot: %s\n' % (myExpectedResult, myResult))
        self.assertEqual(myResult, myExpectedResult, myMessage)

        rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0)
        rect1.combineExtentWith(rect2)
        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect1.contains(rect2)))
        assert rect1.contains(rect2), myMessage

        assert rect1 == QgsRectangle(0.0, 0.0, 7.0, 7.0), "Wrong union result"
Exemplo n.º 5
0
    def testUnion(self):
        rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0)
        rect2 = QgsRectangle(2.0, 2.0, 7.0, 7.0)
        pnt1 = QgsPointXY(6.0, 2.0)

        rect1.combineExtentWith(rect2)
        self.assertTrue(rect1.contains(rect2))

        self.assertEqual(rect1, QgsRectangle(0.0, 0.0, 7.0, 7.0))

        rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0)
        rect1.combineExtentWith(6.0, 2.0)
        self.assertTrue(rect1.contains(pnt1))

        self.assertEqual(rect1.toString(),
                         QgsRectangle(0.0, 0.0, 6.0, 5.0).toString())

        rect1 = QgsRectangle(0.0, 0.0, 5.0, 5.0)
        rect1.combineExtentWith(rect2)
        self.assertTrue(rect1.contains(rect2))

        self.assertEqual(rect1, QgsRectangle(0.0, 0.0, 7.0, 7.0))
Exemplo n.º 6
0
    def canvasReleaseEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()

        point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
        bbox = QgsRectangle(4999.99,4999.69,660000.06,1225000.12)

        if bbox.contains(point):
            os_ref = xy_to_osgb(point.x(), point.y(), 10)
            point_4326 = reproject_point_to_4326(self.canvas, point)
            QApplication.clipboard().setText(os_ref)
            msg = "Grid Ref: {}\n\nLong,Lat: {:.2f}, {:.2f}\n\nCopied to clipboard".format(os_ref, point_4326.x(), point_4326.y())
            QMessageBox.information(None, "OS Grid Reference", msg)
        else:
            QMessageBox.information(None, "OS Grid Reference", "Point out of bounds")
Exemplo n.º 7
0
    def updatecanvasfromgps(self, position, gpsinfo):
        # Recenter map if we go outside of the 95% of the area
        if not self.lastgpsposition == position:
            self.lastposition = position
            rect = QgsRectangle(position, position)
            extentlimt = QgsRectangle(self.canvas.extent())
            extentlimt.scale(0.95)

            if not extentlimt.contains(position):
                self.canvas.setExtent(rect)
                self.canvas.refresh()

        self.marker.show()
        self.marker.setCenter(position)
        self.gpslabel.setText("GPS: PDOP {}   HDOP {}    VDOP {}".format(
            gpsinfo.pdop, gpsinfo.hdop, gpsinfo.vdop))
Exemplo n.º 8
0
    def updatecanvasfromgps(self, position, gpsinfo):
        # Recenter map if we go outside of the 95% of the area
        if not self.lastgpsposition == position:
            self.lastposition = position
            rect = QgsRectangle(position, position)
            extentlimt = QgsRectangle(self.canvas.extent())
            extentlimt.scale(0.95)

            if not extentlimt.contains(position):
                self.canvas.setExtent(rect)
                self.canvas.refresh()

        self.marker.show()
        self.marker.setCenter(position)
        self.gpslabel.setText("GPS: PDOP {}   HDOP {}    VDOP {}".format(gpsinfo.pdop,
                                                                        gpsinfo.hdop,
                                                                        gpsinfo.vdop))
Exemplo n.º 9
0
    def gps_update_canvas(self, position, gpsinfo):
        # Recenter map if we go outside of the 95% of the area
        if self.gpslogging.logging:
            self.gpsband.addPoint(position)
            self.gpsband.show()

        if roam.config.settings.get('gpscenter', True):
            if not self.lastgpsposition == position:
                self.lastposition = position
                rect = QgsRectangle(position, position)
                extentlimt = QgsRectangle(self.canvas.extent())
                extentlimt.scale(0.95)

                if not extentlimt.contains(position):
                    self.zoom_to_location(position)

        self.marker.show()
        self.marker.setCenter(position)
Exemplo n.º 10
0
    def gps_update_canvas(self, position, gpsinfo):
        # Recenter map if we go outside of the 95% of the area
        if self.gpslogging.logging:
            self.gpsband.addPoint(position)
            self.gpsband.show()

        if roam.config.settings.get('gpscenter', True):
            if not self.lastgpsposition == position:
                self.lastposition = position
                rect = QgsRectangle(position, position)
                extentlimt = QgsRectangle(self.canvas.extent())
                extentlimt.scale(0.95)

                if not extentlimt.contains(position):
                    self.zoom_to_location(position)

        self.marker.show()
        self.marker.setCenter(position)
Exemplo n.º 11
0
    def canvasReleaseEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        point = self.canvas.getCoordinateTransform().toMapCoordinates(x, y)
        bbox = QgsRectangle(4999.99, 4999.69, 660000.06, 1225000.12)

        if bbox.contains(point):
            os_ref = xy_to_osgb(point.x(), point.y(), self.precision)
            point_4326 = reproject_point_to_4326(self.canvas, point)

            msg = "Grid Ref: {}\n\nLong,Lat: {:.2f}, {:.2f}\n".format(
                os_ref, point_4326.x(), point_4326.y())
            if self.clipboard_enable:
                QApplication.clipboard().setText(os_ref)
                msg += "\nCopied to clipboard"

            QMessageBox.information(None, "OS Grid Reference", msg)
        else:
            QMessageBox.information(None, "OS Grid Reference",
                                    "Point out of bounds")
Exemplo n.º 12
0
def xform(extent, srcCRS, destCRS):
    if srcCRS == destCRS:
        return extent  # nothing to do

    # cut down the extent so it's not too big

    # clamped to the projection's valid area (usually small)
    projectionClampedExtent = clampToProjectionExtent(extent, srcCRS)

    # clamped to the world (might not work in some projections)
    worldClampedExtent = clampToWorld(extent, srcCRS)

    # xform the two extents to the dest CRS

    transform = QgsCoordinateTransform(srcCRS, destCRS, QgsProject.instance())

    xformed_projectionClamped = QgsRectangle()  # null rect
    if not projectionClampedExtent.isNull():
        xformed_projectionClamped = transform.transformBoundingBox(projectionClampedExtent)

    xformed_worldClamped = QgsRectangle()  # null rect
    if not worldClampedExtent.isNull():
        xformed_worldClamped = transform.transformBoundingBox(worldClampedExtent)


    # make final choice of what to use
    # we WANT to use the world one, but sometimes cannot

    # indicates everything is ok -- likely no projection blowing up
    if xformed_worldClamped.contains(xformed_projectionClamped):
        return xformed_worldClamped  # likely good

    # if one is null, return the other
    if xformed_projectionClamped.isNull():
        return xformed_worldClamped

    if xformed_worldClamped.isNull():
        return xformed_projectionClamped

    # clamp to the destination CRS (last resort to try to get something valid)
    return clampToProjectionExtent(xformed_worldClamped, destCRS)
Exemplo n.º 13
0
    def locationChanged(self, lat, lng, yaw, angle):
        transform = self.coordinatetransform()
        point = transform.transform(float(lng), float(lat))
        self.marker.setCenter(point)
        yaw = float(yaw)
        self.marker.setAngle(angle)
        self.marker.setYaw(yaw)
        self.marker.setTracking(self.viewer.tracking)

        if self.marker.tracking:
            rect = QgsRectangle(point, point)
            extentlimt = QgsRectangle(self.canvas.extent())
            extentlimt.scale(0.95)

            if not extentlimt.contains(point):
                self.canvas.setExtent(rect)
                self.canvas.refresh()

        # Clear old features
        self.viewer.clear_features()
        self.load_layer_features(point)
Exemplo n.º 14
0
    def locationChanged(self, lat, lng, yaw, angle):
        transform = self.coordinatetransform()
        point = transform.transform(float(lng), float(lat))
        self.marker.setCenter(point)
        yaw = float(yaw)
        self.marker.setAngle(angle)
        self.marker.setYaw(yaw)
        self.marker.setTracking(self.viewer.tracking)

        if self.marker.tracking:
            rect = QgsRectangle(point, point)
            extentlimt = QgsRectangle(self.canvas.extent())
            extentlimt.scale(0.95)

            if not extentlimt.contains(point):
                self.canvas.setExtent(rect)
                self.canvas.refresh()

        # Clear old features
        self.viewer.clear_features()
        self.load_layer_features(point)
Exemplo n.º 15
0
    def gps_update_canvas(self, position, gpsinfo):
        """
        Updates the map canvas based on the GPS position.  By default if the GPS is outside the canvas
        extent the canvas will move to center on the GPS.  Can be turned off in settings.
        :param postion: The current GPS position.
        :param gpsinfo: The extra GPS information
        """
        # Recenter map if we go outside of the 95% of the area
        if self.gpslogging.logging:
            self.gpsband.addPoint(position)
            self.gpsband.show()

        if roam.config.settings.get('gpscenter', True):
            if not self.lastgpsposition == position:
                self.lastgpsposition = position
                rect = QgsRectangle(position, position)
                extentlimt = QgsRectangle(self.canvas.extent())
                extentlimt.scale(0.95)

                if not extentlimt.contains(position):
                    self.zoom_to_location(position)

        self.gpsMarker.show()
        self.gpsMarker.setCenter(position, gpsinfo)
Exemplo n.º 16
0
    def gps_update_canvas(self, position, gpsinfo):
        """
        Updates the map canvas based on the GPS position.  By default if the GPS is outside the canvas
        extent the canvas will move to center on the GPS.  Can be turned off in settings.
        :param postion: The current GPS position.
        :param gpsinfo: The extra GPS information
        """
        # Recenter map if we go outside of the 95% of the area
        if self.gpslogging.logging:
            self.gpsband.addPoint(position)
            self.gpsband.show()

        if roam.config.settings.get('gpscenter', True):
            if not self.lastgpsposition == position:
                self.lastposition = position
                rect = QgsRectangle(position, position)
                extentlimt = QgsRectangle(self.canvas.extent())
                extentlimt.scale(0.95)

                if not extentlimt.contains(position):
                    self.zoom_to_location(position)

        self.marker.show()
        self.marker.setCenter(position, gpsinfo)
Exemplo n.º 17
0
class GSIElevTileProvider:

  def __init__(self, dest_wkt):
    self.dest_wkt = dest_wkt

    # crs transformer, which aims to calculate bbox in EPSG:3857
    self.crs3857 = QgsCoordinateReferenceSystem(3857)
    self.dest_crs = QgsCoordinateReferenceSystem()
    if not self.dest_crs.createFromWkt(dest_wkt):
      logMessage("Failed to create CRS from WKT: {0}".format(dest_wkt))
    self.transform = QgsCoordinateTransform(self.dest_crs, self.crs3857)

    # approximate bbox of this data
    self.boundingbox = QgsRectangle(13667807, 2320477, 17230031, 5713298)

    self.downloader = Downloader()
    self.downloader.userAgent = "QGIS/{0} Qgis2threejs GSIElevTileProvider".format(QGis.QGIS_VERSION)  # not written since QGIS 2.2
    self.downloader.DEFAULT_CACHE_EXPIRATION = QSettings().value("/qgis/defaultTileExpiry", 24, type=int)

    self.driver = gdal.GetDriverByName("MEM")
    self.last_dataset = None

  def name(self):
    return "GSI Elevation Tile"

  def read(self, width, height, extent):
    # calculate bounding box in EPSG:3857
    geometry = extent.geometry()
    geometry.transform(self.transform)
    merc_rect = geometry.boundingBox()

    # if the bounding box doesn't intersect with the bounding box of this data, return a list filled with nodata value
    if not self.boundingbox.intersects(merc_rect):
      return [NODATA_VALUE] * width * height

    # get tiles
    over_smpl = 1
    segments_x = 1 if width == 1 else width - 1
    res = extent.width() / segments_x / over_smpl
    ds = self.getDataset(merc_rect.xMinimum(), merc_rect.yMinimum(), merc_rect.xMaximum(), merc_rect.yMaximum(), res)

    geotransform = extent.geotransform(width, height)
    return self._read(ds, width, height, geotransform)

  def readValue(self, x, y):
    """Get value at the position using 1px * 1px memory raster. The value is calculated using a tile of max zoom level"""
    # coordinate transformation into EPSG:3857
    pt = self.transform.transform(QgsPoint(x, y))

    # if the point is not within the bounding box of this data, return nodata value
    if not self.boundingbox.contains(pt):
      return NODATA_VALUE

    res = 0.1
    hres = res / 2
    ds = self.getDataset(pt.x() - hres, pt.y() - hres, pt.x() + hres, pt.y() + hres, res)

    geotransform = [x - hres, res, 0, y + hres, 0, -res]
    return self._read(ds, 1, 1, geotransform)[0]

  def _read(self, ds, width, height, geotransform):
    # create a memory dataset
    warped_ds = self.driver.Create("", width, height, 1, gdal.GDT_Float32)
    warped_ds.SetProjection(self.dest_wkt)
    warped_ds.SetGeoTransform(geotransform)

    # reproject image
    gdal.ReprojectImage(ds, warped_ds, None, None, gdal.GRA_Bilinear)

    # load values into an array
    band = warped_ds.GetRasterBand(1)
    fs = "f" * width * height
    return struct.unpack(fs, band.ReadRaster(0, 0, width, height, buf_type=gdal.GDT_Float32))

  def getDataset(self, xmin, ymin, xmax, ymax, mapUnitsPerPixel):
    # calculate zoom level
    mpp1 = TSIZE1 / TILE_SIZE
    zoom = int(math.ceil(math.log(mpp1 / mapUnitsPerPixel, 2) + 1))
    zoom = max(0, min(zoom, ZMAX))

    # calculate tile range (yOrigin is top)
    size = TSIZE1 / 2 ** (zoom - 1)
    matrixSize = 2 ** zoom
    ulx = max(0, int((xmin + TSIZE1) / size))
    uly = max(0, int((TSIZE1 - ymax) / size))
    lrx = min(int((xmax + TSIZE1) / size), matrixSize - 1)
    lry = min(int((TSIZE1 - ymin) / size), matrixSize - 1)

    cols = lrx - ulx + 1
    rows = lry - uly + 1

    # download count limit
    if cols * rows > 128:
      logMessage("Number of tiles to fetch is too large!")
      width = height = 1
      return self.driver.Create("", width, height, 1, gdal.GDT_Float32, [])

    if self.last_dataset and self.last_dataset[0] == [zoom, ulx, uly, lrx, lry]:    # if same as last tile set, return cached dataset
      return self.last_dataset[1]

    urltmpl = "http://cyberjapandata.gsi.go.jp/xyz/dem/{z}/{x}/{y}.txt"
    #urltmpl = "http://localhost/xyz/dem/{z}/{x}/{y}.txt"
    tiles = self.fetchFiles(urltmpl, zoom, ulx, uly, lrx, lry)

    # create a memory dataset
    width = cols * TILE_SIZE
    height = rows * TILE_SIZE
    res = size / TILE_SIZE
    geotransform = [ulx * size - TSIZE1, res, 0, TSIZE1 - uly * size, 0, -res]

    #mem_driver = gdal.GetDriverByName("GTiff")
    #ds = mem_driver.Create("D:/fetched_tile.tif", width, height, 1, gdal.GDT_Float32, [])

    ds = self.driver.Create("", width, height, 1, gdal.GDT_Float32, [])
    ds.SetProjection(str(self.crs3857.toWkt()))
    ds.SetGeoTransform(geotransform)

    band = ds.GetRasterBand(1)
    for i, tile in enumerate(tiles):
      if tile:
        col = i % cols
        row = i / cols
        band.WriteRaster(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile)

    ds.FlushCache()

    self.last_dataset = [[zoom, ulx, uly, lrx, lry], ds]   # cache dataset
    return ds

  def fetchFiles(self, urltmpl, zoom, xmin, ymin, xmax, ymax):
    downloadTimeout = 60

    urls = []
    for y in range(ymin, ymax + 1):
      for x in range(xmin, xmax + 1):
        urls.append(urltmpl.replace("{x}", str(x)).replace("{y}", str(y)).replace("{z}", str(zoom)))
    files = self.downloader.fetchFiles(urls, downloadTimeout)

    for url in urls:
      data = files[url]
      if data:
        yield numpy.fromstring(data.replace("e", str(NODATA_VALUE)).replace("\n", ","), dtype=numpy.float32, sep=",").tostring()   # to byte array
      else:
        array = numpy.empty(TILE_SIZE * TILE_SIZE, dtype=numpy.float32)
        array.fill(NODATA_VALUE)
        yield array.tostring()
Exemplo n.º 18
0
    def testContains(self):
        rect1 = QgsRectangle( 0.0, 0.0, 5.0, 5.0)
        rect2 = QgsRectangle( 2.0, 2.0, 7.0, 7.0)
        pnt1 = QgsPoint(4.0, 4.0)
        pnt2 = QgsPoint(6.0, 2.0)

        rect3 = rect1.intersect(rect2)

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect1.contains(rect3)))
        assert rect1.contains(rect3), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect2.contains(rect3)))
        assert rect2.contains(rect3), myMessage

        # test for point
        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect1.contains(pnt1)))
        assert rect1.contains(pnt1), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect2.contains(pnt1)))
        assert rect2.contains(pnt1), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect3.contains(pnt1)))
        assert rect3.contains(pnt1), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (False, rect1.contains(pnt2)))
        self.assertFalse(rect1.contains(pnt2), myMessage)

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect2.contains(pnt2)))
        assert rect2.contains(pnt2), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (False, rect3.contains(pnt2)))
        self.assertFalse(rect3.contains(pnt2), myMessage)

        myMessage = ('Expected: %s\nGot: %s\n' %
                      (True, rect3.contains(pnt1)))
        self.assertTrue(rect3.contains(pnt1), myMessage)
Exemplo n.º 19
0
    def make_coco_dataset(self):
        layers = QgsProject.instance().mapLayers().values()
        vectorlayers = [layer for layer in layers if layer.type() == VectorLayer]
        rasterLayers = [layer for layer in layers if layer.type() == RasterLayer]

        vectorlayer = vectorlayers[self.dlg.vectorlayerselector.currentIndex()]
        rasterlayer = rasterLayers[self.dlg.rasterlayerselector.currentIndex()]

        img_size = int(self.dlg.imagesizeselector.currentText())
        scale_realworld = int(self.dlg.zoomlevel.currentText())
        buffer_size = int(self.dlg.buffersize.text()) / 100
        target_dir = self.dlg.dirselectline.text()
        dataset_description = str(self.dlg.datasetdescription.text())
        contributor = str(self.dlg.creatorname.text())
        url = str(self.dlg.url.text())
        version = str(self.dlg.datasetversion.text())
        license = str(self.dlg.licenseselector.currentText())

        # to implement
        scale_to_fit = self.dlg.scaletofit.isChecked()
        use_fieldcategory = bool(self.dlg.usecategoryfields.isChecked())
        categoryfield = self.dlg.categoryfields.currentText()


        QgsMessageLog.logMessage(str(scale_to_fit), "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage(str(use_fieldcategory), "cocotrainer", level=Qgis.Info)

        # prepare directories
        os.makedirs(os.path.join(target_dir, "train"), exist_ok=True)
        os.makedirs(os.path.join(target_dir, "val"), exist_ok=True)

        QgsMessageLog.logMessage("====================================", "cocotrainer", level=Qgis.Info)

        # TODO:
        #  - use field categories

        features_iterator = vectorlayer.getFeatures(QgsFeatureRequest().setFilterExpression('$area > 1'))

        features = [feature for feature in features_iterator]
        QgsMessageLog.logMessage("vector layer: " + vectorlayer.name(), "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage("Filtered polygons smaller than 1m2 from data", "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage("features: " + str(len(list(features))), "cocotrainer", level=Qgis.Info)

        options = QgsMapSettings()
        options.setLayers([rasterlayer])
        options.setOutputSize(QSize(int(img_size), int(img_size)))

        QgsMessageLog.logMessage(str(scale_realworld), "cocotrainer", level=Qgis.Info)
        QgsMessageLog.logMessage(str(img_size), "cocotrainer", level=Qgis.Info)

        date = datetime.now()

        cat_dict = {}
        if use_fieldcategory:
            categories = []
            # uniqueprovider = rasterlayer.dataProvider()
            fields = vectorlayer.fields()
            id = fields.indexFromName(categoryfield)
            uniquevalues = vectorlayer.uniqueValues(id)
            for i, val in enumerate(uniquevalues):
                categories.append({"supercategory": "object", "id": i, "name": str(val)})
                cat_dict[str(val)] = i
        else:
            categories = [{"supercategory": "object", "id": 0, "name": "CATEGORYNAME"}]
            cat_dict["CATEGORYNAME"] = 0

        coco_annotation = {
            "info": {
                "description": dataset_description,
                "url": url,
                "version": version,
                "year": int(date.strftime("%Y")),
                "contributor": contributor,
                "date_created": date.strftime("%d/%m/%y")
            },
            "licenses": [self.license_dict[license]],
            "images": [],
            "annotations": [],
            "categories": categories,
            # < -- Not in Captionsannotations
            "segment_info": []  # < -- Only in Panoptic annotations
        }

        bboxes, polygons = {}, {}
        for i, feature in enumerate(features):
            polygons[i] = feature.geometry()
            bboxes[i] = feature.geometry().boundingBox()

        if use_fieldcategory:
            cats = {}
            for i, feature in enumerate(features):
                cats[i] = str(feature[categoryfield])

        image_id = 0
        annotation_id = 0

        for i, feature in enumerate(features):
            self.dlg.progressBar.setValue((i / len(polygons) * 100))
            QgsMessageLog.logMessage("something is happening", "cocotrainer", level=Qgis.Info)
            geoms = feature.geometry()
            bbox = geoms.boundingBox()

            if scale_to_fit:
                xmax = bbox.xMaximum()
                ymax = bbox.yMaximum()
                ymin = bbox.yMinimum()
                xmin = bbox.xMinimum()

                diffx = xmax - xmin
                diffy = ymax - ymin
                xmax = xmax + (buffer_size * diffx)
                xmin = xmin - (buffer_size * diffx)
                ymax = ymax + (buffer_size * diffy)
                ymin = ymin - (buffer_size * diffy)

            else:
                midpoint = bbox.center()
                QgsMessageLog.logMessage("trying to log centerpoint", "cocotrainer", level=Qgis.Info)
                QgsMessageLog.logMessage(str(midpoint.x()), "cocotrainer", level=Qgis.Info)
                QgsMessageLog.logMessage(str(midpoint.y()), "cocotrainer", level=Qgis.Info)
                xmin = midpoint.x() - scale_realworld / 2
                xmax = midpoint.x() + scale_realworld / 2
                ymin = midpoint.y() - scale_realworld / 2
                ymax = midpoint.y() + scale_realworld / 2

            extent = QgsRectangle(xmin, ymin, xmax, ymax)

            fileid = "{}_{}_{}".format(xmin, ymin, scale_realworld)

            image = {
                "license": 0,
                "file_name": fileid + ".png",
                "coco_url": None,
                "height": img_size,
                "width": img_size,
                "date_captured": date.strftime("%d/%m/%y"),
                "flickr_url": None,
                "id": image_id
            }

            coco_annotation["images"].append(image)

            for j, geo in bboxes.items():
                if extent.contains(geo) or extent.intersects(geo):
                    points = polygons[j].asMultiPolygon()
                    xs = np.array([p.x() - xmin for p in points[0][0]])
                    ys = np.array([(ymax - ymin) - (p.y() - ymin) for p in points[0][0]])

                    xs *= (img_size / scale_realworld)
                    xs = np.round(xs)
                    xs = xs.astype(np.int32)

                    ys *= (img_size / scale_realworld)
                    ys = np.round(ys)
                    ys = ys.astype(np.int32)

                    ys[ys < 0] = 0
                    xs[xs < 0] = 0

                    polygon = [[int(p[0]), int(p[1])] for p in zip(xs, ys)]
                    flat_list = [item for sublist in polygon for item in sublist]
                    QgsMessageLog.logMessage(str(flat_list), "cocotrainer", level=Qgis.Info)

                    pixelposbbox = [int(np.min(xs)), (int(np.min(ys))), geo.width() * (img_size / scale_realworld),
                                    geo.height() * (img_size / scale_realworld)]
                    pixelposbbox = [number if number > 0 else 0 for number in pixelposbbox]

                    QgsMessageLog.logMessage(str([geo.xMinimum(), geo.yMaximum(), geo.width(), geo.height()]),
                                             "cocotrainer", level=Qgis.Info)
                    QgsMessageLog.logMessage(str(pixelposbbox), "cocotrainer", level=Qgis.Info)

                    annotation = {
                        "segmentation": [flat_list],  # format is [x1,y1,x2,y2]
                        "area": polygons[j].area(),
                        "iscrowd": 0,
                        "image_id": image_id,
                        "bbox": pixelposbbox,  # format is [top left x position, top left y position, width, height]
                        "category_id": cat_dict[cats[j]],
                        "id": annotation_id
                    }
                    annotation_id += 1
                    coco_annotation["annotations"].append(annotation)

            options.setExtent(extent)
            render = QgsMapRendererParallelJob(options)

            def finished():
                QgsMessageLog.logMessage("saving image to disk", "cocotrainer", level=Qgis.Info)
                fname = os.path.join(target_dir, 'train', "{}.png".format(fileid))
                img = render.renderedImage()
                if not img.save(fname, "png"):
                    print("Error saving image")

            render.finished.connect(finished)
            render.start()
            render.waitForFinished()
            image_id += 1

        QgsMessageLog.logMessage(str(coco_annotation), "cocotrainer", level=Qgis.Info)

        with open(os.path.join(target_dir, "annotation.json"), "w") as outfile:
            json.dump(coco_annotation, outfile)

        self.dlg.progressBar.setValue(100)
        self.dlg.finished_label.setText("parsed {} features".format(len(list(features))))
Exemplo n.º 20
0
class GSIElevTileProvider:
    def __init__(self, dest_wkt):
        self.dest_wkt = dest_wkt

        # crs transformer, which aims to calculate bbox in EPSG:3857
        self.crs3857 = QgsCoordinateReferenceSystem(3857)
        self.dest_crs = QgsCoordinateReferenceSystem()
        if not self.dest_crs.createFromWkt(dest_wkt):
            logMessage("Failed to create CRS from WKT: {0}".format(dest_wkt))
        self.transform = QgsCoordinateTransform(self.dest_crs, self.crs3857,
                                                QgsProject.instance())

        # approximate bbox of this data
        self.boundingbox = QgsRectangle(13667807, 2320477, 17230031, 5713298)

        self.downloader = Downloader()
        self.downloader.userAgent = "QGIS/{0} Qgis2threejs GSIElevTileProvider".format(
            Qgis.QGIS_VERSION_INT
        )  # will be overwritten in QgsNetworkAccessManager::createRequest() since 2.2
        self.downloader.DEFAULT_CACHE_EXPIRATION = QSettings().value(
            "/qgis/defaultTileExpiry", 24, type=int)

        self.driver = gdal.GetDriverByName("MEM")
        self.last_dataset = None

    def name(self):
        return "GSI Elevation Tile"

    def read(self, width, height, extent):
        # calculate bounding box in EPSG:3857
        geometry = extent.geometry()
        geometry.transform(self.transform)
        merc_rect = geometry.boundingBox()

        # if the bounding box doesn't intersect with the bounding box of this data, return a list filled with nodata value
        if not self.boundingbox.intersects(merc_rect):
            return [NODATA_VALUE] * width * height

        # get tiles
        over_smpl = 1
        segments_x = 1 if width == 1 else width - 1
        res = extent.width() / segments_x / over_smpl
        ds = self.getDataset(merc_rect.xMinimum(), merc_rect.yMinimum(),
                             merc_rect.xMaximum(), merc_rect.yMaximum(), res)

        geotransform = extent.geotransform(width, height)
        return self._read(ds, width, height, geotransform)

    def readValue(self, x, y):
        """Get value at the position using 1px * 1px memory raster. The value is calculated using a tile of max zoom level"""
        # coordinate transformation into EPSG:3857
        pt = self.transform.transform(QgsPoint(x, y))

        # if the point is not within the bounding box of this data, return nodata value
        if not self.boundingbox.contains(pt):
            return NODATA_VALUE

        res = 0.1
        hres = res / 2
        ds = self.getDataset(pt.x() - hres,
                             pt.y() - hres,
                             pt.x() + hres,
                             pt.y() + hres, res)

        geotransform = [x - hres, res, 0, y + hres, 0, -res]
        return self._read(ds, 1, 1, geotransform)[0]

    def _read(self, ds, width, height, geotransform):
        # create a memory dataset
        warped_ds = self.driver.Create("", width, height, 1, gdal.GDT_Float32)
        warped_ds.SetProjection(self.dest_wkt)
        warped_ds.SetGeoTransform(geotransform)

        # reproject image
        gdal.ReprojectImage(ds, warped_ds, None, None, gdal.GRA_Bilinear)

        # load values into an array
        band = warped_ds.GetRasterBand(1)
        fs = "f" * width * height
        return struct.unpack(
            fs, band.ReadRaster(0, 0, width, height,
                                buf_type=gdal.GDT_Float32))

    def getDataset(self, xmin, ymin, xmax, ymax, mapUnitsPerPixel):
        # calculate zoom level
        mpp1 = TSIZE1 / TILE_SIZE
        zoom = int(math.ceil(math.log(mpp1 / mapUnitsPerPixel, 2) + 1))
        zoom = max(0, min(zoom, ZMAX))

        # calculate tile range (yOrigin is top)
        size = TSIZE1 / 2**(zoom - 1)
        matrixSize = 2**zoom
        ulx = max(0, int((xmin + TSIZE1) / size))
        uly = max(0, int((TSIZE1 - ymax) / size))
        lrx = min(int((xmax + TSIZE1) / size), matrixSize - 1)
        lry = min(int((TSIZE1 - ymin) / size), matrixSize - 1)

        cols = lrx - ulx + 1
        rows = lry - uly + 1

        # download count limit
        if cols * rows > 128:
            logMessage("Number of tiles to fetch is too large!")
            width = height = 1
            return self.driver.Create("", width, height, 1, gdal.GDT_Float32,
                                      [])

        if self.last_dataset and self.last_dataset[0] == [
                zoom, ulx, uly, lrx, lry
        ]:  # if same as last tile set, return cached dataset
            return self.last_dataset[1]

        urltmpl = "http://cyberjapandata.gsi.go.jp/xyz/dem/{z}/{x}/{y}.txt"
        #urltmpl = "http://localhost/xyz/dem/{z}/{x}/{y}.txt"
        tiles = self.fetchFiles(urltmpl, zoom, ulx, uly, lrx, lry)

        # create a memory dataset
        width = cols * TILE_SIZE
        height = rows * TILE_SIZE
        res = size / TILE_SIZE
        geotransform = [
            ulx * size - TSIZE1, res, 0, TSIZE1 - uly * size, 0, -res
        ]

        #mem_driver = gdal.GetDriverByName("GTiff")
        #ds = mem_driver.Create("D:/fetched_tile.tif", width, height, 1, gdal.GDT_Float32, [])

        ds = self.driver.Create("", width, height, 1, gdal.GDT_Float32, [])
        ds.SetProjection(str(self.crs3857.toWkt()))
        ds.SetGeoTransform(geotransform)

        band = ds.GetRasterBand(1)
        for i, tile in enumerate(tiles):
            if tile:
                col = i % cols
                row = i // cols
                band.WriteRaster(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE,
                                 TILE_SIZE, tile)

        ds.FlushCache()

        self.last_dataset = [[zoom, ulx, uly, lrx, lry], ds]  # cache dataset
        return ds

    def fetchFiles(self, urltmpl, zoom, xmin, ymin, xmax, ymax):
        downloadTimeout = 60

        urls = []
        for y in range(ymin, ymax + 1):
            for x in range(xmin, xmax + 1):
                urls.append(
                    urltmpl.replace("{x}",
                                    str(x)).replace("{y}", str(y)).replace(
                                        "{z}", str(zoom)))
        files = self.downloader.fetchFiles(urls, downloadTimeout)

        for url in urls:
            data = files[url]
            if data:
                yield numpy.fromstring(data.replace(
                    b"e", NODATA_VALUE_BYTES).replace(b"\n", b","),
                                       dtype=numpy.float32,
                                       sep=",").tostring()  # to byte array
            else:
                array = numpy.empty(TILE_SIZE * TILE_SIZE, dtype=numpy.float32)
                array.fill(NODATA_VALUE)
                yield array.tostring()
Exemplo n.º 21
0
    def runContextMeasure(self, feedback, reference, test, method,
                          threshold) -> MatchPairManager:
        """
        Processing the matching using Context measure.
        
        Return: the MatchPairManager
        """

        # 1) Initial calculus
        # 1.1) Descobrir quem eh menor, que serve de param
        # SearchLength = Diagonal / PointCount * 20  -> distance for 20 points in Diagonal
        boxA = reference.extent()
        boxB = test.extent()

        searchLengthA = math.sqrt(boxA.width()**2 + boxA.height()**2
                                  ) / reference.featureCount() * 20.
        searchLengthB = math.sqrt(boxB.width()**2 +
                                  boxB.height()**2) / test.featureCount() * 20.

        # parameters for context
        cttSearchLength = searchLengthA if searchLengthA > searchLengthB else searchLengthB
        cttDistanceStep = cttSearchLength / 20.
        cttAngleStep = math.pi / 6.

        # outros
        refIsMulti = QgsWkbTypes.isMultiType(int(reference.wkbType()))
        testIsMulti = QgsWkbTypes.isMultiType(int(test.wkbType()))

        # 2) Calculate the context
        context = ContextMeasure()

        shapeContextA = context.calculateShapeContext(reference,
                                                      cttSearchLength,
                                                      cttAngleStep,
                                                      cttDistanceStep)
        feedback.setProgress(10)

        shapeContextB = context.calculateShapeContext(test, cttSearchLength,
                                                      cttAngleStep,
                                                      cttDistanceStep)
        feedback.setProgress(20)

        # 3) Run the processing
        ncols = reference.featureCount()
        nrows = test.featureCount()

        distMatrix = [[1. for x in range(ncols + 1)] for y in range(nrows + 1)]

        # 3.1) Compute the number of steps to display within the progress bar and
        # get features from source
        total = 80.0 / ncols

        # 3.2) Itera sobre os ref e procura o equivalente em test
        for j, refFeat in enumerate(reference.getFeatures()):
            # running chks
            if feedback.isCanceled():
                break

            # Coloque o ID no lugar
            distMatrix[0][j + 1] = refFeat.id()

            refGeom = refFeat.geometry()
            refHist = shapeContextA.get(refFeat.id())

            # Chks habituais
            if refGeom.isEmpty() or refHist is None:
                continue

            # obtem a geometria e monta o box de busca - baseado no cttSearchLength
            refPoint = refGeom.asPoint(
            ) if not refIsMulti else refGeom.asMultiPoint()[0].asPoint()

            refBox = QgsRectangle(refPoint.x() - cttSearchLength,
                                  refPoint.y() - cttSearchLength,
                                  refPoint.x() + cttSearchLength,
                                  refPoint.y() + cttSearchLength)

            for i, testFeat in enumerate(test.getFeatures()):

                # Coloque o ID no lugar - repetindo
                distMatrix[i + 1][0] = testFeat.id()

                testGeom = testFeat.geometry()
                testHist = shapeContextB.get(testFeat.id())

                # Chks habituais
                if testGeom.isEmpty() or testHist is None:
                    continue

                # obtem a geometria
                testPoint = testGeom.asPoint(
                ) if not testIsMulti else testGeom.asMultiPoint()[0].asPoint()

                # ignore o disjoint
                if not refBox.contains(testPoint):
                    continue

                # agora sim, o que a gente veio fazer aqui: distance
                distMatrix[i + 1][j + 1] = context.distanceContext(
                    refHist, testHist)

            feedback.setProgress(20 + int(j * total))
        # fim for_feat

        # debug

        # 4) OK, tenho tudo, faltam os pares
        pairMgr = MatchPairManager()

        # check o criteria
        criteria = pairMgr.CriteriaType.ISMINIMUM if method % 2 == 0 else pairMgr.CriteriaType.BOTHMIN

        pairMgr.buildFromMatrix(distMatrix, criteria, threshold)

        return pairMgr
Exemplo n.º 22
0
    def runEuclideanDistance(self, feedback, reference, test, method,
                             threshold) -> MatchPairManager:
        """
        Processing the matching using Euclidean distance.
        
        Return: the MatchPairManager
        """

        # 2) test parameters
        testExtent = test.extent()
        maxDistance = testExtent.width(
        ) if testExtent.width() > testExtent.height() else testExtent.height()

        if maxDistance < 2. * threshold:
            raise Exception(
                self.
                tr("Test data with a small bounding box. It should be at least twice the threshold."
                   ), "INVALIDPARAMETERVALUE")

        refIsMulti = QgsWkbTypes.isMultiType(int(reference.wkbType()))
        testIsMulti = QgsWkbTypes.isMultiType(int(test.wkbType()))

        # 3) Run the processing
        ncols = reference.featureCount()
        nrows = test.featureCount()

        distMatrix = [[int(maxDistance) for x in range(ncols + 1)]
                      for y in range(nrows + 1)]

        # 3.1) Compute the number of steps to display within the progress bar and
        # get features from source
        total = 100.0 / ncols

        # 3.2) Itera sobre os ref e procura o equivalente em test
        for j, refFeat in enumerate(reference.getFeatures()):
            # running chks
            if feedback.isCanceled():
                break

            # Coloque o ID no lugar
            distMatrix[0][j + 1] = refFeat.id()  #refFeat.id()

            refGeom = refFeat.geometry()

            # Chks habituais
            if refGeom.isEmpty():
                continue

            # obtem a geometria e monta o box de busca
            refPoint = refGeom.asPoint(
            ) if not refIsMulti else refGeom.asMultiPoint()[0].asPoint()

            refBox = QgsRectangle(refPoint.x() - threshold,
                                  refPoint.y() - threshold,
                                  refPoint.x() + threshold,
                                  refPoint.y() + threshold)

            for i, testFeat in enumerate(test.getFeatures()):

                # Coloque o ID no lugar - repetindo
                distMatrix[i + 1][0] = testFeat.id()  #testFeat.id()

                testGeom = testFeat.geometry()

                # Chks habituais
                if testGeom.isEmpty():
                    continue

                # obtem a geometria
                testPoint = testGeom.asPoint(
                ) if not testIsMulti else testGeom.asMultiPoint()[0].asPoint()

                # ignore o disjoint
                if not refBox.contains(testPoint):
                    continue

                # agora sim, o que a gente veio fazer aqui: distance
                distMatrix[i + 1][j + 1] = refPoint.distance(testPoint)

            feedback.setProgress(int(j * total))

        # debug

        # 4) OK, tenho tudo, faltam os pares
        pairMgr = MatchPairManager()

        # check o criteria
        criteria = pairMgr.CriteriaType.ISMINIMUM if method % 2 == 0 else pairMgr.CriteriaType.BOTHMIN

        pairMgr.buildFromMatrix(distMatrix, criteria, threshold)

        return pairMgr
Exemplo n.º 23
0
    def calculateShapeContext(self,
                              pointLayer,
                              searchLength,
                              angleStep,
                              distanceStep,
                              normalize=True):
        """
        Calculate the shape context for a set of points using the Shape Context method developed by Belongie et al.
        
        For details see: Belongie, S., Malik, J., and Puzicha, J., 2002. Shape Matching and Object Recognition Using
        Shape Contexts. IEEE Transactions on Pattern Analysis and Machine Intelligence, 24 (4), 509–522.
        Available at: http://ieeexplore.ieee.org/document/993558/?arnumber=993558
        
        @param pointLayer: Input point layer.
        @param searchLength: Maximum search lenght to consider as a neighbourhood. 4 cm at data scale is a good value.
        @param angleStep: The radial size of each bin. A value of pi/6 is a good choice. pi/6 is a good value.
        @param distanceStep: The initial distance step for the bins. It will grow by its value plus radial size. 1 mm at data scale is a good value.
        @param normalize: Normalizes the histogram count to [0, 1]. Defaults to yes.
        @returns Histogram (bin, count) for the point set.
        """

        # 1) initial vars - O contexto eh um histograma
        # 0
        isMulti = QgsWkbTypes.isMultiType(int(pointLayer.wkbType()))

        # 1.1) Le o layer para pontos
        points = dict()

        for feat in pointLayer.getFeatures():
            # Processe a geom se valida
            geom = feat.geometry()

            # Chks habituais
            if geom.isEmpty():
                continue

            # obtem a geometria
            point = geom.asPoint() if not isMulti else geom.asMultiPoint(
            )[0].asPoint()

            #points.append( point )
            points[feat.id()] = point

        # 1.2) Abordagem radial
        angleSlices = int(round(2. * math.pi / angleStep))

        # fill distance distance map
        distStepMap = []
        currDist = distanceStep

        while currDist < searchLength:
            distStepMap.append(currDist)

            # atlz valores
            currDist += currDist * angleStep

        distanceSlices = len(distStepMap) + 1
        slices = angleSlices * distanceSlices

        # ultimo slice - para todos
        distStepMap.append(searchLength)

        # 2) Varre todos os pontos - jah tenho os limites, preciso acertar qm faz o q
        # saida eh um dict de histogramas
        retval = dict()

        for idA, ptA in points.items():
            # monta o Box
            searchBox = QgsRectangle(ptA.x() - searchLength,
                                     ptA.y() - searchLength,
                                     ptA.x() + searchLength,
                                     ptA.y() + searchLength)
            neighCount = 0
            histog = dict()  # resultado para esse ponto

            # checa sua relacao com os demais
            #for j, ptB in enumerate( points ):
            for idB, ptB in points.items():
                # ignora o mesmo
                #if i == j:
                if idA == idB:
                    continue

                # ignore o disjoint
                if not searchBox.contains(ptB):
                    continue

                # Ok, estah na area de busca, qual o valor do ang e distancia?
                distance = ptA.distance(ptB)

                # distance aqui eh radial - mudanca em relacao aos demais
                if distance > searchLength:
                    continue

                angle = math.atan2(ptB.y() - ptA.y(), ptB.x() - ptA.x())

                # angulo negativo, corrija
                if angle < 0.:
                    angle += 2. * math.pi

                # 3) agora coloca no histograma
                # 3.1) angulo
                angQuad = 1. + math.floor(angle / angleStep)

                # 3.2) distancia - usando o map - um lower_bound resolveria...
                distQuad = 0

                for k, dist in enumerate(distStepMap):
                    if distance < dist:
                        distQuad = k
                        break

                # 3.3) colocando no histograma
                idx = int(angleSlices * distQuad + angQuad)
                if histog.get(idx) == None:
                    histog[idx] = 1
                else:
                    histog[idx] += 1

                neighCount += 1

                # fim for points(search)

            # seguindo o padrao anterior, soh considero os 3 vizinhos
            if neighCount >= 3:
                retval[idA] = histog

            #i += 1
            # fim for points(search)

            # 4) zera todos que nao existem - para iterar
            """ temp comment ---- gasta muito tempo!
            for histog in retval:
                if len( histog ) == 0:
                    retval.remove( histog )
                    
                # preenche, se vazio
                for k in range (1, slices+1 ):
                    if histog.get(k) is None:
                        histog[k] = 0
            """

            # 5) normalizar
            if normalize:
                for histog in retval.values():
                    sum = 0

                    for val in histog.values():
                        sum += val

                    # OK, agora divida - garantindo div0
                    if sum > 0:
                        for key, val in histog.items():
                            histog[key] = val / sum

        return retval
Exemplo n.º 24
0
    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)

        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect1.contains(rect3)))
        assert rect1.contains(rect3), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect2.contains(rect3)))
        assert rect2.contains(rect3), myMessage

        # test for point
        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect1.contains(pnt1)))
        assert rect1.contains(pnt1), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect2.contains(pnt1)))
        assert rect2.contains(pnt1), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect3.contains(pnt1)))
        assert rect3.contains(pnt1), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (False, rect1.contains(pnt2)))
        self.assertFalse(rect1.contains(pnt2), myMessage)

        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect2.contains(pnt2)))
        assert rect2.contains(pnt2), myMessage

        myMessage = ('Expected: %s\nGot: %s\n' % (False, rect3.contains(pnt2)))
        self.assertFalse(rect3.contains(pnt2), myMessage)

        myMessage = ('Expected: %s\nGot: %s\n' % (True, rect3.contains(pnt1)))
        self.assertTrue(rect3.contains(pnt1), myMessage)
    def write_csv(self):
        layer = self.iface.activeLayer()

        if layer.type() != QgsMapLayer.VectorLayer:
            self.show_message(
                'The active layer "{}" is NOT a vector layer containing plot data.\nPlease make a polygon layer active in the layermanager.'
                .format(layer.name()))
            return

        reply = QMessageBox.question(
            self.iface.mainWindow(), 'FieldExplorer NL',
            'Save current active layer "{}" to FieldExplorer CSV?'.format(
                layer.name()), QMessageBox.Yes | QMessageBox.No,
            QMessageBox.Yes)
        if reply == QMessageBox.No:
            return

        layer_path = layer.dataProvider().dataSourceUri()
        (directory, file_name) = os.path.split(layer_path)
        file_name = file_name.split('|')[0]
        csv_name = os.path.splitext(file_name)[0] + '.csv'
        csv_file = os.path.join(directory, csv_name)

        # check if dir is writable
        if not os.access(directory,
                         os.W_OK):  # W_OK is for writing, R_OK for reading
            self.show_message(
                'The data directory "{}"\nis not writable, will not be able to write a csv there.'
                .format(directory))
            return

        # check if layer's crs = epsg:4326
        if 'EPSG:4326' != layer.crs().authid():
            self.show_message(
                'The layer should have EPSG:4326 as crs, but is: "{}".\nPlease provide a layer in EPSG:4326 (lat lon coordinates).'
                .format(layer.crs().authid()))
            return

        # or coordinates within  2,50.0 : 8.0,55 (NL))
        layer_extent = layer.extent()
        nl_extent = QgsRectangle(2, 50.0, 8.0, 55)
        if not nl_extent.contains(layer_extent):
            self.show_message(
                'The data/layer extent:\n{}\nis not within The Netherlands.\nPlease provide data within\n{}.'
                .format(layer_extent.toString(), nl_extent.toString()))
            return

        features = layer.getFeatures()
        attributes = layer.fields().names()
        if not ('Plot-ID' in attributes and 'Comments' in attributes):
            self.show_message(
                'The data should contain both an "Plot-ID" and a "Comments" attribute.\nAvailable attributes: {}'
                .format(attributes))
            return

        # check for touches (could also be intersects)
        for feature in features:
            others = layer.getFeatures()
            for other in others:
                # self.log('Testing: \n{} with {}'.format(feature.attributes(), other.attributes()))
                if feature['Plot-ID'] == other['Plot-ID']:
                    # self.log('IDEM: \n{} {}'.format(feature.attributes(),other.attributes()))
                    pass
                elif feature.geometry().intersects(other.geometry()):
                    self.show_message(
                        'These two features intersect each other: '
                        '\n{}\n{}. They should not share vertices and segments should not touch.'
                        .format(feature.attributes(), other.attributes()))
                    return

        features = layer.getFeatures()
        with open(csv_file, 'w', newline='') as f:
            self.log(
                'Starting to write "{}" ({} in {}) to FieldExplorer NL CSV'.
                format(layer.name(), file_name, directory))
            # QUOTE_NONNUMERIC, QUOTE_MINIMAL
            csv_writer = csv.writer(f,
                                    delimiter=',',
                                    quotechar='"',
                                    quoting=csv.QUOTE_MINIMAL)  # NO quoting
            # header
            csv_writer.writerow(
                ('Plot-ID', 'A(LAT)', 'A(LONG)', 'B(LAT)', 'B(LONG)', 'C(LAT)',
                 'C(LONG)', 'D(LAT)', 'D(LONG)', 'Comments'))
            for feature in features:
                geom = feature.geometry()
                # force singletype (so both multi and single will work)
                if not geom.convertToSingleType():
                    self.show_message(
                        'Cannot convert feature {} to a single polygon.'.
                        format(feature.attributes()))
                    return

                # force clockwise direction!
                geom.forceRHR()

                coordinates = []
                for vertex in geom.vertices():
                    coordinates.append(vertex)

                # check if just 5
                if len(coordinates) > 5:
                    self.show_message(
                        'The feature {}\ncontains too many vertices,\nthere should be just 4, but has: {}'
                        .format(feature.attributes(),
                                len(coordinates) - 1))
                    return
                if len(f'{feature["Plot-ID"]:}') > 50:
                    self.show_message(
                        'The feature {}\nhas a Plot-ID of length {}\nPlease change this Plot-ID to a shorter one:\n"{}"'
                        .format(feature.attributes(), len(feature['Plot-ID']),
                                feature['Plot-ID']))
                    return
                # check for '\ / : * ? " < > |'
                forbidden_chars = ('\\', '/', ':', '*', '?', '"', '<', '>',
                                   '|')
                for c in forbidden_chars:
                    if c in f'{feature["Plot-ID"]:}':
                        self.show_message(
                            'The feature {}\ncontains the character "{}" which is forbidden in Plot-IDs\nPlease change this Plot-ID: "{}"'
                            .format(feature.attributes(), c,
                                    feature['Plot-ID']))
                        return

                row = []
                row.append(feature['Plot-ID'])
                for coord in coordinates[:-1]:
                    row.append(coord.y())
                    row.append(coord.x())
                if 'Comments' in attributes:
                    row.append(feature['Comments'])
                csv_writer.writerow(row)
        # OK, done!
        self.iface.messageBar().pushMessage(
            'Done!',
            'Succesfully wrote FieldExplorer CSV file to:\n{}'.format(
                csv_file),
            level=Qgis.Info,
            duration=15)