Example #1
0
    def field_check(self, layer, z_field):
        errorCheck = False
        #Check if the vectorlayer is projected
        if layer.crs().geographicFlag() == True:
            criticalMessageToBar(
                self, 'Error', "Layer " + layer.name() +
                " is not projected. Please choose an projected reference system."
            )
            printLogMessage(
                self, "Layer " + layer.name() +
                " is not projected. Please choose an projected reference system.",
                'Error_LOG')
            # cancel execution of the script
            errorCheck = True

        #check the z-field
        for field in layer.fields():
            #Take a look for the z Field
            if str(field.name()) == str(z_field):
                # if the z value is not a float
                if field.typeName() != "Real" and field.typeName() != "double":
                    #Give a message
                    criticalMessageToBar(
                        self, 'Error',
                        'The z-Value needs to be a float. Check the field type of the z-Value'
                    )
                    printLogMessage(
                        self,
                        'The z-Value needs to be a float. Check the field type of the z-Value',
                        'Error_LOG')
                    # cancel execution of the script
                    errorCheck = True
        return errorCheck
Example #2
0
def sectionPoint(self, coord_proc, side):
    if side == 'East':
        coord_sort = sorted(coord_proc, key=lambda x: (-x[0], x[1]))
    elif side == 'West':
        coord_sort = sorted(coord_proc, key=lambda x: (x[0], -x[1]))

    coord_sort_xy = []
    for i in range(0, 2):
        coord_sort_xy.append(coord_sort[i])

    coords_sort_z = sorted(coord_sort_xy, key=lambda x: (-x[2]))

    point = QgsPoint(coords_sort_z[0][0], coords_sort_z[0][1])
    printLogMessage(self,
                    str(coords_sort_z[0][0]) + ',' + str(coords_sort_z[0][1]),
                    'koord')

    return point
Example #3
0
    def run(self):
        """Run method that performs all the real work"""
        #trigger help button
        #helpButton.clicked.connect(showPluginHelp())
        # Create the dialog (after translation) and keep reference
        self.dlg = profileAARDialog()
        #initialize the Errorhandler
        errorhandler = ErrorHandler(self.iface)
        magicbox = Magic_Box(self.iface)
        export = Export(self.iface)
        '''DEFINE OUTPUT PATH'''
        #Choose file if button is clicked
        self.dlg.outputPath.clear()
        self.dlg.outputButton.clicked.connect(self.select_output_file)
        '''SELECT INPUT IN GUI'''
        # CHOOSE INPUT LAYER
        # read layers from qgis layers and filter out the pointlayers to display in the input combobox
        self.dlg.inputCombo.setFilters(QgsMapLayerProxyModel.PointLayer)
        # CHOOSE COLUMNS FOR Z-VALUE, VIEW AND PR-NUMBER
        # CALLS FUNCTION LAYER_FIELD (once on startup on activation, to enable using when only one point fc is present)
        self.dlg.inputCombo.activated.connect(self.layer_field)
        self.dlg.inputCombo.currentIndexChanged.connect(self.layer_field)

        self.dlg.helpButton.clicked.connect(self.show_help)

        '''SHORT BLOCK OF PLUGIN CODE (runs the dialog and triggers the event after the OK button was pressed)'''
        # create/show the dialog
        self.dlg.show()
        # Run the dialog event loop
        result = self.dlg.exec_()
        # See if OK was pressed
        if result:
            inputCheck = False
            fieldCheck = False
            #Check if input fields are filled correctly an if the layer has correct properties
            inputCheck = errorhandler.input_check(self.dlg.outputPath.text())

            '''GET INPUT FROM GUI TO VARIABLES/PREPARE LIST OF DATA'''
            #GET TEXT FROM METHOD AND DIRECTION
            #Read the method that is selected
            method = unicode(self.dlg.methodCombo.currentText())
            #read the direction, that is selected
            direction = unicode(self.dlg.directionCombo.currentText())
            #Get the selected layer
            selectedLayer = self.dlg.inputCombo.currentLayer()
            #PREPARE DATA LIST
            #Go thought all data rows in the selected layer
            iter = selectedLayer.getFeatures()
            #list for the data
            coord = []
            #list for the different profile names
            profile_names = []
            #check if the z values have the correct type and if the crs is projected
            fieldCheck = errorhandler.field_check(selectedLayer, self.dlg.zCombo.currentText())



            height = False
            section = False

            if fieldCheck == True or inputCheck == True:
                sys.exitfunc()

            if self.dlg.hightBox.isChecked():
                height = True
            if self.dlg.sectionBox.isChecked():
                    section = True

            point_id = 0
            for feature in iter:
                # retrieve every feature with its geometry and attributes
                # fetch geometry
                # TODO: 3Nachkommastellen!! Bisher sind es nur 2.....
                geom = feature.geometry()
                #getting x and y coordinate
                x = round(geom.asPoint().x(), 3)
                y = round(geom.asPoint().y(), 3)
                #write coordinates and attributes (view, profile and z) in a list
                # TODO: Use dictinary or object
                #add an ID to each point
                point_id += 1
                coord.append([x,y,feature[self.dlg.zCombo.currentText()],feature[self.dlg.viewCombo.currentText()], feature[self.dlg.profileCombo.currentText()], feature[self.dlg.useCombo.currentText()], point_id])
                #write a list of profilenames (unique entries)
                if feature[self.dlg.profileCombo.currentText()] not in profile_names:
                    profile_names.append(feature[self.dlg.profileCombo.currentText()])

            '''WORK ON EVERY PROFILE IN LOOP'''
            # CREATE A LIST OF DATA FOR EVERY PROFILE
            # select every single profile in a loop

            coord_trans = []
            height_points = []
            cutting_line = []

            for i in range(len(profile_names)):
                # instantiate a temporary list for a single profile
                coord_proc = []
                # instantiate list for the view to check if all entries in one profile are the same
                view_check = []
                #CHANGE  # instantiate list for the selection to check if all entries in one profile are the same
                selection_check = []
                # iterate through the features in coord, if the profilename matches store the features datalist in templist
                for x in range(len(coord)):
                    if coord[x][4] == profile_names[i]:
                        coord_proc.append(coord[x])

                        # write the unique view values in the checklist
                        if coord[x][3] not in view_check:
                            view_check.append(coord[x][3])

                        # CHANGE  write the unique selection values in the checklist
                        if coord[x][4] not in selection_check:
                            selection_check.append(coord[x][5])
                
                #Handle Errors depending on the attributes in the fields
                #Errorhandling: Checking the single Profiles for inconsestency
                #Therefore we need the data of the actual profile, the view_check with the view values and actual profile name, selection is 0 or 1
                profileCheck = False
                if fieldCheck == False and inputCheck == False:

                    profileCheck = errorhandler.singleprofile(coord_proc, view_check, str(profile_names[i]), selection_check)



                if profileCheck == False and fieldCheck == False and inputCheck == False:

                    #Calculating the profile and add it to the list
                    transform_return = magicbox.transformation(coord_proc, method, direction)
                    coord_height_list = transform_return['coord_trans']

                    coord_trans.append(coord_height_list)
                    #CHANGE If checked, the upper right poitn has to be exportet as point
                    if height == True:
                        height_points.append(magicbox.height_points(coord_height_list))

                    if section == True:
                        cutting_line.append(sectionCalc(self, coord_proc, transform_return['cutting_start'],transform_return['linegress'], transform_return['ns_error']), )




            if profileCheck == False:
                '''Export the data'''
                #For exporting we need the data, the path and the crs of the input data
                export.export(coord_trans, self.dlg.outputPath.text(), selectedLayer.crs())
                #If points are checked, export them #CHANGE
                if height == True:
                    export.export_height(height_points, self.dlg.outputPath.text(), selectedLayer.crs())
                if section == True:
                    #if a profile is recommended, we have to export it. To make it easy to display everything, export left point first
                    printLogMessage(self,str(coord_proc[0][4]),'sec111t')
                    export.export_section(cutting_line, coord_proc[0][4],self.dlg.outputPath.text(), selectedLayer.crs())

                #Load the file to qgis automaticly
                layer = self.iface.addVectorLayer(self.dlg.outputPath.text(), "", "ogr")
                #CHANGE
                if height == True:
                    filename = self.dlg.outputPath.text().split(".shp")[0]
                    filename = filename + "_height.shp"
                    layer = self.iface.addVectorLayer(filename, "", "ogr")
                if section == True:
                    filename = self.dlg.outputPath.text().split(".shp")[0]
                    filename = filename + "_section.shp"
                    layer = self.iface.addVectorLayer(filename, "", "ogr")
                #if the loading of the layer fails, give a message
                if not layer:
                    criticalMessageToBar(self, 'Error', 'Failed to open '+self.dlg.outputPath.text())

    
            pass
Example #4
0
    def singleprofile(self, coord_proc, view_check, profile_name,
                      selection_check):
        # TODO: check for consistency before calculation
        # TODO: check for spatial consistency (no points should be more than x meters apart)
        errorCheck = False

        # check if actual profile has less then 4 points
        if len(coord_proc) <= 3:
            #if it is less, print error message
            criticalMessageToBar(
                self, 'Error',
                'A profile needs min. 4 points. Error on profile: ' +
                str(profile_name))
            printLogMessage(
                self, 'A profile needs min. 4 points. Error on profile: ' +
                str(profile_name), 'Error_LOG')
            #cancel execution of the script
            errorCheck = True

        # check if the view value is the same in all features
        if len(view_check) != 1:
            # if it is not the same, print error message
            criticalMessageToBar(
                self, 'Error',
                'The view column of your data is inconsistant (either non or two different views are present). Error on profile: '
                + str(profile_name))
            printLogMessage(
                self,
                'The view column of your data is inconsistant (either non or two different views are present). Error on profile: '
                + str(profile_name), 'Error_LOG')
            # cancel execution of the script
            errorCheck = True

        # check if the view is one of the four cardinal directions
        if view_check[0].upper() not in ["N", "E", "S", "W"]:
            # if it is not the same, print error message
            criticalMessageToBar(
                self, 'Error',
                'The view value is not one of the four cardinal directions. Error on profile: '
                + str(profile_name))
            printLogMessage(
                self,
                'The view value is not one of the four cardinal directions. Error on profile: '
                + str(profile_name), 'Error_LOG')
            # cancel execution of the script
            errorCheck = True

        #CHANGE1  check if the selection/use is 0 or 1
        for i in range(len(selection_check)):
            printLogMessage(self, str(selection_check[i]), 'sele')
            if str(selection_check[i]) not in ["1", "0"]:
                # if it is not the same, print error message
                criticalMessageToBar(
                    self, 'Error',
                    'Only 0 or 1 are allowed in the selection/use. Error on profile: '
                    + str(profile_name))
                printLogMessage(
                    self,
                    'Only 0 or 1 are allowed in the selection/use. Error on profile: : '
                    + str(profile_name), 'Error_LOG')
                # cancel execution of the script
                errorCheck = True

        # check if the coordinates x, y, z fall into 2 sigma range
        #instance a table like list of lists with i rows and j columns
        warning_message = []
        for i in range(3):
            xyz = []
            xyz_lower = []
            xyz_upper = []
            xyz = columnreader(coord_proc, i)
            xyz_lower = mean(xyz) - (2 * std(xyz))
            xyz_upper = mean(xyz) + (2 * std(xyz))
            for j in range(len(xyz)):
                if xyz[j] < xyz_lower or xyz[j] > xyz_upper:
                    #warning_message.append("Warning: Profile " )+ str(profile_name) + chr(120+i) + str(j) + 'excedes th 2 std interval of ' + chr(120+i))
                    criticalMessageToBar(
                        self, 'Warning',
                        'Warning: Profile ' + str(profile_name) + ': ' +
                        chr(120 + i) + 'Pt ' + str(j + 1) +
                        ' exceeds the 2std interval of ' + chr(120 + i))
                    printLogMessage(
                        self, 'Warning: Profile ' + str(profile_name) + ': ' +
                        chr(120 + i) + 'Pt ' + str(j + 1) +
                        ' exceeds the 2std interval of ' + chr(120 + i),
                        'Error_LOG')
        return errorCheck
Example #5
0
    def transformation(self, coord_proc, method, direction):
        #initialize the Errorhandler
        errorhandler = ErrorHandler(self)
        profilnr_proc = listToList(self, coord_proc, 4)

        fehler_check = False
        ns_fehler_vorhanden = ns_error_determination(self, coord_proc)
        if ns_fehler_vorhanden:
            # Profil um 45 Grad drehen
            rotationresult = rotation(self, coord_proc, 45, False)
            fehler_check = True
            for i in range(len(coord_proc)):
                coord_proc[i][0] = rotationresult['x_trans'][i]
                coord_proc[i][1] = rotationresult['y_trans'][i]
                coord_proc[i][2] = rotationresult['z_trans'][i]

        #write the x and v values in the corresponding lists

        # instantiate an empty list for the transformed coordinates and other values
        # instantiate lists for the x and y values
        x_coord_proc = listToList(self, coord_proc, 0)
        y_coord_proc = listToList(self, coord_proc, 1)
        z_coord_proc = listToList(self, coord_proc, 2)
        selection_proc = listToList(self, coord_proc, 5)

        id_proc = listToList(self, coord_proc, 6)
        rangcheck_orginal = []

        for i in range(len(coord_proc)):

            tmplist = []
            for k in range(len(coord_proc[i])):
                tmplist.append(coord_proc[i][k])
            rangcheck_orginal.append(tmplist)

        for coords in range(len(rangcheck_orginal)):
            del rangcheck_orginal[coords][5]
            del rangcheck_orginal[coords][4]
            del rangcheck_orginal[coords][3]
        #distanz zwischen den beiden Punkten oben CHANGE

        # create the valuelists that are used
#EINFUEGEN WENN Spalte = x verwenden
        xw = []
        yw = []
        #CHANGE
        xw_check = []
        yw_check = []
        for x in range(len(x_coord_proc)):
            #CHANGE Nur Auswahl zum berechnen der Steigung verwenden
            if (selection_proc[x] == 1):
                xw.append(x_coord_proc[x] - min(x_coord_proc))
                yw.append(y_coord_proc[x] - min(y_coord_proc))
            xw_check.append(x_coord_proc[x] - min(x_coord_proc))
            yw_check.append(y_coord_proc[x] - min(y_coord_proc))

        #QgsMessageLog.logMessage(str(xw), 'MyPlugin')
        #CHANGE
        #There is a problem with lingress if the points are nearly N-S oriented
        #To solve this, it is nessecary to change the input values of the regression
        # Calculate the regression for both directions

        linegress_x = scipy.stats.linregress(scipy.array(xw), scipy.array(yw))
        linegress_y = scipy.stats.linregress(scipy.array(yw), scipy.array(xw))

        # get the sum of residuals for both direction
        #We like to use the regression with less sum of the residuals
        res_x = self.calculateResidual(linegress_x, scipy.array(xw),
                                       scipy.array(yw), profilnr_proc[0])
        res_y = self.calculateResidual(linegress_y, scipy.array(yw),
                                       scipy.array(xw), profilnr_proc[0])

        if isnan(res_y) or res_x >= res_y:
            linegress = linegress_x
            slope = linegress[0]
        elif isnan(res_x) or res_x < res_y:
            linegress = linegress_y
            # if the linear regression with the changed values was used, the angle of the slope is rotated by 90°
            slope = tan((-90 - (((atan(linegress[0]) * 180) / pi))) * pi / 180)
        else:
            criticalMessageToBar(self, ' Error',
                                 'Calculation failed! Corrupt data!')
            sys.exitfunc()

        #CHANGE Check the distance with all points
        distance = errorhandler.calculateError(linegress, xw_check, yw_check,
                                               coord_proc[0][4])

        # calculate the degree of the slope
        #Defining the starting point for the export of the section
        slope_deg = 0.0
        #Variable for determining the paint direction of the cutting line
        cutting_start = ''
        if slope < 0 and coord_proc[0][3] in ["N", "E"]:
            slope_deg = 180 - fabs((atan(slope) * 180) / pi) * -1
            cutting_start = 'E'
        elif slope < 0 and coord_proc[0][3] in ["S", "W"]:
            slope_deg = fabs((atan(slope) * 180) / pi)
            cutting_start = 'W'
        elif slope > 0 and coord_proc[0][3] in ["S", "E"]:
            slope_deg = ((atan(slope) * 180) / pi) * -1
            cutting_start = 'W'
        elif slope > 0 and coord_proc[0][3] in ["N", "W"]:
            slope_deg = 180 - ((atan(slope) * 180) / pi)
            cutting_start = 'E'
        elif slope == 0 and coord_proc[0][3] == "N":
            slope_deg = 180
            cutting_start = 'E'

        # instantiate lists for the transformed coordinates
        x_trans = []
        y_trans = []
        z_trans = []
        first_rotationresult = rotation(self, coord_proc, slope_deg, True)
        for i in range(len(coord_proc)):
            x_trans.append(first_rotationresult['x_trans'][i])
            y_trans.append(first_rotationresult['y_trans'][i])
            z_trans.append(first_rotationresult['z_trans'][i])

        if direction == "absolute height":
            #To get an export for the absolute height it is necessary to rotate the profile like the horizontal way
            #and move it on the y-axis
            x_coord_proc = listToList(self, coord_proc, 0)
            y_coord_proc = listToList(self, coord_proc, 1)
            z_coord_proc = listToList(self, coord_proc, 2)
            # calculate the minimal x
            mean_x = mean(x_coord_proc)
            mean_y = mean(y_coord_proc)
            mean_z = mean(z_coord_proc)
            for i in range(len(x_trans)):
                x_trans[i] = x_trans[i] - mean_x
                z_trans[i] = z_trans[i] - mean_y + mean_z
            #  printLogMessage(self, str(x_coord_proc[i]), 'ttt')
            #   printLogMessage(self, str(x_trans[i]), 'ttt')
            #printLogMessage(self,str(min_x),'ttt')
            new_min_x = min(x_trans)
            for i in range(len(x_trans)):
                x_trans[i] = x_trans[i] + abs(new_min_x)

        # instantiate a list for the transformed coordinates
        coord_trans = []
        #CHANGE
        rangcheck_trans = []
        # build the finished list
        for i in range(len(coord_proc)):
            coord_trans.append([
                x_trans[i], y_trans[i], z_trans[i], coord_proc[i][4],
                coord_proc[i][2], distance[i], selection_proc[i], id_proc[i]
            ])
            rangcheck_trans.append([x_trans[i], z_trans[i], y_trans[i]])

        #If the aim is to get the view of the surface, the x-axis has to be rotated aswell
        if method == "surface":
            # calculating the slope, therefore preparing lists
            z_yw = []
            z_zw = []
            for i in range(len(coord_proc)):
                z_yw.append(y_trans[i] - min(y_trans + z_trans))
                z_zw.append(z_trans[i] - min(y_trans + z_trans))

            # actual calculation of the slope using the linear regression again
            z_slope = scipy.stats.linregress(scipy.array(z_yw),
                                             scipy.array(z_zw))[0]

            # transform the radians of the slope into degrees
            z_slope_deg = 0.0
            if z_slope < 0:
                z_slope_deg = -(90 - fabs(((atan(z_slope) * 180) / pi)))
            elif z_slope > 0:
                z_slope_deg = 90 - ((atan(z_slope) * 180) / pi)
            elif z_slope == 0:
                z_slope_deg = 0.0

            # calculate the centerpoint
            z_center_y = mean(y_trans)
            z_center_z = mean(z_trans)

            # rewrite the lists for the y and z values
            y_trans = []
            z_trans = []
            for i in range(len(coord_trans)):
                y_trans.append(z_center_y + (coord_trans[i][1] - z_center_y) *
                               cos(z_slope_deg / 180 * pi) -
                               (coord_trans[i][2] - z_center_z) *
                               sin(z_slope_deg / 180 * pi))
                z_trans.append(z_center_z + (coord_trans[i][1] - z_center_y) *
                               sin(z_slope_deg / 180 * pi) +
                               (coord_trans[i][2] - z_center_z) *
                               cos(z_slope_deg / 180 * pi))

            # empty and rewrite the output list
            coord_trans = []
            rangcheck_trans = []
            for i in range(len(coord_proc)):
                # CHANGE
                coord_trans.append([
                    x_trans[i], y_trans[i], z_trans[i], coord_proc[i][4],
                    coord_proc[i][2], distance[i], selection_proc[i],
                    id_proc[i]
                ])
                rangcheck_trans.append([x_trans[i], z_trans[i], y_trans[i]])

        # If the direction is in the "original" setting, the points have to be rotated back to their original orientation
        if direction == "original":
            # the rotation angle is the negative angle of the first rotation
            if fehler_check == True:
                y_slope_deg = -slope_deg - 45

            else:
                y_slope_deg = -slope_deg

            # get the centerpoint
            y_center_x = mean(x_trans)
            y_center_z = mean(z_trans)

            #rewrite the lists for the x and z values
            x_trans = []
            z_trans = []
            for i in range(len(coord_trans)):
                x_trans.append(y_center_x + (coord_trans[i][0] - y_center_x) *
                               cos(y_slope_deg / 180 * pi) -
                               (coord_trans[i][2] - y_center_z) *
                               sin(y_slope_deg / 180 * pi))
                z_trans.append(y_center_z + (coord_trans[i][0] - y_center_x) *
                               sin(y_slope_deg / 180 * pi) +
                               (coord_trans[i][2] - y_center_z) *
                               cos(y_slope_deg / 180 * pi))

            # empty and rewrite the output list
            coord_trans = []
            rangcheck_trans = []
            for i in range(len(coord_proc)):
                # CHANGE
                coord_trans.append([
                    x_trans[i], y_trans[i], z_trans[i], coord_proc[i][4],
                    coord_proc[i][2], distance[i], selection_proc[i],
                    id_proc[i]
                ])
                rangcheck_trans.append([x_trans[i], z_trans[i], y_trans[i]])

        #change

        # check the distances of the outter points from the old points and the converted ones
        original_outer_points = self.outer_profile_points(coord_proc)
        original_distance = self.calculate_distance_from_outer_profile_points_orgiginal(
            original_outer_points)

        new_outer_points = []
        for point in coord_trans:
            if point[7] == original_outer_points[0][6] or point[
                    7] == original_outer_points[1][6]:
                new_outer_points.append(point)
        new_distance = self.calculate_distance_from_outer_profile_points_proc(
            new_outer_points)

        printLogMessage(self, 'PR:' + str(coord_proc[0][4]), 'Distance')
        printLogMessage(self, 'Original Distance: ' + str(original_distance),
                        'Distance')
        printLogMessage(self, 'New Distance: ' + str(new_distance), 'Distance')
        printLogMessage(
            self,
            'Diff. Distance: ' + str(abs(original_distance - new_distance)),
            'Distance')

        if abs(original_distance - new_distance) > 0.01:
            criticalMessageToBar(
                self, 'Error',
                'Profile was calculated incorrect (1cm acc.) See Log-Window: '
                + str(str(coord_proc[0][4])))
            printLogMessage(self, 'DISTANCE WARNING!', 'Distance')

        return {
            'coord_trans': coord_trans,
            'cutting_start': cutting_start,
            'linegress': linegress,
            'ns_error': ns_fehler_vorhanden
        }