예제 #1
0
 def progressdialog(self, progress):
     pdialog = QProgressDialog()
     pdialog.setWindowTitle("Progress")
     pdialog.setLabelText("Voortgang van importeren:")
     pbar = QProgressBar(pdialog)
     pbar.setTextVisible(True)
     pbar.setValue(progress)
     pdialog.setBar(pbar)
     pdialog.setMinimumWidth(300)
     pdialog.show()
     return pdialog, pbar
예제 #2
0
class Create_model:
    def __init__(self, dlg, current_layer):
        """This constructor need Qt Dialog  class as dlg and need current layer to execute the algorithm
        in current_layer parameter"""

        self.layers = current_layer
        self.bar = QProgressBar()
        self.dlg = dlg

        #self.list = []
        self.border = []

        self.X = []
        self.Y = []
        self.Z = []
        self.faces = []
        self.points = []
        #self.list_of_all=[]

        self.NoData = -3.4028234663852886e+38

    '''def iterator(self):
        """Main algorithm to iterate through all the pixels and also to create boundaries"""
        self.layer = self.dlg.cmbSelectLayer.currentLayer()
        #get the extent of layer
        provider = self.layer.dataProvider()
        extent = provider.extent()
        xmin = extent.xMinimum()
        ymax = extent.yMaximum()
        rows = self.layer.height()
        cols = self.layer.width()
        xsize = self.layer.rasterUnitsPerPixelX()
        ysize = self.layer.rasterUnitsPerPixelY()
        xinit = xmin + xsize / 2
        yinit = ymax - ysize / 2
        block = provider.block(1, extent, cols, rows)
        #iterate the raster to get the values of pixels
        k=1
        for i in range(rows):
            for j in range(cols):
                x = xinit + j * xsize
                y = yinit
                k += 1
                if block.value(i, j)  == self.NoData:
                    self.list_of_all.append([i,j,x,y,block.value(i,j)])
                elif block.value(i,j)>=self.dlg.dsbDatum.value():
                    self.list.append([x, y, block.value(i, j)])
                    self.list_of_all.append([i,j,x,y,block.value(i,j)])
                else:
                    self.list_of_all.append([i,j,x,y,self.NoData])
            xinit = xmin + xsize / 2
            yinit -= ysize
        #get minimal value to stretching method
        print(len(self.list_of_all))
        height=[]
        for searching in self.list:
                height.append(searching[2])
        self.minimal=min(height)
        #iterate the raster to get the boundaries
        colrow=[]
        rowcol=[]
        for pixelo in self.list_of_all:
            rowcol.append(pixelo)
            if pixelo[1]==j:
                colrow.append(rowcol)
                rowcol=[]
        for pixel in self.list_of_all:
            if pixel[4] != self.NoData:
                if pixel[0]==0 or pixel[1]==0 or pixel[0]==i or pixel[1]==j:
                    pixel[4] = float(self.dlg.dsbDatum.value())
                    self.border.append([pixel[2],pixel[3],pixel[4]])
                    #self.list = self.border + self.list
                else:
                    wii=pixel[0]
                    kol=pixel[1]
                    pixel[4]=float(self.dlg.dsbDatum.value())
                    condition1 = colrow[wii-1][kol][4]
                    condition2 = colrow[wii][kol-1][4]
                    condition3 = colrow[wii+1][kol][4]
                    condition4 = colrow[wii][kol+1][4]
                    if condition1> self.NoData or condition2> self.NoData or condition3> self.NoData or condition4 > self.NoData:
                        if condition1 == self.NoData or condition2== self.NoData or condition3== self.NoData or condition4 == self.NoData:
                            self.border.append([pixel[2],pixel[3],pixel[4]])
                            #self.list=self.border+self.list
        self.list += self.border    
        print(len(self.border))
        #print(self.list)
        print(len(self.list))
        
        return self.list, self.minimal'''

    def iterator(self):
        #path = iface.activeLayer().source()

        path = self.dlg.cmbSelectLayer.currentLayer().source()

        data_source = gdal.Open(path)
        #extract one band, because we don't need 3d matrix
        band = data_source.GetRasterBand(1)
        #read matrix as numpy array

        raster = band.ReadAsArray().astype(np.float)
        #threshold = 222 #poziom odniesienia - wyzsze od 222

        threshold = self.dlg.dsbDatum.value()

        #change no data to nan value
        raster[raster == band.GetNoDataValue()] = np.nan
        raster2 = raster[np.logical_not(
            np.isnan(raster)
        )]  #w raster2 nie mam nanow i sa to tylko wartosci wysokosci
        (y_index, x_index) = np.nonzero(raster >= threshold)

        #get the minimal value to stretching method
        self.minimal = np.nanmin(raster)

        #To demonstate this compare a.shape to band.XSize and band.YSize
        (upper_left_x, x_size, x_rotation, upper_left_y, y_rotation,
         y_size) = data_source.GetGeoTransform()

        x_coords = x_index * x_size + upper_left_x + (
            x_size / 2)  #add half the cell size
        y_coords = y_index * y_size + upper_left_y + (y_size / 2
                                                      )  #to centre the point
        raster3 = raster2[raster2 >= threshold]
        z_coords = np.asarray(raster3).reshape(-1)

        entire_matrix = np.stack((x_coords, y_coords, z_coords), axis=-1)

        #add outer
        bounder = np.pad(raster,
                         pad_width=1,
                         mode='constant',
                         constant_values=np.nan)
        bounder_inner = (np.roll(bounder, 1, axis=0) *
                         np.roll(bounder, -1, axis=0) *
                         np.roll(bounder, 1, axis=1) *
                         np.roll(bounder, -1, axis=1) *
                         np.roll(np.roll(bounder, 1, axis=0), 1, axis=1) *
                         np.roll(np.roll(bounder, 1, axis=0), -1, axis=1) *
                         np.roll(np.roll(bounder, -1, axis=0), 1, axis=1) *
                         np.roll(np.roll(bounder, -1, axis=0), -1, axis=1))
        is_inner = (np.isnan(bounder_inner) == False)
        b = bounder
        b[is_inner] = np.nan
        b[~np.isnan(b)] = threshold
        boundary_real = b[1:-1, 1:-1]

        boundary_real_2 = boundary_real[np.logical_not(
            np.isnan(boundary_real))]

        #create boundary coordinates
        (y_index_boundary,
         x_index_boundary) = np.nonzero(boundary_real == threshold)

        #print(len(boundary_real_2))
        x_coords_boundary = x_index_boundary * x_size + upper_left_x + (
            x_size / 2)  #add half the cell size
        y_coords_boundary = y_index_boundary * y_size + upper_left_y + (
            y_size / 2)  #to centre the point
        z_coords_boundary = np.asarray(boundary_real_2).reshape(-1)

        boundary_the_end = np.stack(
            (x_coords_boundary, y_coords_boundary, z_coords_boundary), axis=-1)
        boundary_the_end = np.repeat(boundary_the_end, 10, axis=0)

        self.entire_mat_with_heights = np.concatenate(
            (entire_matrix, boundary_the_end))
        #entire_mat_with_heights[entire_mat_with_heights[:, [0,1,2]].argsort()]
        self.entire_mat_with_heights = self.entire_mat_with_heights[np.argsort(
            self.entire_mat_with_heights[:, 2])]

        return self.entire_mat_with_heights, self.minimal

    def delaunay(self):
        """This is Delaunay algorithm from Scipy lib
        This is needed to create vertices and faces which will be going to executed in creating STL model"""

        self.x = self.entire_mat_with_heights[:, 0]
        self.y = self.entire_mat_with_heights[:, 1]
        self.z = self.entire_mat_with_heights[:, 2]

        #print(self.x.shape)
        self.tri = Delaunay(np.array([self.x, self.y]).T)
        for vert in self.tri.simplices:
            self.faces.append([vert[0], vert[1], vert[2]])
        for i in range(self.x.shape[0]):
            self.points.append([self.x[i], self.y[i], self.z[i]])

        return self.faces, self.points, self.x, self.y, self.z, self.tri

    def saver(self):
        """ Create STL model """

        # Define the vertices
        vertices = np.array(self.points)
        # Define the triangles
        facess = np.array(self.faces)
        # Create the mesh
        self.figure = mesh.Mesh(
            np.zeros(facess.shape[0], dtype=mesh.Mesh.dtype))
        all_percentage = len(facess)
        value = self.bar.value()
        for i, f in enumerate(facess):
            if value < all_percentage:
                value = value + 1
                self.bar.setValue(value)
            else:
                self.timer.stop()
            for j in range(3):
                self.figure.vectors[i][j] = vertices[f[j], :]

        filename = self.dlg.lineEdit.text()
        self.figure.save(filename)
        return self.figure

    def create_graph(self):
        """ Visualize model by Matplotlib lib"""

        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1, projection='3d')
        ax.plot_trisurf(self.x,
                        self.y,
                        self.z,
                        triangles=self.tri.simplices,
                        cmap=plt.cm.Spectral)
        ax.set_title('3D_Graph')
        ax.set_xlabel('X Label')
        ax.set_ylabel('Y Label')
        ax.set_zlabel('Z Label')
        plt.show()

    def stretching(self):
        """ This method stretching the entire model to the given Datum level"""
        for cords in self.entire_mat_with_heights:
            if cords[2] > self.minimal:
                height_stretched = cords[2] - float(self.dlg.dsbDatum.value())
                height_stretched = height_stretched * self.dlg.sbStretch.value(
                )
                height_stretched += float(self.dlg.dsbDatum.value())
                cords[2] = height_stretched
        return self.entire_mat_with_heights

    def loading(self):
        """ Loading progress bar """

        self.dialog = QProgressDialog()
        self.dialog.setWindowTitle("Loading")
        self.dialog.setLabelText("That's your progress")
        self.bar = QProgressBar()
        self.bar.setTextVisible(True)
        self.dialog.setBar(self.bar)
        self.dialog.setMinimumWidth(300)
        self.dialog.show()
        self.timer = QTimer()
        self.timer.timeout.connect(self.saver)
        self.timer.start(1000)

    def shape(self, direction):
        """ This algorithm convert ShapeFile to the .tif file.
        To created that process I used a lot of GDAL processing algorithms
         and this gave me possibility to convert the shape to .tif file,
         drape them to the correct elevation and merge this new raster to the current main tif """

        self.plugin_dir = direction
        buffer_distance = self.dlg.dsbBuffer.value()
        output_data_type = self.dlg.sbOutputData.value()
        output_raster_size_unit = 0
        no_data_value = 0
        layer2 = self.dlg.cmbSelectShape.currentLayer()
        shape_dir = os.path.join(self.plugin_dir, 'TRASH')

        layer_ext_cor = self.dlg.cmbSelectLayer.currentLayer()
        provider = layer_ext_cor.dataProvider()
        extent = provider.extent()
        xmin = extent.xMinimum()
        ymax = extent.yMaximum()
        xmax = extent.xMaximum()
        ymin = extent.yMinimum()
        cord_sys = layer_ext_cor.crs().authid()
        coords = "%f,%f,%f,%f " % (xmin, xmax, ymin,
                                   ymax) + '[' + str(cord_sys) + ']'
        rows = layer_ext_cor.height()
        cols = layer_ext_cor.width()
        set_shp_height = self.dlg.sbHeight.value()

        processing.run(
            "native:buffer", {
                'INPUT': layer2,
                'DISTANCE': buffer_distance,
                'SEGMENTS': 5,
                'END_CAP_STYLE': 0,
                'JOIN_STYLE': 0,
                'MITER_LIMIT': 2,
                'DISSOLVE': False,
                'OUTPUT': os.path.join(shape_dir, 'shape_bufor.shp')
            })  #### tu poprawic ten dissolve \/ zredukowac ten na dole

        processing.run(
            "native:dissolve", {
                'INPUT': os.path.join(shape_dir, 'shape_bufor.shp'),
                'FIELD': [],
                'OUTPUT': os.path.join(shape_dir, 'shape_dissolve.shp')
            })

        processing.run(
            "qgis:generatepointspixelcentroidsinsidepolygons", {
                'INPUT_RASTER':
                self.dlg.cmbSelectLayer.currentLayer().dataProvider().
                dataSourceUri(),
                'INPUT_VECTOR':
                os.path.join(shape_dir, 'shape_dissolve.shp'),
                'OUTPUT':
                os.path.join(shape_dir, 'shape_points.shp')
            })

        processing.run(
            "native:setzfromraster", {
                'INPUT':
                os.path.join(shape_dir, 'shape_points.shp'),
                'RASTER':
                self.dlg.cmbSelectLayer.currentLayer().dataProvider().
                dataSourceUri(),
                'BAND':
                1,
                'NODATA':
                0,
                'SCALE':
                1,
                'OUTPUT':
                os.path.join(shape_dir, 'shape_drape.shp')
            })

        layer3 = iface.addVectorLayer(
            os.path.join(shape_dir, 'shape_drape.shp'), "Shape_Drape", "ogr")
        if not layer3:
            print("Layer failed to load!")
        field_name = "height"
        field_namess = [field.name() for field in layer3.fields()]
        i = 0
        for l in range(100):
            i += 1
            if field_name in field_namess:
                print('Exist')
                field_name = field_name + str(i)
                continue
            else:
                print('Doesn\'t Exist')
                break

        processing.run(
            "qgis:fieldcalculator", {
                'INPUT': os.path.join(shape_dir, 'shape_drape.shp'),
                'FIELD_NAME': field_name,
                'FIELD_TYPE': 0,
                'FIELD_LENGTH': 10,
                'FIELD_PRECISION': 3,
                'NEW_FIELD': True,
                'FORMULA': 'z($geometry)+' + str(set_shp_height),
                'OUTPUT': os.path.join(shape_dir, 'shape_drape_c.shp')
            })

        processing.run(
            "gdal:rasterize", {
                'INPUT': os.path.join(shape_dir, 'shape_drape_c.shp'),
                'FIELD': field_name,
                'BURN': 0,
                'UNITS': output_raster_size_unit,
                'WIDTH': cols,
                'HEIGHT': rows,
                'EXTENT': coords,
                'NODATA': no_data_value,
                'OPTIONS': '',
                'DATA_TYPE': output_data_type,
                'INIT': None,
                'INVERT': False,
                'OUTPUT': os.path.join(shape_dir, 'shape_to_raster.tif')
            })
        iface.addRasterLayer(os.path.join(shape_dir, 'shape_to_raster.tif'),
                             "Shape_to_Raster")
        QgsProject.instance().removeMapLayers([layer3.id()])

        processing.run(
            "gdal:merge", {
                'INPUT': [
                    self.dlg.cmbSelectLayer.currentLayer().dataProvider().
                    dataSourceUri(),
                    os.path.join(shape_dir, 'shape_to_raster.tif')
                ],
                'PCT':
                False,
                'SEPARATE':
                False,
                'NODATA_INPUT':
                None,
                'NODATA_OUTPUT':
                None,
                'OPTIONS':
                '',
                'DATA_TYPE':
                5,
                'OUTPUT':
                os.path.join(shape_dir, 'merged.tif')
            })
        iface.addRasterLayer(os.path.join(shape_dir, 'merged.tif'),
                             "Raster_With_Shape")

        shape_to_raster = QgsProject.instance().mapLayersByName(
            'Shape_to_Raster')
        QgsProject.instance().removeMapLayers([shape_to_raster[0].id()])