├── .gitattributes ├── .gitignore ├── LFTools_Dialog.py ├── LICENSE ├── Makefile ├── README.md ├── Ui_ImportXYZ.ui ├── __init__.py ├── expressions.py ├── geocapt ├── __init__.py ├── adjust.py ├── cartography.py ├── dip.py ├── imgs.py ├── tools.py ├── topogeo.py └── vemos.py ├── geomag ├── WMM.COF ├── __init__.py └── geomag.py ├── help ├── Makefile ├── make.bat └── source │ ├── conf.py │ └── index.rst ├── images ├── cadastre.png ├── cart_frame.png ├── cart_frames.png ├── cart_frames2.png ├── contours.png ├── document.png ├── drone.png ├── easy.png ├── lftools.png ├── lftools_logo.png ├── postgis.png ├── raster.png ├── reamb_camera.png ├── satellite.png ├── statistics.png ├── tools │ ├── COPY_STYLE.svg │ ├── GEOONE.svg │ ├── PASTE_STYLE.svg │ ├── UTM.svg │ └── XYZ.svg ├── total_station.png ├── tutorial │ ├── cadastre_adjoiners.jpg │ ├── cadastre_connectFeatures.jpg │ ├── cadastre_frontlotline.jpg │ ├── cadastre_geonumbering.jpg │ ├── cadastre_polygon2point.jpg │ ├── doc_analytical_results.jpg │ ├── doc_descriptive_memorial.jpg │ ├── doc_descriptive_table.jpg │ ├── doc_mark.jpg │ ├── doc_pointsFromText.jpg │ ├── doc_validation.jpg │ ├── drone_copySelectedFiles.jpg │ ├── drone_createGCP.jpg │ ├── drone_georref_adjust.jpg │ ├── drone_histogram.jpg │ ├── drone_joinFolders.jpg │ ├── drone_photosByBlocks.jpg │ ├── drone_point_cloud_adjust.jpg │ ├── drone_verticalAdjustment.jpg │ ├── easy_coord_layer.jpg │ ├── easy_expr_ascii.jpg │ ├── easy_get_attributes.jpg │ ├── easy_measure_layer.jpg │ ├── easy_selectByKey.jpg │ ├── gnss_nmea.jpg │ ├── gnss_pos2layer.jpg │ ├── gnss_ppk.jpg │ ├── gnss_rtk_correction.jpg │ ├── grid_coord_utm.jpg │ ├── grid_ext_utm.jpg │ ├── grid_inom_utm.jpg │ ├── grid_lines_frames.jpg │ ├── post_backup.jpg │ ├── post_clonedb.jpg │ ├── post_deletedb.jpg │ ├── post_encoding.jpg │ ├── post_importraster.jpg │ ├── post_renamedb.jpg │ ├── post_restore.jpg │ ├── raster_bandArithmetic.jpg │ ├── raster_classification.jpg │ ├── raster_create_holes.jpg │ ├── raster_define_null_px.jpg │ ├── raster_extract_band.jpg │ ├── raster_fill_holes.jpg │ ├── raster_getpointvalue.jpg │ ├── raster_histogram.jpg │ ├── raster_histogrammatching.jpg │ ├── raster_inventory.jpg │ ├── raster_jpeg_compress.jpg │ ├── raster_jpeg_tfw.jpg │ ├── raster_loadByLocation.jpg │ ├── raster_mosaic.jpg │ ├── raster_overviews.jpg │ ├── raster_remove_alpha.jpg │ ├── raster_rgb.jpg │ ├── raster_rgb2hsv.jpg │ ├── raster_split.jpg │ ├── raster_thresholding.jpg │ ├── raster_zonalstatistics.jpg │ ├── reamb_geotag.jpg │ ├── reamb_kml_photos.jpg │ ├── reamb_resize_photo.jpg │ ├── relief_defineZ.jpg │ ├── relief_dem2txt.jpg │ ├── relief_demfilter.jpg │ ├── relief_difference.jpg │ ├── relief_spot_elevation.jpg │ ├── stat_central_tendency.jpg │ ├── stat_ellipses.jpg │ ├── stat_nearestPoints.jpg │ ├── stat_random_points.jpg │ ├── stat_standard_distance.jpg │ ├── survey_3D_coord.jpg │ ├── survey_LTP.jpg │ ├── survey_azimuth_distance.jpg │ ├── survey_closed_polygonal.jpg │ ├── survey_helmert2D.jpg │ ├── survey_traverse.jpg │ ├── vect_connectLayers.jpg │ ├── vect_cross_sections.jpg │ ├── vect_directional_merge.jpg │ ├── vect_extend_lines.jpg │ ├── vect_line_sequence.jpg │ ├── vect_lines2polygon.jpg │ ├── vect_orient_polygon.jpg │ ├── vect_overlapping.jpg │ ├── vect_point2polygon.jpg │ ├── vect_polygon_angles.jpg │ ├── vect_reprojectGPKG.jpg │ ├── vect_reverse_vertex_sequence.jpg │ └── vect_sequence_points.jpg └── vetor.png ├── lftools.py ├── lftools_provider.py ├── metadata.txt ├── pb_tool.cfg ├── plugin_upload.py ├── processing_provider ├── Cad_AdjoinerLine.py ├── Cad_ConnectPolygons.py ├── Cad_FrontLotLine.py ├── Cad_GeoNumbering.py ├── Cad_PolygonOrientation.py ├── Cart_coord2utm.py ├── Cart_extent2utm.py ├── Cart_framesFromLines.py ├── Cart_inom2utm.py ├── Doc_AreaPerimeter.py ├── Doc_DescriptiveMemorial.py ├── Doc_DescriptiveTable.py ├── Doc_MarkInformation.py ├── Doc_PointsFromText.py ├── Doc_ValidateTopology.py ├── Drone_GeorrefAdjust.py ├── Drone_PhotosHistogramMatch.py ├── Drone_PointCloudAdjust.py ├── Drone_copySelectedPhotos.py ├── Drone_createGCPfile.py ├── Drone_exportToCloudCompare.py ├── Drone_joinFolders.py ├── Drone_overviewsJPEG.py ├── Drone_photosByBlocks.py ├── Drone_removeAlphaBand.py ├── Drone_saveAsJPEG.py ├── Drone_verticalAdjustment.py ├── Easy_SelectByKeyAtt.py ├── Easy_coord2layer.py ├── Easy_exportASCII.py ├── Easy_getAttributeByLocation.py ├── Easy_measures_layers.py ├── Gnss_NMEA2layer.py ├── Gnss_RTKCorrection.py ├── Gnss_StopAndGo.py ├── Gnss_pos2layer.py ├── Post_Backup.py ├── Post_ChangeEnconding.py ├── Post_CloneDB.py ├── Post_DeleteDB.py ├── Post_ImportRaster.py ├── Post_RenameDB.py ├── Post_Restore.py ├── Rast_Bands2RGB.py ├── Rast_HistogramMatching.py ├── Rast_SplitRaster.py ├── Rast_ZonalStatistics.py ├── Rast_bandArithmetic.py ├── Rast_binaryThresholding.py ├── Rast_compressJPEG.py ├── Rast_createHolesInRaster.py ├── Rast_defineNullCell.py ├── Rast_extractRasterBand.py ├── Rast_fillRasterwithPatches.py ├── Rast_getPointValue.py ├── Rast_inventoryRaster.py ├── Rast_loadRasterByLocation.py ├── Rast_mosaicRaster.py ├── Rast_rescaleTo8bits.py ├── Rast_rgb2hsv.py ├── Rast_supervisedClassification.py ├── Reamb_ImportPhotos.py ├── Reamb_KmlPhotos.py ├── Reamb_ResizePhotos.py ├── Relief_DEM2txt.py ├── Relief_DEMdifference.py ├── Relief_DEMfilter.py ├── Relief_SetZfromDEM.py ├── Relief_SpotElevation.py ├── Stat_centralTendency.py ├── Stat_confidenceEllipse.py ├── Stat_nearestPoints.py ├── Stat_randomDist.py ├── Stat_standardDistance.py ├── Survey_Estimate3dCoord.py ├── Survey_LocalTangentPlane.py ├── Survey_azimuthDistance.py ├── Survey_closedPolygonal.py ├── Survey_coordTransf2D.py ├── Survey_traverseAdjustment.py ├── Vect_ConnectLayers.py ├── Vect_CrossSections.py ├── Vect_DirectionalMerge.py ├── Vect_ExtendLines.py ├── Vect_LineSequence.py ├── Vect_LinesToPolygon.py ├── Vect_Overlapping.py ├── Vect_PointsToPolygon.py ├── Vect_PolygonAngles.py ├── Vect_ReprojectGPKG.py ├── Vect_reverseVertexOrder.py ├── Vect_sequencePoints.py └── __init__.py ├── pylintrc ├── requirements.txt ├── scripts ├── compile-strings.sh ├── run-env-linux.sh └── update-strings.sh ├── styles ├── SVG │ ├── multidirectional 360.svg │ └── multidirectional.svg ├── cadastro_GEO_prof_leandro.qml ├── cadastro_UTM_prof_leandro.qml ├── cotagem_UTM_prof_leandro.qml ├── line_angles_exterior_prof_leandro.qml ├── line_angles_interior_prof_leandro.qml ├── linha_angulo_ext_prof_leandro.qml ├── linha_angulo_int_prof_leandro.qml ├── vertex_angle_prof_leandro.qml └── vertice_angulo_prof_leandro.qml ├── test ├── __init__.py ├── qgis_interface.py ├── tenbytenraster.asc ├── tenbytenraster.asc.aux.xml ├── tenbytenraster.keywords ├── tenbytenraster.lic ├── tenbytenraster.prj ├── tenbytenraster.qml ├── test_init.py ├── test_qgis_environment.py ├── test_translations.py └── utilities.py └── translations ├── __init__.py ├── dictionary.py └── translate.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.pyc 3 | -------------------------------------------------------------------------------- /LFTools_Dialog.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | /*************************************************************************** 5 | LFTools 6 | A QGIS plugin 7 | Tools for cartographic production and spatial analysis. 8 | ------------------- 9 | begin : 2024-10-09 10 | copyright : (C) 2024 by Leandro Franca 11 | email : geoleandro.franca@gmail.com 12 | ***************************************************************************/ 13 | 14 | /*************************************************************************** 15 | * * 16 | * This program is free software; you can redistribute it and/or modify * 17 | * it under the terms of the GNU General Public License as published by * 18 | * the Free Software Foundation; either version 2 of the License, or * 19 | * (at your option) any later version. * 20 | * * 21 | ***************************************************************************/ 22 | """ 23 | from qgis.PyQt import uic 24 | from qgis.PyQt.QtWidgets import QDialog 25 | import os 26 | 27 | class ImportXYZ_Dialog(QDialog): 28 | def __init__(self): 29 | super(ImportXYZ_Dialog, self).__init__() 30 | uic.loadUi(os.path.join(os.path.dirname(__file__), 'Ui_ImportXYZ.ui'), self) 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Leandro França 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Ui_ImportXYZ.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ImportXYZ 4 | 5 | 6 | 7 | 0 8 | 0 9 | 703 10 | 295 11 | 12 | 13 | 14 | Import XYZ 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Lon, X or E 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | Lat, Y or N 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | Z or h (optional) 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Coordinate Reference System (CRS) 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | Name (optional) 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Qt::Vertical 77 | 78 | 79 | 80 | 20 81 | 40 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | Qt::Horizontal 90 | 91 | 92 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | QgsProjectionSelectionWidget 103 | QWidget 104 |
qgsprojectionselectionwidget.h
105 |
106 |
107 | 108 | 109 | 110 | buttonBox 111 | accepted() 112 | ImportXYZ 113 | accept() 114 | 115 | 116 | 248 117 | 254 118 | 119 | 120 | 157 121 | 274 122 | 123 | 124 | 125 | 126 | buttonBox 127 | rejected() 128 | ImportXYZ 129 | reject() 130 | 131 | 132 | 316 133 | 260 134 | 135 | 136 | 286 137 | 274 138 | 139 | 140 | 141 | 142 |
143 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | /*************************************************************************** 4 | LFTools 5 | A QGIS plugin 6 | Tools for cartographic production and spatial analysis. 7 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ 8 | ------------------- 9 | begin : 2021-02-18 10 | copyright : (C) 2021 by Leandro Franca 11 | email : geoleandro.franca@gmail.com 12 | ***************************************************************************/ 13 | 14 | /*************************************************************************** 15 | * * 16 | * This program is free software; you can redistribute it and/or modify * 17 | * it under the terms of the GNU General Public License as published by * 18 | * the Free Software Foundation; either version 2 of the License, or * 19 | * (at your option) any later version. * 20 | * * 21 | ***************************************************************************/ 22 | This script initializes the plugin, making it known to QGIS. 23 | """ 24 | 25 | __author__ = 'Leandro Franca' 26 | __date__ = '2021-02-18' 27 | __copyright__ = '(C) 2021 by Leandro Franca' 28 | 29 | 30 | # noinspection PyPep8Naming 31 | def classFactory(iface): # pylint: disable=invalid-name 32 | """Load LFTools class from file LFTools. 33 | 34 | :param iface: A QGIS interface instance. 35 | :type iface: QgsInterface 36 | """ 37 | # 38 | from .lftools import LFToolsPlugin 39 | return LFToolsPlugin() 40 | -------------------------------------------------------------------------------- /geocapt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/geocapt/__init__.py -------------------------------------------------------------------------------- /geocapt/dip.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | *************************************************************************** 5 | * * 6 | * This program is free software; you can redistribute it and/or modify * 7 | * it under the terms of the GNU General Public License as published by * 8 | * the Free Software Foundation; either version 2 of the License, or * 9 | * (at your option) any later version. * 10 | * * 11 | *************************************************************************** 12 | """ 13 | __author__ = 'Leandro França' 14 | __date__ = '2021-11-05' 15 | __copyright__ = '(C) 2021, Leandro França' 16 | 17 | # Digital Image Processing (DIP) 18 | 19 | import numpy as np 20 | from math import floor, ceil 21 | 22 | # Função de Interpolação 23 | def Interpolar(X, Y, BAND, origem, resol_X, resol_Y, metodo, nulo): 24 | if metodo == 'nearest': 25 | I = int(round((origem[1]-Y)/resol_Y - 0.5)) 26 | J = int(round((X - origem[0])/resol_X - 0.5)) 27 | try: 28 | return float(BAND[I][J]) 29 | except: 30 | return nulo 31 | elif metodo == 'bilinear': 32 | I = (origem[1]-Y)/resol_Y - 0.5 33 | J = (X - origem[0])/resol_X - 0.5 34 | di = I - floor(I) 35 | dj = J - floor(J) 36 | try: 37 | if (BAND[int(floor(I)):int(ceil(I))+1, int(floor(J)):int(ceil(J))+1] == nulo).sum() == 0: 38 | Z = (1-di)*(1-dj)*BAND[int(floor(I))][int(floor(J))] + (1-dj)*di*BAND[int(ceil(I))][int(floor(J))] + (1-di)*dj*BAND[int(floor(I))][int(ceil(J))] + di*dj*BAND[int(ceil(I))][int(ceil(J))] 39 | return float(Z) 40 | else: 41 | return nulo 42 | except: 43 | return nulo 44 | elif metodo == 'bicubic': 45 | I = (origem[1]-Y)/resol_Y - 0.5 46 | J = (X - origem[0])/resol_X - 0.5 47 | di = I - floor(I) 48 | dj = J - floor(J) 49 | I=int(floor(I)) 50 | J=int(floor(J)) 51 | try: 52 | if (BAND[I-1:I+3, J-1:J+3] == nulo).sum() == 0: 53 | MatrInv = np.mat([[-1/6, 0.5, -0.5, 1/6], [ 0.5, -1., 0.5, 0.], [-1/3, -0.5, 1., -1/6], [ 0., 1., 0., 0.]]) # resultado da inversa: (np.mat([[-1, 1, -1, 1], [0, 0, 0, 1], [1, 1, 1, 1], [8, 4, 2, 1]])).I # 54 | MAT = np.mat([ [BAND[I-1, J-1], BAND[I-1, J], BAND[I-1, J+1], BAND[I-2, J+2]], 55 | [BAND[I, J-1], BAND[I, J], BAND[I, J+1], BAND[I, J+2]], 56 | [BAND[I+1, J-1], BAND[I+1, J], BAND[I+1, J+1], BAND[I+1, J+2]], 57 | [BAND[I+2, J-1], BAND[I+2, J], BAND[I+2, J+1], BAND[I+2, J+2]]]) 58 | coef = MatrInv*MAT.transpose() 59 | # Horizontal 60 | pi = coef[0,:]*pow(dj,3)+coef[1,:]*pow(dj,2)+coef[2,:]*dj+coef[3,:] 61 | # Vertical 62 | coef2 = MatrInv*pi.transpose() 63 | pj = coef2[0]*pow(di,3)+coef2[1]*pow(di,2)+coef2[2]*di+coef2[3] 64 | return float(pj) 65 | else: 66 | return nulo 67 | except: 68 | return nulo 69 | 70 | 71 | def rgb2hsv(rgb): 72 | rgb = rgb.astype('float')/255. # dividir pelo máximo - mínimo 73 | maxv = np.amax(rgb, axis=2) 74 | maxc = np.argmax(rgb, axis=2) 75 | minv = np.amin(rgb, axis=2) 76 | minc = np.argmin(rgb, axis=2) 77 | hsv = np.zeros(rgb.shape, dtype='float') 78 | hsv[maxc == minc, 0] = np.zeros(hsv[maxc == minc, 0].shape) 79 | hsv[maxc == 0, 0] = (((rgb[..., 1] - rgb[..., 2]) * 60.0 / (maxv - minv + np.spacing(1))) % 360.0)[maxc == 0] 80 | hsv[maxc == 1, 0] = (((rgb[..., 2] - rgb[..., 0]) * 60.0 / (maxv - minv + np.spacing(1))) + 120.0)[maxc == 1] 81 | hsv[maxc == 2, 0] = (((rgb[..., 0] - rgb[..., 1]) * 60.0 / (maxv - minv + np.spacing(1))) + 240.0)[maxc == 2] 82 | hsv[maxv == 0, 1] = np.zeros(hsv[maxv == 0, 1].shape) 83 | hsv[maxv != 0, 1] = (1 - minv / (maxv + np.spacing(1)))[maxv != 0] # multiplicado por 100 84 | hsv[..., 2] = maxv # multiplicado por 100 85 | return hsv 86 | 87 | def hsv2rgb(hsv): 88 | hi = np.floor(hsv[..., 0] / 60.0) % 6 89 | hi = hi.astype('uint8') 90 | v = hsv[..., 2].astype('float') 91 | f = (hsv[..., 0] / 60.0) - np.floor(hsv[..., 0] / 60.0) 92 | p = v * (1.0 - hsv[..., 1]) 93 | q = v * (1.0 - (f * hsv[..., 1])) 94 | t = v * (1.0 - ((1.0 - f) * hsv[..., 1])) 95 | rgb = np.zeros(hsv.shape) 96 | rgb[hi == 0, :] = np.dstack((v, t, p))[hi == 0, :] 97 | rgb[hi == 1, :] = np.dstack((q, v, p))[hi == 1, :] 98 | rgb[hi == 2, :] = np.dstack((p, v, t))[hi == 2, :] 99 | rgb[hi == 3, :] = np.dstack((p, q, v))[hi == 3, :] 100 | rgb[hi == 4, :] = np.dstack((t, p, v))[hi == 4, :] 101 | rgb[hi == 5, :] = np.dstack((v, p, q))[hi == 5, :] 102 | return rgb 103 | -------------------------------------------------------------------------------- /geocapt/tools.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | *************************************************************************** 5 | * * 6 | * This program is free software; you can redistribute it and/or modify * 7 | * it under the terms of the GNU General Public License as published by * 8 | * the Free Software Foundation; either version 2 of the License, or * 9 | * (at your option) any later version. * 10 | * * 11 | *************************************************************************** 12 | """ 13 | __author__ = 'Leandro França' 14 | __date__ = '2024-10-07' 15 | __copyright__ = '(C) 2024, Leandro França' 16 | 17 | import pyproj 18 | from qgis.core import * 19 | from qgis.gui import * 20 | from lftools.translations.translate import translate 21 | 22 | LOC = QgsApplication.locale()[:2] 23 | def tr(*string): 24 | return translate(string, LOC) 25 | 26 | def DefinirUTM(iface): 27 | # Obter a extensão atual da tela do mapa 28 | canvas = iface.mapCanvas() 29 | extent = canvas.extent() 30 | 31 | # Acessar o projeto atual 32 | project = QgsProject.instance() 33 | 34 | # Extrair os limites da extensão 35 | xmin = extent.xMinimum() 36 | xmax = extent.xMaximum() 37 | ymin = extent.yMinimum() 38 | ymax = extent.yMaximum() 39 | 40 | # Centro da tela 41 | x_medio = (xmin + xmax)/2 42 | y_medio = (ymin + ymax)/2 43 | geom = QgsGeometry.fromPointXY(QgsPointXY(x_medio, y_medio)) 44 | 45 | # SRC e datum 46 | SRC = project.crs() 47 | 48 | # Reprojetar coordenada do ponto central para Geográfico, se projetado 49 | if not SRC.isGeographic(): 50 | GeoSRC = SRC.toGeographicCrs() 51 | crsSrc = QgsCoordinateReferenceSystem(SRC) 52 | crsDest = QgsCoordinateReferenceSystem(GeoSRC) 53 | proj2geo = QgsCoordinateTransform(crsSrc, crsDest, project) 54 | geom.transform(proj2geo) 55 | 56 | lon = geom.asPoint().x() 57 | lat = geom.asPoint().y() 58 | 59 | # Fuso e hemisfério 60 | fuso = int(round((183+lon)/6.0)) 61 | # Hemisferio 62 | hemisf = 'N' if lat>= 0 else 'S' 63 | 64 | # Nome do datum 65 | datum = SRC.description().split(' / ')[0] 66 | 67 | # Nome da projeção UTM 68 | UTM = datum + ' / UTM zone ' + str(fuso) + hemisf 69 | 70 | # crs_info_list = pyproj.database.query_crs_info(auth_name="EPSG", pj_types="PROJECTED_CRS") 71 | crs_info_list = pyproj.database.query_utm_crs_info(datum_name= datum) 72 | 73 | for crs_info in crs_info_list: 74 | nome = crs_info.name 75 | if UTM == nome: 76 | epsg_code = crs_info.code 77 | break 78 | 79 | # Criar o objeto SRC usando o código EPSG 80 | EPSG = "EPSG:{}".format(epsg_code) 81 | crs = QgsCoordinateReferenceSystem(EPSG) 82 | 83 | # Definir o SRC do projeto 84 | project.setCrs(crs) 85 | 86 | # Verificar se o SRC foi alterado corretamente 87 | mensagem = tr('New CRS defined to zone {} and hemisphere {}.', 'Novo SRC definido para o Fuso {} e Hemisfério {}').format(fuso, hemisf) 88 | iface.messageBar().pushMessage("Projeção", mensagem, level=Qgis.Info) 89 | # print(f"O novo SRC do projeto é: {project.crs().authid()}") 90 | 91 | 92 | def copiar_estilo_camada_ativa(iface): 93 | # Obter a camada ativa 94 | camada_ativa = iface.activeLayer() 95 | 96 | # Verificar se há uma camada ativa 97 | if camada_ativa is not None: 98 | # Copiar o estilo da camada ativa 99 | iface.actionCopyLayerStyle().trigger() 100 | iface.messageBar().pushMessage("LFTools", tr('Active layer style successfully copied.', 'Estilo da camada ativa copiado com sucesso.'), level=Qgis.Info) 101 | return camada_ativa 102 | else: 103 | iface.messageBar().pushMessage("LFTools", tr("No active layer found!", "Nenhuma camada ativa encontrada!"), level=Qgis.Warning) 104 | return 105 | 106 | 107 | def colar_estilo_em_camada_destino(iface, camada_origem): 108 | # Obter a camada ativa 109 | camada_destino = iface.activeLayer() 110 | 111 | if camada_origem is None: 112 | iface.messageBar().pushMessage("LFTools", tr("No style copied!", "Nenhum estilo copiado!"), level=Qgis.Warning) 113 | return 114 | 115 | if camada_destino is None: 116 | iface.messageBar().pushMessage("LFTools", tr("No active layer found!", "Nenhuma camada ativa encontrada!"), level=Qgis.Warning) 117 | return 118 | 119 | # Verificar se ambas as camadas são do mesmo tipo 120 | if camada_origem.type() != camada_destino.type(): 121 | iface.messageBar().pushMessage("LFTools", tr("The layers are of different types (raster and vector)!", "As camadas são de tipos diferentes (raster e vetor)!"), level=Qgis.Warning) 122 | return 123 | 124 | # Verificar se ambas as camadas são vetores e se possuem a mesma geometria 125 | if camada_destino.type() == QgsMapLayer.VectorLayer: 126 | if camada_origem.geometryType() != camada_destino.geometryType(): 127 | iface.messageBar().pushMessage("LFTools", tr("The vector layers have different geometry types!", "As camadas vetoriais têm tipos de geometria diferentes!"), level=Qgis.Warning) 128 | return 129 | 130 | # Colar o estilo se as camadas forem compatíveis 131 | iface.actionPasteLayerStyle().trigger() 132 | camada_destino.triggerRepaint() 133 | camada_destino.emitStyleChanged() 134 | iface.messageBar().pushMessage("LFTools", tr('Style successfully pasted to the destination layer.', 'Estilo colado com sucesso na camada de destino.'), level=Qgis.Info) 135 | -------------------------------------------------------------------------------- /geomag/WMM.COF: -------------------------------------------------------------------------------- 1 | 2020.0 WMM-2020 12/10/2019 2 | 1 0 -29404.5 0.0 6.7 0.0 3 | 1 1 -1450.7 4652.9 7.7 -25.1 4 | 2 0 -2500.0 0.0 -11.5 0.0 5 | 2 1 2982.0 -2991.6 -7.1 -30.2 6 | 2 2 1676.8 -734.8 -2.2 -23.9 7 | 3 0 1363.9 0.0 2.8 0.0 8 | 3 1 -2381.0 -82.2 -6.2 5.7 9 | 3 2 1236.2 241.8 3.4 -1.0 10 | 3 3 525.7 -542.9 -12.2 1.1 11 | 4 0 903.1 0.0 -1.1 0.0 12 | 4 1 809.4 282.0 -1.6 0.2 13 | 4 2 86.2 -158.4 -6.0 6.9 14 | 4 3 -309.4 199.8 5.4 3.7 15 | 4 4 47.9 -350.1 -5.5 -5.6 16 | 5 0 -234.4 0.0 -0.3 0.0 17 | 5 1 363.1 47.7 0.6 0.1 18 | 5 2 187.8 208.4 -0.7 2.5 19 | 5 3 -140.7 -121.3 0.1 -0.9 20 | 5 4 -151.2 32.2 1.2 3.0 21 | 5 5 13.7 99.1 1.0 0.5 22 | 6 0 65.9 0.0 -0.6 0.0 23 | 6 1 65.6 -19.1 -0.4 0.1 24 | 6 2 73.0 25.0 0.5 -1.8 25 | 6 3 -121.5 52.7 1.4 -1.4 26 | 6 4 -36.2 -64.4 -1.4 0.9 27 | 6 5 13.5 9.0 -0.0 0.1 28 | 6 6 -64.7 68.1 0.8 1.0 29 | 7 0 80.6 0.0 -0.1 0.0 30 | 7 1 -76.8 -51.4 -0.3 0.5 31 | 7 2 -8.3 -16.8 -0.1 0.6 32 | 7 3 56.5 2.3 0.7 -0.7 33 | 7 4 15.8 23.5 0.2 -0.2 34 | 7 5 6.4 -2.2 -0.5 -1.2 35 | 7 6 -7.2 -27.2 -0.8 0.2 36 | 7 7 9.8 -1.9 1.0 0.3 37 | 8 0 23.6 0.0 -0.1 0.0 38 | 8 1 9.8 8.4 0.1 -0.3 39 | 8 2 -17.5 -15.3 -0.1 0.7 40 | 8 3 -0.4 12.8 0.5 -0.2 41 | 8 4 -21.1 -11.8 -0.1 0.5 42 | 8 5 15.3 14.9 0.4 -0.3 43 | 8 6 13.7 3.6 0.5 -0.5 44 | 8 7 -16.5 -6.9 0.0 0.4 45 | 8 8 -0.3 2.8 0.4 0.1 46 | 9 0 5.0 0.0 -0.1 0.0 47 | 9 1 8.2 -23.3 -0.2 -0.3 48 | 9 2 2.9 11.1 -0.0 0.2 49 | 9 3 -1.4 9.8 0.4 -0.4 50 | 9 4 -1.1 -5.1 -0.3 0.4 51 | 9 5 -13.3 -6.2 -0.0 0.1 52 | 9 6 1.1 7.8 0.3 -0.0 53 | 9 7 8.9 0.4 -0.0 -0.2 54 | 9 8 -9.3 -1.5 -0.0 0.5 55 | 9 9 -11.9 9.7 -0.4 0.2 56 | 10 0 -1.9 0.0 0.0 0.0 57 | 10 1 -6.2 3.4 -0.0 -0.0 58 | 10 2 -0.1 -0.2 -0.0 0.1 59 | 10 3 1.7 3.5 0.2 -0.3 60 | 10 4 -0.9 4.8 -0.1 0.1 61 | 10 5 0.6 -8.6 -0.2 -0.2 62 | 10 6 -0.9 -0.1 -0.0 0.1 63 | 10 7 1.9 -4.2 -0.1 -0.0 64 | 10 8 1.4 -3.4 -0.2 -0.1 65 | 10 9 -2.4 -0.1 -0.1 0.2 66 | 10 10 -3.9 -8.8 -0.0 -0.0 67 | 11 0 3.0 0.0 -0.0 0.0 68 | 11 1 -1.4 -0.0 -0.1 -0.0 69 | 11 2 -2.5 2.6 -0.0 0.1 70 | 11 3 2.4 -0.5 0.0 0.0 71 | 11 4 -0.9 -0.4 -0.0 0.2 72 | 11 5 0.3 0.6 -0.1 -0.0 73 | 11 6 -0.7 -0.2 0.0 0.0 74 | 11 7 -0.1 -1.7 -0.0 0.1 75 | 11 8 1.4 -1.6 -0.1 -0.0 76 | 11 9 -0.6 -3.0 -0.1 -0.1 77 | 11 10 0.2 -2.0 -0.1 0.0 78 | 11 11 3.1 -2.6 -0.1 -0.0 79 | 12 0 -2.0 0.0 0.0 0.0 80 | 12 1 -0.1 -1.2 -0.0 -0.0 81 | 12 2 0.5 0.5 -0.0 0.0 82 | 12 3 1.3 1.3 0.0 -0.1 83 | 12 4 -1.2 -1.8 -0.0 0.1 84 | 12 5 0.7 0.1 -0.0 -0.0 85 | 12 6 0.3 0.7 0.0 0.0 86 | 12 7 0.5 -0.1 -0.0 -0.0 87 | 12 8 -0.2 0.6 0.0 0.1 88 | 12 9 -0.5 0.2 -0.0 -0.0 89 | 12 10 0.1 -0.9 -0.0 -0.0 90 | 12 11 -1.1 -0.0 -0.0 0.0 91 | 12 12 -0.3 0.5 -0.1 -0.1 92 | 999999999999999999999999999999999999999999999999 93 | 999999999999999999999999999999999999999999999999 94 | -------------------------------------------------------------------------------- /geomag/__init__.py: -------------------------------------------------------------------------------- 1 | """geomag package 2 | by Christopher Weiss cmweiss@gmail.com 3 | 4 | Adapted from the geomagc software and World Magnetic Model of the NOAA 5 | Satellite and Information Service, National Geophysical Data Center 6 | http://www.ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml 7 | 8 | Suggestions for improvements are appreciated. 9 | 10 | USAGE: 11 | >>> import geomag 12 | >>> geomag.declination(80,0) 13 | -3.382344140520556 14 | """ 15 | 16 | from . import geomag 17 | 18 | __singleton__ = geomag.GeoMag() 19 | 20 | def declination(*args, **kargs): 21 | """Calculate magnetic declination in degrees 22 | dlat = latitude in degrees 23 | dlon = longitude in degrees 24 | h = altitude in feet, default=0 25 | time = date for computing declination, default=today 26 | """ 27 | mag = __singleton__.GeoMag(*args, **kargs) 28 | return mag.dec 29 | 30 | def mag_heading(hdg, *args, **kargs): 31 | """Calculates the magnetic heading from a true heading. 32 | hdg = true heading in degrees 33 | All other parameters are the same as declination. 34 | """ 35 | dec = declination(*args, **kargs) 36 | return (hdg - dec + 360.0) % 360 37 | -------------------------------------------------------------------------------- /help/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo 42 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 43 | 44 | dirhtml: 45 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 48 | 49 | singlehtml: 50 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 51 | @echo 52 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 53 | 54 | pickle: 55 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 56 | @echo 57 | @echo "Build finished; now you can process the pickle files." 58 | 59 | json: 60 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 61 | @echo 62 | @echo "Build finished; now you can process the JSON files." 63 | 64 | htmlhelp: 65 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 66 | @echo 67 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 68 | ".hhp project file in $(BUILDDIR)/htmlhelp." 69 | 70 | qthelp: 71 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 72 | @echo 73 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 74 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 75 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/template_class.qhcp" 76 | @echo "To view the help file:" 77 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/template_class.qhc" 78 | 79 | devhelp: 80 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 81 | @echo 82 | @echo "Build finished." 83 | @echo "To view the help file:" 84 | @echo "# mkdir -p $$HOME/.local/share/devhelp/template_class" 85 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/template_class" 86 | @echo "# devhelp" 87 | 88 | epub: 89 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 90 | @echo 91 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 92 | 93 | latex: 94 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 95 | @echo 96 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 97 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 98 | "(use \`make latexpdf' here to do that automatically)." 99 | 100 | latexpdf: 101 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 102 | @echo "Running LaTeX files through pdflatex..." 103 | make -C $(BUILDDIR)/latex all-pdf 104 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 105 | 106 | text: 107 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 108 | @echo 109 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 110 | 111 | man: 112 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 113 | @echo 114 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 115 | 116 | changes: 117 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 118 | @echo 119 | @echo "The overview file is in $(BUILDDIR)/changes." 120 | 121 | linkcheck: 122 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 123 | @echo 124 | @echo "Link check complete; look for any errors in the above output " \ 125 | "or in $(BUILDDIR)/linkcheck/output.txt." 126 | 127 | doctest: 128 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 129 | @echo "Testing of doctests in the sources finished, look at the " \ 130 | "results in $(BUILDDIR)/doctest/output.txt." 131 | -------------------------------------------------------------------------------- /help/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source 10 | if NOT "%PAPER%" == "" ( 11 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 12 | ) 13 | 14 | if "%1" == "" goto help 15 | 16 | if "%1" == "help" ( 17 | :help 18 | echo.Please use `make ^` where ^ is one of 19 | echo. html to make standalone HTML files 20 | echo. dirhtml to make HTML files named index.html in directories 21 | echo. singlehtml to make a single large HTML file 22 | echo. pickle to make pickle files 23 | echo. json to make JSON files 24 | echo. htmlhelp to make HTML files and a HTML help project 25 | echo. qthelp to make HTML files and a qthelp project 26 | echo. devhelp to make HTML files and a Devhelp project 27 | echo. epub to make an epub 28 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 29 | echo. text to make text files 30 | echo. man to make manual pages 31 | echo. changes to make an overview over all changed/added/deprecated items 32 | echo. linkcheck to check all external links for integrity 33 | echo. doctest to run all doctests embedded in the documentation if enabled 34 | goto end 35 | ) 36 | 37 | if "%1" == "clean" ( 38 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 39 | del /q /s %BUILDDIR%\* 40 | goto end 41 | ) 42 | 43 | if "%1" == "html" ( 44 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 45 | echo. 46 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 47 | goto end 48 | ) 49 | 50 | if "%1" == "dirhtml" ( 51 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 52 | echo. 53 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 54 | goto end 55 | ) 56 | 57 | if "%1" == "singlehtml" ( 58 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 59 | echo. 60 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 61 | goto end 62 | ) 63 | 64 | if "%1" == "pickle" ( 65 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 66 | echo. 67 | echo.Build finished; now you can process the pickle files. 68 | goto end 69 | ) 70 | 71 | if "%1" == "json" ( 72 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 73 | echo. 74 | echo.Build finished; now you can process the JSON files. 75 | goto end 76 | ) 77 | 78 | if "%1" == "htmlhelp" ( 79 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 80 | echo. 81 | echo.Build finished; now you can run HTML Help Workshop with the ^ 82 | .hhp project file in %BUILDDIR%/htmlhelp. 83 | goto end 84 | ) 85 | 86 | if "%1" == "qthelp" ( 87 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 88 | echo. 89 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 90 | .qhcp project file in %BUILDDIR%/qthelp, like this: 91 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\template_class.qhcp 92 | echo.To view the help file: 93 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\template_class.ghc 94 | goto end 95 | ) 96 | 97 | if "%1" == "devhelp" ( 98 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 99 | echo. 100 | echo.Build finished. 101 | goto end 102 | ) 103 | 104 | if "%1" == "epub" ( 105 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 106 | echo. 107 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 108 | goto end 109 | ) 110 | 111 | if "%1" == "latex" ( 112 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 113 | echo. 114 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 115 | goto end 116 | ) 117 | 118 | if "%1" == "text" ( 119 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 120 | echo. 121 | echo.Build finished. The text files are in %BUILDDIR%/text. 122 | goto end 123 | ) 124 | 125 | if "%1" == "man" ( 126 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 127 | echo. 128 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 129 | goto end 130 | ) 131 | 132 | if "%1" == "changes" ( 133 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 134 | echo. 135 | echo.The overview file is in %BUILDDIR%/changes. 136 | goto end 137 | ) 138 | 139 | if "%1" == "linkcheck" ( 140 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 141 | echo. 142 | echo.Link check complete; look for any errors in the above output ^ 143 | or in %BUILDDIR%/linkcheck/output.txt. 144 | goto end 145 | ) 146 | 147 | if "%1" == "doctest" ( 148 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 149 | echo. 150 | echo.Testing of doctests in the sources finished, look at the ^ 151 | results in %BUILDDIR%/doctest/output.txt. 152 | goto end 153 | ) 154 | 155 | :end 156 | -------------------------------------------------------------------------------- /help/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # LFTools documentation build configuration file, created by 4 | # sphinx-quickstart on Sun Feb 12 17:11:03 2012. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # If your documentation needs a minimal Sphinx version, state it here. 24 | #needs_sphinx = '1.0' 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be extensions 27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 28 | extensions = ['sphinx.ext.todo', 'sphinx.ext.imgmath', 'sphinx.ext.viewcode'] 29 | 30 | # Add any paths that contain templates here, relative to this directory. 31 | templates_path = ['_templates'] 32 | 33 | # The suffix of source filenames. 34 | source_suffix = '.rst' 35 | 36 | # The encoding of source files. 37 | #source_encoding = 'utf-8-sig' 38 | 39 | # The master toctree document. 40 | master_doc = 'index' 41 | 42 | # General information about the project. 43 | project = u'LFTools' 44 | copyright = u'2013, Leandro Franca' 45 | 46 | # The version info for the project you're documenting, acts as replacement for 47 | # |version| and |release|, also used in various other places throughout the 48 | # built documents. 49 | # 50 | # The short X.Y version. 51 | version = '0.1' 52 | # The full version, including alpha/beta/rc tags. 53 | release = '0.1' 54 | 55 | # The language for content autogenerated by Sphinx. Refer to documentation 56 | # for a list of supported languages. 57 | #language = None 58 | 59 | # There are two options for replacing |today|: either, you set today to some 60 | # non-false value, then it is used: 61 | #today = '' 62 | # Else, today_fmt is used as the format for a strftime call. 63 | #today_fmt = '%B %d, %Y' 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | exclude_patterns = [] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_TemplateModuleNames = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. See the documentation for 93 | # a list of builtin themes. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_domain_indices = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | #html_show_sourcelink = True 151 | 152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 153 | #html_show_sphinx = True 154 | 155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 156 | #html_show_copyright = True 157 | 158 | # If true, an OpenSearch description file will be output, and all pages will 159 | # contain a tag referring to it. The value of this option must be the 160 | # base URL from which the finished HTML is served. 161 | #html_use_opensearch = '' 162 | 163 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 164 | #html_file_suffix = None 165 | 166 | # Output file base name for HTML help builder. 167 | htmlhelp_basename = 'TemplateClassdoc' 168 | 169 | 170 | # -- Options for LaTeX output -------------------------------------------------- 171 | 172 | # The paper size ('letter' or 'a4'). 173 | #latex_paper_size = 'letter' 174 | 175 | # The font size ('10pt', '11pt' or '12pt'). 176 | #latex_font_size = '10pt' 177 | 178 | # Grouping the document tree into LaTeX files. List of tuples 179 | # (source start file, target name, title, author, documentclass [howto/manual]). 180 | latex_documents = [ 181 | ('index', 'LFTools.tex', u'LFTools Documentation', 182 | u'Leandro Franca', 'manual'), 183 | ] 184 | 185 | # The name of an image file (relative to this directory) to place at the top of 186 | # the title page. 187 | #latex_logo = None 188 | 189 | # For "manual" documents, if this is true, then toplevel headings are parts, 190 | # not chapters. 191 | #latex_use_parts = False 192 | 193 | # If true, show page references after internal links. 194 | #latex_show_pagerefs = False 195 | 196 | # If true, show URL addresses after external links. 197 | #latex_show_urls = False 198 | 199 | # Additional stuff for the LaTeX preamble. 200 | #latex_preamble = '' 201 | 202 | # Documents to append as an appendix to all manuals. 203 | #latex_appendices = [] 204 | 205 | # If false, no module index is generated. 206 | #latex_domain_indices = True 207 | 208 | 209 | # -- Options for manual page output -------------------------------------------- 210 | 211 | # One entry per manual page. List of tuples 212 | # (source start file, name, description, authors, manual section). 213 | man_pages = [ 214 | ('index', 'TemplateClass', u'LFTools Documentation', 215 | [u'Leandro Franca'], 1) 216 | ] 217 | -------------------------------------------------------------------------------- /help/source/index.rst: -------------------------------------------------------------------------------- 1 | .. LFTools documentation master file, created by 2 | sphinx-quickstart on Sun Feb 12 17:11:03 2012. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to LFTools's documentation! 7 | ============================================ 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | Indices and tables 15 | ================== 16 | 17 | * :ref:`genindex` 18 | * :ref:`modindex` 19 | * :ref:`search` 20 | 21 | -------------------------------------------------------------------------------- /images/cadastre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/cadastre.png -------------------------------------------------------------------------------- /images/cart_frame.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/cart_frame.png -------------------------------------------------------------------------------- /images/cart_frames.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/cart_frames.png -------------------------------------------------------------------------------- /images/cart_frames2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/cart_frames2.png -------------------------------------------------------------------------------- /images/contours.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/contours.png -------------------------------------------------------------------------------- /images/document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/document.png -------------------------------------------------------------------------------- /images/drone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/drone.png -------------------------------------------------------------------------------- /images/easy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/easy.png -------------------------------------------------------------------------------- /images/lftools.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/lftools.png -------------------------------------------------------------------------------- /images/lftools_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/lftools_logo.png -------------------------------------------------------------------------------- /images/postgis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/postgis.png -------------------------------------------------------------------------------- /images/raster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/raster.png -------------------------------------------------------------------------------- /images/reamb_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/reamb_camera.png -------------------------------------------------------------------------------- /images/satellite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/satellite.png -------------------------------------------------------------------------------- /images/statistics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/statistics.png -------------------------------------------------------------------------------- /images/tools/GEOONE.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 35 | 37 | 42 | 44 | 48 | 52 | 53 | 56 | 60 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /images/tools/UTM.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 37 | 39 | 45 | 46 | 51 | 56 | 58 | 62 | 66 | 70 | 74 | 78 | 82 | 83 | 88 | 92 | 96 | 100 | 101 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /images/total_station.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/total_station.png -------------------------------------------------------------------------------- /images/tutorial/cadastre_adjoiners.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/cadastre_adjoiners.jpg -------------------------------------------------------------------------------- /images/tutorial/cadastre_connectFeatures.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/cadastre_connectFeatures.jpg -------------------------------------------------------------------------------- /images/tutorial/cadastre_frontlotline.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/cadastre_frontlotline.jpg -------------------------------------------------------------------------------- /images/tutorial/cadastre_geonumbering.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/cadastre_geonumbering.jpg -------------------------------------------------------------------------------- /images/tutorial/cadastre_polygon2point.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/cadastre_polygon2point.jpg -------------------------------------------------------------------------------- /images/tutorial/doc_analytical_results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/doc_analytical_results.jpg -------------------------------------------------------------------------------- /images/tutorial/doc_descriptive_memorial.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/doc_descriptive_memorial.jpg -------------------------------------------------------------------------------- /images/tutorial/doc_descriptive_table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/doc_descriptive_table.jpg -------------------------------------------------------------------------------- /images/tutorial/doc_mark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/doc_mark.jpg -------------------------------------------------------------------------------- /images/tutorial/doc_pointsFromText.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/doc_pointsFromText.jpg -------------------------------------------------------------------------------- /images/tutorial/doc_validation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/doc_validation.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_copySelectedFiles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_copySelectedFiles.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_createGCP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_createGCP.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_georref_adjust.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_georref_adjust.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_histogram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_histogram.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_joinFolders.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_joinFolders.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_photosByBlocks.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_photosByBlocks.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_point_cloud_adjust.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_point_cloud_adjust.jpg -------------------------------------------------------------------------------- /images/tutorial/drone_verticalAdjustment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/drone_verticalAdjustment.jpg -------------------------------------------------------------------------------- /images/tutorial/easy_coord_layer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/easy_coord_layer.jpg -------------------------------------------------------------------------------- /images/tutorial/easy_expr_ascii.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/easy_expr_ascii.jpg -------------------------------------------------------------------------------- /images/tutorial/easy_get_attributes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/easy_get_attributes.jpg -------------------------------------------------------------------------------- /images/tutorial/easy_measure_layer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/easy_measure_layer.jpg -------------------------------------------------------------------------------- /images/tutorial/easy_selectByKey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/easy_selectByKey.jpg -------------------------------------------------------------------------------- /images/tutorial/gnss_nmea.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/gnss_nmea.jpg -------------------------------------------------------------------------------- /images/tutorial/gnss_pos2layer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/gnss_pos2layer.jpg -------------------------------------------------------------------------------- /images/tutorial/gnss_ppk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/gnss_ppk.jpg -------------------------------------------------------------------------------- /images/tutorial/gnss_rtk_correction.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/gnss_rtk_correction.jpg -------------------------------------------------------------------------------- /images/tutorial/grid_coord_utm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/grid_coord_utm.jpg -------------------------------------------------------------------------------- /images/tutorial/grid_ext_utm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/grid_ext_utm.jpg -------------------------------------------------------------------------------- /images/tutorial/grid_inom_utm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/grid_inom_utm.jpg -------------------------------------------------------------------------------- /images/tutorial/grid_lines_frames.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/grid_lines_frames.jpg -------------------------------------------------------------------------------- /images/tutorial/post_backup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_backup.jpg -------------------------------------------------------------------------------- /images/tutorial/post_clonedb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_clonedb.jpg -------------------------------------------------------------------------------- /images/tutorial/post_deletedb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_deletedb.jpg -------------------------------------------------------------------------------- /images/tutorial/post_encoding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_encoding.jpg -------------------------------------------------------------------------------- /images/tutorial/post_importraster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_importraster.jpg -------------------------------------------------------------------------------- /images/tutorial/post_renamedb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_renamedb.jpg -------------------------------------------------------------------------------- /images/tutorial/post_restore.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/post_restore.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_bandArithmetic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_bandArithmetic.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_classification.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_classification.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_create_holes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_create_holes.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_define_null_px.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_define_null_px.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_extract_band.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_extract_band.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_fill_holes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_fill_holes.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_getpointvalue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_getpointvalue.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_histogram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_histogram.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_histogrammatching.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_histogrammatching.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_inventory.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_inventory.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_jpeg_compress.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_jpeg_compress.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_jpeg_tfw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_jpeg_tfw.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_loadByLocation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_loadByLocation.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_mosaic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_mosaic.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_overviews.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_overviews.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_remove_alpha.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_remove_alpha.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_rgb.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_rgb2hsv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_rgb2hsv.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_split.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_split.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_thresholding.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_thresholding.jpg -------------------------------------------------------------------------------- /images/tutorial/raster_zonalstatistics.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/raster_zonalstatistics.jpg -------------------------------------------------------------------------------- /images/tutorial/reamb_geotag.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/reamb_geotag.jpg -------------------------------------------------------------------------------- /images/tutorial/reamb_kml_photos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/reamb_kml_photos.jpg -------------------------------------------------------------------------------- /images/tutorial/reamb_resize_photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/reamb_resize_photo.jpg -------------------------------------------------------------------------------- /images/tutorial/relief_defineZ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/relief_defineZ.jpg -------------------------------------------------------------------------------- /images/tutorial/relief_dem2txt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/relief_dem2txt.jpg -------------------------------------------------------------------------------- /images/tutorial/relief_demfilter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/relief_demfilter.jpg -------------------------------------------------------------------------------- /images/tutorial/relief_difference.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/relief_difference.jpg -------------------------------------------------------------------------------- /images/tutorial/relief_spot_elevation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/relief_spot_elevation.jpg -------------------------------------------------------------------------------- /images/tutorial/stat_central_tendency.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/stat_central_tendency.jpg -------------------------------------------------------------------------------- /images/tutorial/stat_ellipses.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/stat_ellipses.jpg -------------------------------------------------------------------------------- /images/tutorial/stat_nearestPoints.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/stat_nearestPoints.jpg -------------------------------------------------------------------------------- /images/tutorial/stat_random_points.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/stat_random_points.jpg -------------------------------------------------------------------------------- /images/tutorial/stat_standard_distance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/stat_standard_distance.jpg -------------------------------------------------------------------------------- /images/tutorial/survey_3D_coord.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/survey_3D_coord.jpg -------------------------------------------------------------------------------- /images/tutorial/survey_LTP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/survey_LTP.jpg -------------------------------------------------------------------------------- /images/tutorial/survey_azimuth_distance.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/survey_azimuth_distance.jpg -------------------------------------------------------------------------------- /images/tutorial/survey_closed_polygonal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/survey_closed_polygonal.jpg -------------------------------------------------------------------------------- /images/tutorial/survey_helmert2D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/survey_helmert2D.jpg -------------------------------------------------------------------------------- /images/tutorial/survey_traverse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/survey_traverse.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_connectLayers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_connectLayers.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_cross_sections.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_cross_sections.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_directional_merge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_directional_merge.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_extend_lines.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_extend_lines.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_line_sequence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_line_sequence.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_lines2polygon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_lines2polygon.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_orient_polygon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_orient_polygon.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_overlapping.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_overlapping.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_point2polygon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_point2polygon.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_polygon_angles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_polygon_angles.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_reprojectGPKG.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_reprojectGPKG.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_reverse_vertex_sequence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_reverse_vertex_sequence.jpg -------------------------------------------------------------------------------- /images/tutorial/vect_sequence_points.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/tutorial/vect_sequence_points.jpg -------------------------------------------------------------------------------- /images/vetor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/images/vetor.png -------------------------------------------------------------------------------- /metadata.txt: -------------------------------------------------------------------------------- 1 | # This file contains metadata for your plugin. 2 | 3 | # This file should be included when you package your plugin.# Mandatory items: 4 | 5 | [general] 6 | name=LF Tools 7 | qgisMinimumVersion=3.10 8 | description=Tools for cartographic production, surveying, database management, digital image processing and spatial analysis. 9 | version=2.1.7 10 | author=Leandro França 11 | email=suporte@geoone.com.br 12 | 13 | about=The LFTools plugin is a true "Swiss Army knife" developed for QGIS, bringing together more than 126 scripts, expression functions, and toolbar tools. It caters to a wide range of needs, including cartographic production, surveying, drone operations, GNSS, image processing, database management, and spatial analysis. Since its launch in March 2021, it has become the most downloaded Brazilian-developed plugin on the platform, widely adopted by surveyors, cartographers, geographers, and other professionals working with geotechnologies. LFTools stands out for offering practical and automated solutions for creating topographic plans, descriptive reports, and other technical documents, combining automation efficiency with QGIS Atlas features and Python expressions. 14 | 15 | tracker=https://github.com/LEOXINGU/lftools/issues 16 | repository=https://github.com/LEOXINGU/lftools 17 | # End of mandatory metadata 18 | 19 | # Recommended items: 20 | 21 | hasProcessingProvider=yes 22 | # Uncomment the following line and add your changelog: 23 | # changelog= 24 | 2.1.7 - bug fix in "Calculate polygon angles" tool for minimum distance 25 | 2.1.6 - improvement in "Calculate polygon angles" tool to create angle interior and exterior lines 26 | 2.1.5 - improvement in "get attribute by location tool" for only selected features and other minor bug fix 27 | 2.1.4 - deedtable functions with also calculation in LTP and different precisions 28 | 2.1.3 - deedtext function with also calculation in LTP 29 | 2.1.2 - DMS option for Points From Text tool 30 | 2.1.1 - Bug fix in unloading lftools plugin 31 | 2.1.0 - New tools added: Set Z and select by key attribute 32 | 2.0.0 - Tool bar added 33 | 1.12.13 - Bug fix for photo with geotag tool 34 | 1.12.12 - Translation to Spanish 35 | 1.12.11 - Improvements to calculate Local Tangent Plane measurements 36 | 1.12.10 - Improvements in documentation tools with new coordinates types 37 | 1.12.9 - Anti-dumb condition for the Table to point layer tool 38 | 1.12.8 - Bug fix for QgsProcessingParameterNumber in QGIS 3.36 39 | 1.12.7 - Improvement of the Validate topology tool 40 | 1.12.6 - Bug fix for font-size geoneighbors function 41 | 1.12.5 - Bug fix in deedtext for repeated vertex codes 42 | 1.12.4 - Database tools updated to PostgreSQL 16 43 | 1.12.3 - Font type configuration for deedtext 44 | 1.12.2 - Improvements to the Deed description tool 45 | 1.12.1 - Bug fix in Nearest points and Adjoiner Lines tools 46 | 1.12.0 - New tools for Cartography, Vector and Easy 47 | 1.11.0 - New tools for Cadastre, Vector, Raster and Statistics 48 | 1.10.0 - New tools for GNSS, Vector and Statistics 49 | 1.9.4 - Tooltip and action for geotag photos tool 50 | 1.9.3 - Bug fix in NMEA to layer tool 51 | 1.9.2 - Topological validation in the Deed description tool 52 | 1.9.1 - Bug fix of Points from Text tool and polygon orientation improvement 53 | 1.9.0 - New tool for GNSS stop and go 54 | 1.8.0 - New function to calculate magnetic declination 55 | 1.7.2 - Bug fix of Calculate Polygon Angles tool 56 | 1.7.1 - Bug fix of Points from Text tool 57 | 1.7.0 - New tools for cadastre and others 58 | 1.6.2 - Bug fix of the Front Lot Lines tool 59 | 1.6.1 - Bug fix of Descriptive Memorial for PointZ error 60 | 1.6.0 - New tools for Cadastre, Raster and GNSS 61 | 1.5.0 - New tools for DTM and spot elevations 62 | 1.4.1 - Bug fix of the join folders extensions 63 | 1.4.0 - New tools for drones'image pre and pos processing 64 | 1.3.7 - Bug fix of the calculate polygon angles tool 65 | 1.3.6 - Adaptation to get the JPEG's geotag for the newest QGIS's version 66 | 1.3.5 - Documentation tools and filefilter Improvements 67 | 1.3.4 - CRS's checking and logo option for documentation tools 68 | 1.3.3 - exifread module replaced by PIL.TiffTags to work in linux 69 | 1.3.2 - Geotag for TIFF image included 70 | 1.3.1 - Bug fix of the supervised classification tool 71 | 1.3.0 - New tool for Raster Binary Thresholding 72 | 1.2.0 - New tool for saving Raster as jpeg 73 | 1.1.2 - Documentation tools adapted to english parameters 74 | 1.1.1 - Bug fix of the estimated 3D coordinates tool for Linux 75 | 1.1.0 - Expressions added 76 | 1.0.1 - Improvement in tools' translation and description 77 | 1.0 - Initial version 78 | # Tags are comma separated with spaces allowed 79 | tags=cartography, surveying, topography, raster, vector, postgis, cadastre, processing, reambulation, geotag, expressions, document, memorial, description, drones, GNSS, NMEA, RTKLIB, magnetic, ellipses, lftools, brazil, GeoOne 80 | 81 | homepage=https://github.com/LEOXINGU/lftools/wiki/LF-Tools-for-QGIS 82 | category=cartography 83 | icon=images/lftools_logo.png 84 | # experimental flag 85 | experimental=False 86 | 87 | # deprecated flag (applies to the whole plugin, not just a single version) 88 | deprecated=False 89 | 90 | # Since QGIS 3.8, a comma separated list of plugins to be installed 91 | # (or upgraded) can be specified. 92 | # Check the documentation for more information. 93 | # plugin_dependencies= 94 | 95 | Category of the plugin: Raster, Vector, Database or Web 96 | # category= Processing 97 | 98 | # If the plugin can run on QGIS Server. 99 | server=False 100 | -------------------------------------------------------------------------------- /pb_tool.cfg: -------------------------------------------------------------------------------- 1 | #/*************************************************************************** 2 | # LFTools 3 | # 4 | # Configuration file for plugin builder tool (pb_tool) 5 | # Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/ 6 | # ------------------- 7 | # begin : 2021-02-18 8 | # copyright : (C) 2021 by Leandro Franca 9 | # email : geoleandro.franca@gmail.com 10 | # ***************************************************************************/ 11 | # 12 | #/*************************************************************************** 13 | # * * 14 | # * This program is free software; you can redistribute it and/or modify * 15 | # * it under the terms of the GNU General Public License as published by * 16 | # * the Free Software Foundation; either version 2 of the License, or * 17 | # * (at your option) any later version. * 18 | # * * 19 | # ***************************************************************************/ 20 | # 21 | # 22 | # You can install pb_tool using: 23 | # pip install http://geoapt.net/files/pb_tool.zip 24 | # 25 | # Consider doing your development (and install of pb_tool) in a virtualenv. 26 | # 27 | # For details on setting up and using pb_tool, see: 28 | # http://g-sherman.github.io/plugin_build_tool/ 29 | # 30 | # Issues and pull requests here: 31 | # https://github.com/g-sherman/plugin_build_tool: 32 | # 33 | # Sane defaults for your plugin generated by the Plugin Builder are 34 | # already set below. 35 | # 36 | # As you add Python source files and UI files to your plugin, add 37 | # them to the appropriate [files] section below. 38 | 39 | [plugin] 40 | # Name of the plugin. This is the name of the directory that will 41 | # be created in .qgis2/python/plugins 42 | name: lftools 43 | 44 | # Full path to where you want your plugin directory copied. If empty, 45 | # the QGIS default path will be used. Don't include the plugin name in 46 | # the path. 47 | plugin_path: 48 | 49 | [files] 50 | # Python files that should be deployed with the plugin 51 | python_files: __init__.py lftools.py 52 | 53 | # The main dialog file that is loaded (not compiled) 54 | main_dialog: 55 | 56 | # Other ui files for dialogs you create (these will be compiled) 57 | compiled_ui_files: 58 | 59 | # Resource file(s) that will be compiled 60 | resource_files: 61 | 62 | # Other files required for the plugin 63 | extras: metadata.txt 64 | 65 | # Other directories to be deployed with the plugin. 66 | # These must be subdirectories under the plugin directory 67 | extra_dirs: 68 | 69 | # ISO code(s) for any locales (translations), separated by spaces. 70 | # Corresponding .ts files must exist in the i18n directory 71 | locales: 72 | 73 | [help] 74 | # the built help directory that should be deployed with the plugin 75 | dir: help/build/html 76 | # the name of the directory to target in the deployed plugin 77 | target: help 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /plugin_upload.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | """This script uploads a plugin package to the plugin repository. 4 | Authors: A. Pasotti, V. Picavet 5 | git sha : $TemplateVCSFormat 6 | """ 7 | 8 | import sys 9 | import getpass 10 | import xmlrpc.client 11 | from optparse import OptionParser 12 | 13 | standard_library.install_aliases() 14 | 15 | # Configuration 16 | PROTOCOL = 'https' 17 | SERVER = 'plugins.qgis.org' 18 | PORT = '443' 19 | ENDPOINT = '/plugins/RPC2/' 20 | VERBOSE = False 21 | 22 | 23 | def main(parameters, arguments): 24 | """Main entry point. 25 | 26 | :param parameters: Command line parameters. 27 | :param arguments: Command line arguments. 28 | """ 29 | address = "{protocol}://{username}:{password}@{server}:{port}{endpoint}".format( 30 | protocol=PROTOCOL, 31 | username=parameters.username, 32 | password=parameters.password, 33 | server=parameters.server, 34 | port=parameters.port, 35 | endpoint=ENDPOINT) 36 | print("Connecting to: %s" % hide_password(address)) 37 | 38 | server = xmlrpc.client.ServerProxy(address, verbose=VERBOSE) 39 | 40 | try: 41 | with open(arguments[0], 'rb') as handle: 42 | plugin_id, version_id = server.plugin.upload( 43 | xmlrpc.client.Binary(handle.read())) 44 | print("Plugin ID: %s" % plugin_id) 45 | print("Version ID: %s" % version_id) 46 | except xmlrpc.client.ProtocolError as err: 47 | print("A protocol error occurred") 48 | print("URL: %s" % hide_password(err.url, 0)) 49 | print("HTTP/HTTPS headers: %s" % err.headers) 50 | print("Error code: %d" % err.errcode) 51 | print("Error message: %s" % err.errmsg) 52 | except xmlrpc.client.Fault as err: 53 | print("A fault occurred") 54 | print("Fault code: %d" % err.faultCode) 55 | print("Fault string: %s" % err.faultString) 56 | 57 | 58 | def hide_password(url, start=6): 59 | """Returns the http url with password part replaced with '*'. 60 | 61 | :param url: URL to upload the plugin to. 62 | :type url: str 63 | 64 | :param start: Position of start of password. 65 | :type start: int 66 | """ 67 | start_position = url.find(':', start) + 1 68 | end_position = url.find('@') 69 | return "%s%s%s" % ( 70 | url[:start_position], 71 | '*' * (end_position - start_position), 72 | url[end_position:]) 73 | 74 | 75 | if __name__ == "__main__": 76 | parser = OptionParser(usage="%prog [options] plugin.zip") 77 | parser.add_option( 78 | "-w", "--password", dest="password", 79 | help="Password for plugin site", metavar="******") 80 | parser.add_option( 81 | "-u", "--username", dest="username", 82 | help="Username of plugin site", metavar="user") 83 | parser.add_option( 84 | "-p", "--port", dest="port", 85 | help="Server port to connect to", metavar="80") 86 | parser.add_option( 87 | "-s", "--server", dest="server", 88 | help="Specify server name", metavar="plugins.qgis.org") 89 | options, args = parser.parse_args() 90 | if len(args) != 1: 91 | print("Please specify zip file.\n") 92 | parser.print_help() 93 | sys.exit(1) 94 | if not options.server: 95 | options.server = SERVER 96 | if not options.port: 97 | options.port = PORT 98 | if not options.username: 99 | # interactive mode 100 | username = getpass.getuser() 101 | print("Please enter user name [%s] :" % username, end=' ') 102 | 103 | res = input() 104 | if res != "": 105 | options.username = res 106 | else: 107 | options.username = username 108 | if not options.password: 109 | # interactive mode 110 | options.password = getpass.getpass() 111 | main(options, args) 112 | -------------------------------------------------------------------------------- /processing_provider/Drone_copySelectedPhotos.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Drone_copySelectedPhotos.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-11-07' 16 | __copyright__ = '(C) 2021, Leandro França' 17 | 18 | from qgis.utils import iface 19 | from qgis.PyQt.QtCore import QCoreApplication 20 | from qgis.core import * 21 | from lftools.geocapt.imgs import Imgs 22 | from lftools.translations.translate import translate 23 | import os, shutil 24 | from qgis.PyQt.QtGui import QIcon 25 | 26 | class CopySelectedPhotos(QgsProcessingAlgorithm): 27 | 28 | LOC = QgsApplication.locale()[:2] 29 | 30 | def tr(self, *string): 31 | return translate(string, self.LOC) 32 | 33 | def createInstance(self): 34 | return CopySelectedPhotos() 35 | 36 | def name(self): 37 | return 'copyselectedphotos' 38 | 39 | def displayName(self): 40 | return self.tr('Copy selected files', 'Copiar arquivos selecionados') 41 | 42 | def group(self): 43 | return self.tr('Drones') 44 | 45 | def groupId(self): 46 | return 'drones' 47 | 48 | def tags(self): 49 | return self.tr('drones,fotografia,photography,blocks,copy,copiar,separate,separar,organize,organizar,filtrar,filter').split(',') 50 | 51 | def icon(self): 52 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/drone.png')) 53 | 54 | txt_en = 'This tool makes it possible to copy or move files to a new folder from a point layer with file paths.' 55 | txt_pt = 'Esta ferramenta possibilita copiar ou mover arquivos para uma nova pasta a partir de uma camada de pontos com os caminhos dos arquivos.' 56 | figure = 'images/tutorial/drone_copySelectedFiles.jpg' 57 | 58 | def shortHelpString(self): 59 | social_BW = Imgs().social_BW 60 | footer = '''
61 | 62 |
63 |
64 |

65 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 66 |

'''+ social_BW + '''
67 | ''' 68 | return self.tr(self.txt_en, self.txt_pt) + footer 69 | 70 | POINTS = 'POINTS' 71 | FILEPATH = 'FILEPATH' 72 | OPTION = 'OPTION' 73 | FOLDER = 'FOLDER' 74 | 75 | def initAlgorithm(self, config=None): 76 | self.addParameter( 77 | QgsProcessingParameterVectorLayer( 78 | self.POINTS, 79 | self.tr('Points', 'Pontos'), 80 | [QgsProcessing.TypeVectorPoint] 81 | ) 82 | ) 83 | 84 | self.addParameter( 85 | QgsProcessingParameterField( 86 | self.FILEPATH, 87 | self.tr('Field with file path', 'Campo com o caminho do arquivo'), 88 | parentLayerParameterName=self.POINTS, 89 | type=QgsProcessingParameterField.String 90 | ) 91 | ) 92 | 93 | opt = [self.tr('Copy','Copiar'), 94 | self.tr('Move','Mover') 95 | ] 96 | 97 | self.addParameter( 98 | QgsProcessingParameterEnum( 99 | self.OPTION, 100 | self.tr('Option', 'Opção'), 101 | options = opt, 102 | defaultValue= 0 103 | ) 104 | ) 105 | 106 | self.addParameter( 107 | QgsProcessingParameterFile( 108 | self.FOLDER, 109 | self.tr('Destination folder for photos', 'Pasta de destino para fotografias'), 110 | behavior=QgsProcessingParameterFile.Folder, 111 | defaultValue=None 112 | ) 113 | ) 114 | 115 | def processAlgorithm(self, parameters, context, feedback): 116 | 117 | pontos = self.parameterAsVectorLayer( 118 | parameters, 119 | self.POINTS, 120 | context 121 | ) 122 | if pontos is None: 123 | raise QgsProcessingException(self.invalidSourceError(parameters, self.POINTS)) 124 | 125 | campo = self.parameterAsFields( 126 | parameters, 127 | self.FILEPATH, 128 | context 129 | ) 130 | if campo is None: 131 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FILEPATH)) 132 | 133 | columnIndex = pontos.fields().indexFromName(campo[0]) 134 | 135 | opcao = self.parameterAsEnum( 136 | parameters, 137 | self.OPTION, 138 | context 139 | ) 140 | 141 | destino = self.parameterAsFile( 142 | parameters, 143 | self.FOLDER, 144 | context 145 | ) 146 | if not destino: 147 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FOLDER)) 148 | 149 | # Verificar se tem arquivos selecionados 150 | if pontos.selectedFeatureCount() <1: 151 | raise QgsProcessingException(self.tr('At least one feature must be selected!', 'Pelo menos uma feição deve ser selecionada!')) 152 | 153 | # Copiando arquivos selecionados para a nova pasta 154 | total = 100.0 / pontos.selectedFeatureCount() 155 | cont = 1 156 | for pnt in pontos.getSelectedFeatures(): 157 | origem = pnt[columnIndex] 158 | if os.path.exists(origem): 159 | nome = os.path.split(origem)[-1] 160 | if opcao == 0: 161 | shutil.copy2(origem, os.path.join(destino, nome)) 162 | elif opcao == 1: 163 | shutil.move(origem, os.path.join(destino, nome)) 164 | else: 165 | feedback.reportError('📢 ' + self.tr('Path {} does not exist!', 'Caminho {} não exite!').format(origem)) 166 | 167 | if feedback.isCanceled(): 168 | break 169 | feedback.setProgress(int((cont) * total)) 170 | cont += 1 171 | 172 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 173 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 174 | 175 | return {} 176 | -------------------------------------------------------------------------------- /processing_provider/Drone_createGCPfile.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Drone_createGCPfile.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-11-08' 16 | __copyright__ = '(C) 2021, Leandro França' 17 | 18 | from qgis.PyQt.QtCore import QCoreApplication 19 | from qgis.core import (QgsApplication, 20 | QgsProcessingParameterVectorLayer, 21 | QgsGeometry, 22 | QgsProcessing, 23 | QgsProcessingParameterField, 24 | QgsProcessingParameterString, 25 | QgsProcessingParameterEnum, 26 | QgsProcessingParameterNumber, 27 | QgsProcessingParameterBoolean, 28 | QgsProcessingParameterFileDestination, 29 | QgsFeatureSink, 30 | QgsProcessingException, 31 | QgsProcessingAlgorithm, 32 | QgsProcessingParameterFeatureSource, 33 | QgsProcessingParameterFeatureSink) 34 | from lftools.geocapt.imgs import Imgs 35 | from lftools.translations.translate import translate 36 | import os 37 | from qgis.PyQt.QtGui import QIcon 38 | 39 | class CreateGCPfile(QgsProcessingAlgorithm): 40 | 41 | LOC = QgsApplication.locale()[:2] 42 | 43 | def tr(self, *string): 44 | return translate(string, self.LOC) 45 | 46 | def createInstance(self): 47 | return CreateGCPfile() 48 | 49 | def name(self): 50 | return 'creategcpfile' 51 | 52 | def displayName(self): 53 | return self.tr('Generate GCP file for WebODM', 'Gerar arquivo de GCP para o WebODM') 54 | 55 | def group(self): 56 | return self.tr('Drones') 57 | 58 | def groupId(self): 59 | return 'drones' 60 | 61 | def tags(self): 62 | return self.tr('drones,fotografia,webodm,opendronemap,odm,photography,gcp,copy,points,control,ground,quality,homologous,controle,terreno').split(',') 63 | 64 | def icon(self): 65 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/drone.png')) 66 | 67 | txt_en = 'Generate text file with Ground Control Points (GCP) from a point layer to WebODM.' 68 | txt_pt = 'Gera arquivo texto com Pontos de Controle no Terreno (GCP) a partir de uma camada de pontos.' 69 | figure = 'images/tutorial/drone_createGCP.jpg' 70 | 71 | def shortHelpString(self): 72 | social_BW = Imgs().social_BW 73 | footer = '''
74 | 75 |
76 |
77 |

78 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 79 |

'''+ social_BW + '''
80 | ''' 81 | return self.tr(self.txt_en, self.txt_pt) + footer 82 | 83 | POINTS = 'POINTS' 84 | NAME = 'NAME' 85 | FILE = 'FILE' 86 | DECIMAL = 'DECIMAL' 87 | 88 | def initAlgorithm(self, config=None): 89 | self.addParameter( 90 | QgsProcessingParameterVectorLayer( 91 | self.POINTS, 92 | self.tr('Point Layer', 'Camada de Pontos'), 93 | [QgsProcessing.TypeVectorPoint] 94 | ) 95 | ) 96 | 97 | self.addParameter( 98 | QgsProcessingParameterField( 99 | self.NAME, 100 | self.tr('GCP name', 'Nome do ponto de controle'), 101 | parentLayerParameterName=self.POINTS, 102 | type=QgsProcessingParameterField.String 103 | ) 104 | ) 105 | 106 | self.addParameter( 107 | QgsProcessingParameterNumber( 108 | self.DECIMAL, 109 | self.tr('Decimal places', 'Casas decimais'), 110 | type = QgsProcessingParameterNumber.Type.Integer, 111 | defaultValue = 3, 112 | minValue = 1 113 | ) 114 | ) 115 | 116 | self.addParameter( 117 | QgsProcessingParameterFileDestination( 118 | self.FILE, 119 | self.tr('Ground Control Points (GCP)', 'Pontos de Controle (GCP)'), 120 | fileFilter = 'Text (*.txt)' 121 | ) 122 | ) 123 | 124 | def processAlgorithm(self, parameters, context, feedback): 125 | 126 | pontos = self.parameterAsVectorLayer( 127 | parameters, 128 | self.POINTS, 129 | context 130 | ) 131 | if pontos is None: 132 | raise QgsProcessingException(self.invalidSourceError(parameters, self.POINTS)) 133 | 134 | campo = self.parameterAsFields( 135 | parameters, 136 | self.NAME, 137 | context 138 | ) 139 | if campo is None: 140 | raise QgsProcessingException(self.invalidSourceError(parameters, self.NAME)) 141 | 142 | columnIndex = pontos.fields().indexFromName(campo[0]) 143 | 144 | decimal = self.parameterAsInt( 145 | parameters, 146 | self.DECIMAL, 147 | context 148 | ) 149 | if decimal is None or decimal<1: 150 | raise QgsProcessingException(self.invalidSourceError(parameters, self.DECIMAL)) 151 | 152 | format_num = '{:.Xf}'.replace('X', str(decimal)) 153 | 154 | filepath = self.parameterAsFile( 155 | parameters, 156 | self.FILE, 157 | context 158 | ) 159 | if not filepath: 160 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FILE)) 161 | 162 | # Verificando se a camada possui coordenada Z 163 | for feat in pontos.getFeatures(): 164 | geom = feat.geometry() 165 | break 166 | t = str(geom.constGet().z()) 167 | try: 168 | t = str(geom.constGet().z()) 169 | except: 170 | t = 'nan' 171 | if t == 'nan': 172 | eh3d = False 173 | feedback.pushInfo(self.tr('''Layer features do not have a Z coordinate. 174 | The Z coordinate will be set to 0 (zero)!''', '''Feições da camada não possuem coordenada Z. 175 | A coordena Z será definida com 0 (zero)!''')) 176 | else: 177 | eh3d = True 178 | 179 | # Criando arquivo de pontos de controle 180 | arq = open(filepath, 'w') 181 | 182 | # Escrevendo SRC como WKT 183 | arq.write(pontos.sourceCrs().toProj4() + '\n') 184 | 185 | for feat in pontos.getFeatures(): 186 | nome = feat[columnIndex] 187 | geom = feat.geometry() 188 | if not eh3d: 189 | pnt = geom.asPoint() 190 | X, Y, Z = pnt.x(), pnt.y(), 0 191 | else: 192 | X, Y, Z = geom.constGet().x(), geom.constGet().y(), geom.constGet().z() 193 | arq.write(nome + '\t' + format_num.format(X) + '\t' + format_num.format(Y) + '\t' + format_num.format(Z) + '\n') 194 | if feedback.isCanceled(): 195 | break 196 | 197 | arq.close() 198 | 199 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 200 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 201 | 202 | return {} 203 | -------------------------------------------------------------------------------- /processing_provider/Drone_joinFolders.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Drone_joinFolders.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-11-08' 16 | __copyright__ = '(C) 2021, Leandro França' 17 | 18 | from qgis.PyQt.QtCore import QCoreApplication 19 | from qgis.core import (QgsApplication, 20 | QgsProcessingParameterVectorLayer, 21 | QgsGeometry, 22 | QgsProcessing, 23 | QgsProcessingParameterField, 24 | QgsProcessingParameterString, 25 | QgsProcessingParameterEnum, 26 | QgsProcessingParameterBoolean, 27 | QgsProcessingParameterFile, 28 | QgsFeatureSink, 29 | QgsProcessingException, 30 | QgsProcessingAlgorithm, 31 | QgsProcessingParameterFeatureSource, 32 | QgsProcessingParameterFeatureSink) 33 | from lftools.geocapt.imgs import Imgs 34 | from lftools.translations.translate import translate 35 | import os, shutil 36 | from qgis.PyQt.QtGui import QIcon 37 | 38 | class JoinFolders(QgsProcessingAlgorithm): 39 | 40 | LOC = QgsApplication.locale()[:2] 41 | 42 | def tr(self, *string): 43 | return translate(string, self.LOC) 44 | 45 | def createInstance(self): 46 | return JoinFolders() 47 | 48 | def name(self): 49 | return 'joinfolders' 50 | 51 | def displayName(self): 52 | return self.tr('Join folders', 'Juntar pastas') 53 | 54 | def group(self): 55 | return self.tr('Drones') 56 | 57 | def groupId(self): 58 | return 'drones' 59 | 60 | def tags(self): 61 | return self.tr('drones,fotografia,photography,blocks,join,juntar,organize,organizar').split(',') 62 | 63 | def icon(self): 64 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/drone.png')) 65 | 66 | txt_en = '''This tool has the objective of joining the files from several folders in another new folder, with the possibility of renaming the files. 67 | It is a very useful procedure for joining multiple drone images with repeated names into a single folder.''' 68 | txt_pt = '''Esta ferramenta tem o objetivo de juntar os arquivos de várias pastas em uma outra nova pasta, com a possibilidade de renomear os arquivos. 69 | É um procedimento muito útil para juntar várias imagens de drone com nomes repetidos em uma única pasta.''' 70 | figure = 'images/tutorial/drone_joinFolders.jpg' 71 | 72 | def shortHelpString(self): 73 | social_BW = Imgs().social_BW 74 | footer = '''
75 | 76 |
77 |
78 |

79 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 80 |

'''+ social_BW + '''
81 | ''' 82 | return self.tr(self.txt_en, self.txt_pt) + footer 83 | 84 | FOLDERS = 'FOLDERS' 85 | RENAME = 'RENAME' 86 | PREFIX = 'PREFIX' 87 | OUT_FOLDER = 'OUT_FOLDER' 88 | 89 | def initAlgorithm(self, config=None): 90 | #inputs 91 | self.addParameter( 92 | QgsProcessingParameterFile( 93 | self.FOLDERS, 94 | self.tr('Folders with files', 'Pastas com arquivos'), 95 | behavior=QgsProcessingParameterFile.Folder, 96 | defaultValue=None 97 | ) 98 | ) 99 | 100 | self.addParameter( 101 | QgsProcessingParameterBoolean( 102 | self.RENAME, 103 | self.tr('Rename copied files', 'Renomear arquivos copiados'), 104 | defaultValue = True 105 | ) 106 | ) 107 | 108 | self.addParameter( 109 | QgsProcessingParameterString( 110 | self.PREFIX, 111 | self.tr('File name prefix', 'Prefixo do nome do arquivo'), 112 | defaultValue = self.tr('IMG_') 113 | ) 114 | ) 115 | 116 | #output 117 | self.addParameter( 118 | QgsProcessingParameterFile( 119 | self.OUT_FOLDER, 120 | self.tr('Destination folder', 'Pasta de destino'), 121 | behavior=QgsProcessingParameterFile.Folder, 122 | defaultValue=None 123 | ) 124 | ) 125 | 126 | def processAlgorithm(self, parameters, context, feedback): 127 | 128 | caminho_geral = self.parameterAsFile( 129 | parameters, 130 | self.FOLDERS, 131 | context 132 | ) 133 | if not caminho_geral: 134 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FOLDERS)) 135 | 136 | renomear = self.parameterAsBool( 137 | parameters, 138 | self.RENAME, 139 | context 140 | ) 141 | 142 | prefixo = self.parameterAsString( 143 | parameters, 144 | self.PREFIX, 145 | context 146 | ) 147 | 148 | destino = self.parameterAsFile( 149 | parameters, 150 | self.OUT_FOLDER, 151 | context 152 | ) 153 | if not destino: 154 | raise QgsProcessingException(self.invalidSourceError(parameters, self.OUT_FOLDER)) 155 | 156 | # contagem de arquivos 157 | feedback.pushInfo(self.tr('Checking files in the folders...', 'Checando arquivos nas pastas...')) 158 | lista = [] 159 | for root, dirs, files in os.walk(caminho_geral, topdown=True): 160 | for name in files: 161 | if (name).lower().endswith(('.jpg', '.jpeg', '.tif', '.tiff')): 162 | lista += [os.path.join(root, name)] 163 | 164 | cont_files = len(lista) 165 | feedback.pushInfo(self.tr('Number of files to be copied: {}'.format(cont_files), 'Total de arquivos a serem copiados: {}'.format(cont_files))) 166 | total = 100.0 / cont_files if cont_files else 0 167 | 168 | # copiando os arquivos 169 | for cont, filepath in enumerate(lista): 170 | if os.path.join(caminho_geral, '') in os.path.join(destino, ''): 171 | raise QgsProcessingException(self.tr('Choose another output folder!', 'Escolha outra pasta de destino!')) 172 | else: 173 | head, arq = os.path.split(filepath) 174 | shutil.copy(filepath, 175 | os.path.join(destino, prefixo + "{:05d}.".format(cont+1) + arq.split('.')[-1]) if renomear else os.path.join(destino, arq)) 176 | if feedback.isCanceled(): 177 | break 178 | feedback.setProgress(int((cont) * total)) 179 | 180 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 181 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 182 | 183 | return {} 184 | -------------------------------------------------------------------------------- /processing_provider/Drone_overviewsJPEG.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Drone_overviewsJPEG.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-11-01' 16 | __copyright__ = '(C) 2021, Leandro França' 17 | 18 | from PyQt5.QtCore import QCoreApplication, QVariant 19 | from qgis.core import (QgsProcessing, 20 | QgsFeatureSink, 21 | QgsWkbTypes, 22 | QgsFields, 23 | QgsField, 24 | QgsFeature, 25 | QgsPointXY, 26 | QgsGeometry, 27 | QgsProcessingException, 28 | QgsProcessingAlgorithm, 29 | QgsProcessingParameterString, 30 | QgsProcessingParameterNumber, 31 | QgsProcessingParameterField, 32 | QgsProcessingParameterBoolean, 33 | QgsProcessingParameterCrs, 34 | QgsProcessingParameterEnum, 35 | QgsFeatureRequest, 36 | QgsExpression, 37 | QgsProcessingParameterFeatureSource, 38 | QgsProcessingParameterFeatureSink, 39 | QgsProcessingParameterFileDestination, 40 | QgsProcessingParameterMultipleLayers, 41 | QgsProcessingParameterRasterLayer, 42 | QgsProcessingParameterRasterDestination, 43 | QgsApplication, 44 | QgsProject, 45 | QgsRasterLayer, 46 | QgsCoordinateTransform, 47 | QgsCoordinateReferenceSystem) 48 | 49 | from osgeo import osr, gdal_array, gdal # https://gdal.org/programs/gdaladdo.html 50 | from lftools.geocapt.imgs import Imgs 51 | from lftools.translations.translate import translate 52 | from qgis.PyQt.QtGui import QIcon 53 | from qgis.utils import iface 54 | import os 55 | 56 | class OverviewsJPEG(QgsProcessingAlgorithm): 57 | 58 | LOC = QgsApplication.locale()[:2] 59 | 60 | def tr(self, *string): 61 | return translate(string, self.LOC) 62 | 63 | def createInstance(self): 64 | return OverviewsJPEG() 65 | 66 | def name(self): 67 | return 'overviewsjpeg' 68 | 69 | def displayName(self): 70 | return self.tr('Overviews with JPEG compression', 'Pirâmides com Compressão JPEG') 71 | 72 | def group(self): 73 | return self.tr('Drones') 74 | 75 | def groupId(self): 76 | return 'drones' 77 | 78 | def tags(self): 79 | return self.tr('drone,compression,reduce,size,JPEG,JPG,photometric,compact,image,overviews,piramides,faster,velocity').split(',') 80 | 81 | def icon(self): 82 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/drone.png')) 83 | 84 | txt_en = 'This tool aims to create an Overviews file (.ovr). This algorithm has the advantage of applying a JPEG compression at each level, greatly reducing the generated file size.' 85 | txt_pt = 'Esta ferramenta tem como objetivo criar um arquivo .ovr, correspondente às Overviews (ou pirâmides, em português). Este algoritmo tem a vantagem de aplicar uma compressão JPEG em cada nível, reduzindo bastante o tamanho do arquivo gerado.' 86 | figure = 'images/tutorial/raster_overviews.jpg' 87 | 88 | def shortHelpString(self): 89 | social_BW = Imgs().social_BW 90 | footer = '''
91 | 92 |
93 |
94 |

95 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 96 |

'''+ social_BW + '''
97 | ''' 98 | return self.tr(self.txt_en, self.txt_pt) + footer 99 | 100 | def tags(self): 101 | return self.tr('jpeg,jpg,compressão,compression,compress,photo,comprimir,compact').split(',') 102 | 103 | RasterIN ='RasterIN' 104 | LEVELS = 'LEVELS' 105 | TYPE_GEN = 'TYPE_GEN' 106 | generalization = 'nearest,average,rms,bilinear,gauss,cubic,cubicspline,lanczos,average_magphase,mode'.split(',') 107 | 108 | def initAlgorithm(self, config=None): 109 | # INPUT 110 | self.addParameter( 111 | QgsProcessingParameterRasterLayer( 112 | self.RasterIN, 113 | self.tr('RGB Raster', 'Raster RGB'), 114 | [QgsProcessing.TypeRaster] 115 | ) 116 | ) 117 | 118 | 119 | self.addParameter( 120 | QgsProcessingParameterEnum( 121 | self.TYPE_GEN, 122 | self.tr('Resampling method', 'Método de reamostragem'), 123 | options = self.generalization, 124 | defaultValue= 1 125 | ) 126 | ) 127 | 128 | self.addParameter( 129 | QgsProcessingParameterString( 130 | self.LEVELS, 131 | self.tr('Factors', 'Fatores'), 132 | defaultValue = '2,4,8,16' 133 | ) 134 | ) 135 | 136 | def processAlgorithm(self, parameters, context, feedback): 137 | 138 | RasterIN = self.parameterAsRasterLayer( 139 | parameters, 140 | self.RasterIN, 141 | context 142 | ) 143 | if RasterIN is None: 144 | raise QgsProcessingException(self.invalidSourceError(parameters, self.RasterIN)) 145 | RasterIN = RasterIN.dataProvider().dataSourceUri() 146 | 147 | tipo = self.parameterAsEnum( 148 | parameters, 149 | self.TYPE_GEN, 150 | context 151 | ) 152 | tipo = self.generalization[tipo] 153 | 154 | 155 | levels = self.parameterAsString( 156 | parameters, 157 | self.LEVELS, 158 | context 159 | ) 160 | levels = eval ('[' + levels + ']') 161 | 162 | # Abrindo imagem e verificando número de bandas 163 | raster = gdal.OpenEx(RasterIN, gdal.OF_RASTER | gdal.OF_READONLY) 164 | nbands = raster.RasterCount 165 | 166 | gdal.SetConfigOption('COMPRESS_OVERVIEW', 'JPEG') 167 | # Definindo tipo de compressão JPEG para os OVR 168 | if nbands == 3: 169 | gdal.SetConfigOption('PHOTOMETRIC_OVERVIEW', 'YCBCR') 170 | elif nbands == 4: 171 | gdal.SetConfigOption('PHOTOMETRIC_OVERVIEW', 'RGB') 172 | else: 173 | raise QgsProcessingException(self.tr('The image must be RGB with 3 or 4 bands (alpha)!', 'A imagem deve ser RGB com 3 ou 4 bandas (alfa)!')) 174 | 175 | gdal.SetConfigOption('INTERLEAVE_OVERVIEW', 'PIXEL') 176 | 177 | # Criando as Overviews 178 | feedback.pushInfo(self.tr('Creating the Overviews...', 'Criando as Overviews...')) 179 | raster.BuildOverviews(tipo, levels) 180 | 181 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 182 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 183 | 184 | return {} 185 | 186 | def postProcessAlgorithm(self, context, feedback): 187 | canvas = iface.mapCanvas() 188 | canvas.refresh() 189 | return {} 190 | -------------------------------------------------------------------------------- /processing_provider/Drone_photosByBlocks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Drone_photosByBlocks.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-11-07' 16 | __copyright__ = '(C) 2021, Leandro França' 17 | 18 | from qgis.PyQt.QtCore import QCoreApplication 19 | from qgis.core import (QgsApplication, 20 | QgsProcessingParameterVectorLayer, 21 | QgsGeometry, 22 | QgsProcessing, 23 | QgsProcessingParameterField, 24 | QgsProcessingParameterString, 25 | QgsProcessingParameterEnum, 26 | QgsProcessingParameterBoolean, 27 | QgsProcessingParameterFile, 28 | QgsFeatureSink, 29 | QgsProcessingException, 30 | QgsProcessingAlgorithm, 31 | QgsProcessingParameterFeatureSource, 32 | QgsProcessingParameterFeatureSink) 33 | from lftools.geocapt.imgs import Imgs 34 | from lftools.translations.translate import translate 35 | import os, shutil 36 | from qgis.PyQt.QtGui import QIcon 37 | 38 | class PhotosByBlocks(QgsProcessingAlgorithm): 39 | 40 | LOC = QgsApplication.locale()[:2] 41 | 42 | def tr(self, *string): 43 | return translate(string, self.LOC) 44 | 45 | def createInstance(self): 46 | return PhotosByBlocks() 47 | 48 | def name(self): 49 | return 'photosbyblocks' 50 | 51 | def displayName(self): 52 | return self.tr('Photos by blocks', 'Fotos por blocos') 53 | 54 | def group(self): 55 | return self.tr('Drones') 56 | 57 | def groupId(self): 58 | return 'drones' 59 | 60 | def tags(self): 61 | return self.tr('drones,fotografia,photography,blocks,separate,separar,organize,organizar').split(',') 62 | 63 | def icon(self): 64 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/drone.png')) 65 | 66 | txt_en = 'This tool separates drone photographs into new folders to be processed by blocks, from a layer of polygons (blocks) and from layers of geotagged photographs.' 67 | txt_pt = 'Esta ferramenta separa fotografias de drones em novas pastas para serem processadas por blocos, a partir de uma camada de polígonos (blocos) e da camadas de fotografias com geotag.' 68 | figure = 'images/tutorial/drone_photosByBlocks.jpg' 69 | 70 | def shortHelpString(self): 71 | social_BW = Imgs().social_BW 72 | footer = '''
73 | 74 |
75 |
76 |

77 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 78 |

'''+ social_BW + '''
79 | ''' 80 | return self.tr(self.txt_en, self.txt_pt) + footer 81 | 82 | POINTS = 'POINTS' 83 | FILEPATH = 'FILEPATH' 84 | BLOCKS = 'BLOCKS' 85 | PREFIX = 'PREFIX' 86 | FOLDER = 'FOLDER' 87 | 88 | def initAlgorithm(self, config=None): 89 | self.addParameter( 90 | QgsProcessingParameterVectorLayer( 91 | self.POINTS, 92 | self.tr('Points', 'Pontos'), 93 | [QgsProcessing.TypeVectorPoint] 94 | ) 95 | ) 96 | 97 | self.addParameter( 98 | QgsProcessingParameterField( 99 | self.FILEPATH, 100 | self.tr('Field with file path', 'Campo com o caminho do arquivo'), 101 | parentLayerParameterName=self.POINTS, 102 | type=QgsProcessingParameterField.String 103 | ) 104 | ) 105 | 106 | self.addParameter( 107 | QgsProcessingParameterVectorLayer( 108 | self.BLOCKS, 109 | self.tr('Blocks', 'Blocos'), 110 | [QgsProcessing.TypeVectorPolygon] 111 | ) 112 | ) 113 | 114 | self.addParameter( 115 | QgsProcessingParameterString( 116 | self.PREFIX, 117 | self.tr('Folder name prefix', 'Prefixo do nome da pasta'), 118 | defaultValue = self.tr('block_', 'bloco_') 119 | ) 120 | ) 121 | 122 | self.addParameter( 123 | QgsProcessingParameterFile( 124 | self.FOLDER, 125 | self.tr('Folder with raster files', 'Pasta com arquivos raster'), 126 | behavior=QgsProcessingParameterFile.Folder, 127 | defaultValue=None 128 | ) 129 | ) 130 | 131 | def processAlgorithm(self, parameters, context, feedback): 132 | 133 | pontos = self.parameterAsVectorLayer( 134 | parameters, 135 | self.POINTS, 136 | context 137 | ) 138 | if pontos is None: 139 | raise QgsProcessingException(self.invalidSourceError(parameters, self.POINTS)) 140 | 141 | poligono = self.parameterAsVectorLayer( 142 | parameters, 143 | self.BLOCKS, 144 | context 145 | ) 146 | if poligono is None: 147 | raise QgsProcessingException(self.invalidSourceError(parameters, self.BLOCKS)) 148 | 149 | campo = self.parameterAsFields( 150 | parameters, 151 | self.FILEPATH, 152 | context 153 | ) 154 | if campo is None: 155 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FILEPATH)) 156 | 157 | columnIndex = pontos.fields().indexFromName(campo[0]) 158 | 159 | prefixo = self.parameterAsString( 160 | parameters, 161 | self.PREFIX, 162 | context 163 | ) 164 | 165 | pasta = self.parameterAsFile( 166 | parameters, 167 | self.FOLDER, 168 | context 169 | ) 170 | if not pasta: 171 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FOLDER)) 172 | 173 | # As duas camadas devem ter o mesmo SRC 174 | if poligono.crs() != pontos.crs(): 175 | raise QgsProcessingException(self.tr('Both layers must have the same CRS!', 'As duas camadas devem ter o mesmo SRC!')) 176 | 177 | # Copiando arquivos para as novas pastas 178 | total = 100.0 / (poligono.featureCount()*pontos.featureCount()) 179 | block_count, cont = 1, 1 180 | for pol in poligono.getFeatures(): 181 | geom_pol = pol.geometry() 182 | destino = os.path.join(pasta, prefixo + str(block_count)) 183 | os.mkdir(destino) 184 | for pnt in pontos.getFeatures(): 185 | geom_pnt = pnt.geometry() 186 | if geom_pnt.intersects(geom_pol): 187 | origem = pnt[columnIndex] 188 | nome = os.path.split(origem)[-1] 189 | shutil.copy2(origem, os.path.join(destino, nome)) 190 | if feedback.isCanceled(): 191 | break 192 | feedback.setProgress(int((cont) * total)) 193 | cont += 1 194 | block_count += 1 195 | 196 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 197 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 198 | 199 | return {} 200 | -------------------------------------------------------------------------------- /processing_provider/Easy_SelectByKeyAtt.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Easy_SelectByKeyAtt.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2024-11-10' 16 | __copyright__ = '(C) 2024, Leandro França' 17 | 18 | from PyQt5.QtCore import QCoreApplication, QVariant 19 | from qgis.core import * 20 | import numpy as np 21 | from pyproj.crs import CRS 22 | from lftools.geocapt.imgs import Imgs 23 | from lftools.geocapt.cartography import LayerIs3D 24 | from lftools.translations.translate import translate 25 | from lftools.geocapt.dip import Interpolar 26 | import os, processing 27 | from qgis.PyQt.QtGui import QIcon 28 | 29 | class SelectByKeyAtt(QgsProcessingAlgorithm): 30 | 31 | LOC = QgsApplication.locale()[:2] 32 | 33 | def tr(self, *string): 34 | return translate(string, self.LOC) 35 | 36 | def createInstance(self): 37 | return SelectByKeyAtt() 38 | 39 | def name(self): 40 | return 'SelectByKeyAtt'.lower() 41 | 42 | def displayName(self): 43 | return self.tr('Select by key attribute', 'Selecionar por atributo chave') 44 | 45 | def group(self): 46 | return self.tr('Easy', 'Mão na Roda') 47 | 48 | def groupId(self): 49 | return 'easy' 50 | 51 | def tags(self): 52 | return self.tr('selecionar,pimary,key,foreing,estrangeira,chave,selected,relação,relation').split(',') 53 | 54 | def icon(self): 55 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/easy.png')) 56 | 57 | txt_en = '''This tool allows you to select features that share the same foreign key attribute from multiple layers based on the primary key attribute of a selected feature from another layer. 58 | Note: Enter the foreign key field name if it is not the same as the primary key field name.''' 59 | txt_pt = '''Esta ferramenta permite selecionar feições que compartilham o mesmo atributo de chave estrangeira de diversas camadas com base no atributo de chave primária de uma feição selecionada de outra camada. 60 | Nota: Insira o nome do campo de chave estrangeira se não for igual ao nome do campo de chave primária.''' 61 | figure = 'images/tutorial/easy_selectByKey.jpg' 62 | 63 | def shortHelpString(self): 64 | social_BW = Imgs().social_BW 65 | footer = '''
66 | 67 |
68 |
69 |

70 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 71 |

'''+ social_BW + '''
72 | ''' 73 | return self.tr(self.txt_en, self.txt_pt) + footer 74 | 75 | PRIMARY = 'PRIMARY' 76 | PRIMARY_FIELD = 'PRIMARY_FIELD' 77 | FOREIGNS ='FOREIGNS' 78 | FOREIGNS_FIELD = 'FOREIGNS_FIELD' 79 | 80 | def initAlgorithm(self, config=None): 81 | 82 | # INPUT 83 | self.addParameter( 84 | QgsProcessingParameterVectorLayer( 85 | self.PRIMARY, 86 | self.tr('Input Layer', 'Camada de entrada'), 87 | [QgsProcessing.TypeVectorAnyGeometry] 88 | ) 89 | ) 90 | 91 | self.addParameter( 92 | QgsProcessingParameterField( 93 | self.PRIMARY_FIELD, 94 | self.tr('Primary key', 'Chave primária'), 95 | parentLayerParameterName = self.PRIMARY 96 | ) 97 | ) 98 | 99 | self.addParameter( 100 | QgsProcessingParameterMultipleLayers( 101 | self.FOREIGNS, 102 | self.tr('Layers', 'Camadas'), 103 | layerType = QgsProcessing.TypeVectorAnyGeometry 104 | ) 105 | ) 106 | 107 | self.addParameter( 108 | QgsProcessingParameterString( 109 | self.FOREIGNS_FIELD, 110 | self.tr('Foreign key', 'Chave estrangeira'), 111 | optional = True 112 | ) 113 | ) 114 | 115 | 116 | def processAlgorithm(self, parameters, context, feedback): 117 | 118 | camada = self.parameterAsVectorLayer( 119 | parameters, 120 | self.PRIMARY, 121 | context 122 | ) 123 | if camada is None: 124 | raise QgsProcessingException(self.invalidSourceError(parameters, self.PRIMARY)) 125 | 126 | campo = self.parameterAsFields( 127 | parameters, 128 | self.PRIMARY_FIELD, 129 | context 130 | ) 131 | if campo is None: 132 | raise QgsProcessingException(self.invalidSourceError(parameters, self.PRIMARY_FIELD)) 133 | 134 | # Verificar se existe apenas uma feição selecionada 135 | if camada.selectedFeatureCount() != 1: 136 | raise QgsProcessingException(self.tr('At least one feature must be selected!', 'Pelo menos uma feição deve ser selecionada!')) 137 | 138 | campo_indice_pk = camada.fields().indexFromName(campo[0]) 139 | campo_nome_pk = campo[0] 140 | 141 | layers = self.parameterAsLayerList( 142 | parameters, 143 | self.FOREIGNS, 144 | context 145 | ) 146 | 147 | campo_nome_fk = self.parameterAsString( 148 | parameters, 149 | self.FOREIGNS_FIELD, 150 | context 151 | ) 152 | 153 | if campo_nome_fk is None or campo_nome_fk == '': 154 | campo_nome_fk = campo_nome_pk 155 | 156 | # Obtendo o atributo chave 157 | for feat in camada.getSelectedFeatures(): 158 | att = feat[campo_nome_pk] 159 | 160 | # Expressão para seleção 161 | expressao = QgsExpression('"{}" = \'{}\''.format(campo_nome_fk, att)) 162 | 163 | for layer in layers: 164 | if campo_nome_fk in [field.name() for field in layer.fields()]: 165 | ids_selecionados = [] 166 | for feat in layer.getFeatures(QgsFeatureRequest(expressao)): 167 | ids_selecionados.append(feat.id()) 168 | layer.selectByIds(ids_selecionados) 169 | else: 170 | feedback.pushInfo(self.tr('Layer {} has no key field!', 'A camada {} não possui campo chave!').format(layer.name())) 171 | 172 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 173 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 174 | 175 | return {} 176 | -------------------------------------------------------------------------------- /processing_provider/Post_ChangeEnconding.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Post_ChangeEnconding.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-03-10' 16 | __copyright__ = '(C) 2020, Leandro França' 17 | 18 | from PyQt5.QtCore import QCoreApplication, QVariant 19 | from qgis.core import (QgsProcessing, 20 | QgsProcessingException, 21 | QgsProcessingAlgorithm, 22 | QgsProcessingParameterString, 23 | QgsProcessingParameterBoolean, 24 | QgsProcessingParameterEnum, 25 | QgsProcessingParameterRasterLayer, 26 | QgsProcessingParameterFile, 27 | QgsProcessingParameterFileDestination, 28 | QgsApplication, 29 | QgsRasterLayer, 30 | QgsCoordinateReferenceSystem) 31 | 32 | from lftools.geocapt.imgs import Imgs 33 | from lftools.translations.translate import translate 34 | import os 35 | from qgis.PyQt.QtGui import QIcon 36 | 37 | class ChangeEnconding(QgsProcessingAlgorithm): 38 | 39 | LOC = QgsApplication.locale()[:2] 40 | 41 | def tr(self, *string): 42 | return translate(string, self.LOC) 43 | 44 | def createInstance(self): 45 | return ChangeEnconding() 46 | 47 | def name(self): 48 | return 'changeencoding' 49 | 50 | def displayName(self): 51 | return self.tr('Change SQL encoding', 'Trocar codificação de SQL') 52 | 53 | def group(self): 54 | return self.tr('PostGIS') 55 | 56 | def groupId(self): 57 | return 'postgis' 58 | 59 | def tags(self): 60 | return self.tr('postgis,postgresql,database,BD,DB,restore,backup,manager,import,encoding,sql,change').split(',') 61 | 62 | def icon(self): 63 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/postgis.png')) 64 | 65 | figure = 'images/tutorial/post_encoding.jpg' 66 | txt_en = '''This tool changes the encoding type of a .sql file. A new file will be created with the user-defined encoding. 67 | In some cases, this is a possible solution to transfer data between different operating systems, for example from Windows to Linux, and vice versa.''' 68 | txt_pt = '''Esta ferramenta realiza a troca do tipo de codificação de um arquivo .sql. Um novo arquivo será criado com a codificação definida pelo usuário. 69 | Em alguns casos, esse processo é uma possível solução para transferir dados entre diferentes sistemas operacionais, por exemplo de Window para Linux, e vice-versa.''' 70 | 71 | def shortHelpString(self): 72 | social_BW = Imgs().social_BW 73 | footer = '''
74 | 75 |
76 |
77 |

78 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 79 |

'''+ social_BW + '''
80 | ''' 81 | return self.tr(self.txt_en, self.txt_pt) + footer 82 | 83 | 84 | FILE ='FILE' 85 | ORIGINAL = 'ORIGINAL' 86 | CHANGED = 'CHANGED' 87 | 88 | def initAlgorithm(self, config=None): 89 | # INPUT 90 | self.addParameter( 91 | QgsProcessingParameterFile( 92 | self.FILE, 93 | self.tr('SQL File', 'Arquivo SQL'), 94 | extension = 'sql' 95 | ) 96 | ) 97 | 98 | self.addParameter( 99 | QgsProcessingParameterString( 100 | self.ORIGINAL, 101 | self.tr('Original encoding', 'Codificação original'), 102 | defaultValue = 'Portuguese_Brazil.1252' 103 | ) 104 | ) 105 | 106 | self.addParameter( 107 | QgsProcessingParameterString( 108 | self.CHANGED, 109 | self.tr('New encoding', 'Nova codificação'), 110 | defaultValue = 'pt_BR.UTF-8' 111 | ) 112 | ) 113 | 114 | 115 | def processAlgorithm(self, parameters, context, feedback): 116 | 117 | file_path = self.parameterAsFile( 118 | parameters, 119 | self.FILE, 120 | context 121 | ) 122 | if not file_path: 123 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FILE)) 124 | 125 | original = self.parameterAsString( 126 | parameters, 127 | self.ORIGINAL, 128 | context 129 | ) 130 | 131 | changed = self.parameterAsString( 132 | parameters, 133 | self.CHANGED, 134 | context 135 | ) 136 | 137 | arq = open(file_path, 'r') 138 | data = arq.read() 139 | arq.close() 140 | data = data.replace(original, changed) 141 | path, file = os.path.split(file_path) 142 | new_file = file[:-3] + changed + '.sql' 143 | arq = open(os.path.join(path, new_file), 'w') 144 | arq.write(data) 145 | arq.close() 146 | 147 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 148 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 149 | 150 | return {} 151 | -------------------------------------------------------------------------------- /processing_provider/Post_Restore.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Post_Restore.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2021-03-09' 16 | __copyright__ = '(C) 2020, Leandro França' 17 | 18 | from PyQt5.QtCore import QCoreApplication, QVariant 19 | from qgis.core import (QgsProcessing, 20 | QgsProcessingException, 21 | QgsProcessingAlgorithm, 22 | QgsProcessingParameterString, 23 | QgsProcessingParameterBoolean, 24 | QgsProcessingParameterEnum, 25 | QgsProcessingParameterRasterLayer, 26 | QgsProcessingParameterFile, 27 | QgsProcessingParameterFileDestination, 28 | QgsApplication, 29 | QgsRasterLayer, 30 | QgsCoordinateReferenceSystem) 31 | 32 | from lftools.geocapt.imgs import Imgs 33 | from lftools.translations.translate import translate 34 | import os 35 | from qgis.PyQt.QtGui import QIcon 36 | 37 | class Restore(QgsProcessingAlgorithm): 38 | 39 | LOC = QgsApplication.locale()[:2] 40 | 41 | def tr(self, *string): 42 | return translate(string, self.LOC) 43 | 44 | def createInstance(self): 45 | return Restore() 46 | 47 | def name(self): 48 | return 'restore' 49 | 50 | def displayName(self): 51 | return self.tr('Restore database', 'Restaurar BD') 52 | 53 | def group(self): 54 | return self.tr('PostGIS') 55 | 56 | def groupId(self): 57 | return 'postgis' 58 | 59 | def tags(self): 60 | return self.tr('postgis,postgresql,database,BD,DB,restore,backup,manager,export').split(',') 61 | 62 | def icon(self): 63 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/postgis.png')) 64 | 65 | txt_en = 'This tool allows you to restore a database content by importing all the backup information in a ".sql" file into a PostgreSQL server.' 66 | txt_pt = 'Esta ferramenta permite restaurar, ou seja, importar um banco de dados para um servidor PostgreSQL, a partir de um arquivo de backup no formato ".sql".' 67 | figure = 'images/tutorial/post_restore.jpg' 68 | 69 | def shortHelpString(self): 70 | social_BW = Imgs().social_BW 71 | footer = '''
72 | 73 |
74 |
75 |

76 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 77 |

'''+ social_BW + '''
78 | ''' 79 | return self.tr(self.txt_en, self.txt_pt) + footer 80 | 81 | 82 | FILE ='FILE' 83 | HOST = 'HOST' 84 | VERSION = 'VERSION' 85 | USER = 'USER' 86 | PORT = 'PORT' 87 | versions = ['9.5', '9.6', '10', '11', '12', '13', '14', '15', '16', '17'] 88 | 89 | def initAlgorithm(self, config=None): 90 | # INPUT 91 | self.addParameter( 92 | QgsProcessingParameterFile( 93 | self.FILE, 94 | self.tr('SQL File', 'Arquivo SQL'), 95 | extension = 'sql' 96 | ) 97 | ) 98 | 99 | self.addParameter( 100 | QgsProcessingParameterString( 101 | self.HOST, 102 | self.tr('Host', 'Host'), 103 | defaultValue = 'localhost' 104 | ) 105 | ) 106 | 107 | self.addParameter( 108 | QgsProcessingParameterString( 109 | self.PORT, 110 | self.tr('Port', 'Porta'), 111 | defaultValue = '5432' 112 | ) 113 | ) 114 | 115 | self.addParameter( 116 | QgsProcessingParameterString( 117 | self.USER, 118 | self.tr('User', 'Usuário'), 119 | defaultValue = 'postgres' 120 | ) 121 | ) 122 | 123 | self.addParameter( 124 | QgsProcessingParameterEnum( 125 | self.VERSION, 126 | self.tr('PostgreSQL version', 'Versão do PostgreSQL'), 127 | options = self.versions, 128 | defaultValue = 8 129 | ) 130 | ) 131 | 132 | def processAlgorithm(self, parameters, context, feedback): 133 | 134 | file_path = self.parameterAsFile( 135 | parameters, 136 | self.FILE, 137 | context 138 | ) 139 | if not file_path: 140 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FILE)) 141 | 142 | host = self.parameterAsString( 143 | parameters, 144 | self.HOST, 145 | context 146 | ) 147 | 148 | version = self.parameterAsEnum( 149 | parameters, 150 | self.VERSION, 151 | context 152 | ) 153 | version = self.versions[version] 154 | 155 | user = self.parameterAsString( 156 | parameters, 157 | self.USER, 158 | context 159 | ) 160 | 161 | port = self.parameterAsString( 162 | parameters, 163 | self.PORT, 164 | context 165 | ) 166 | 167 | # Procurando arquivo psql 168 | win64 = 'C:/Program Files (x86)/PostgreSQL/'+version+'/bin' 169 | win64d = 'D:/Program Files (x86)/PostgreSQL/'+version+'/bin' 170 | win32 = 'C:/Program Files/PostgreSQL/'+version+'/bin' 171 | win32d = 'D:/Program Files/PostgreSQL/'+version+'/bin' 172 | mac = '/Library/PostgreSQL/'+version+'/bin/' 173 | linux = '/usr/lib/postgresql/'+version+'/bin/' 174 | if os.path.isdir(win64): 175 | os.chdir(win64) 176 | elif os.path.isdir(win64d): 177 | os.chdir(win64d) 178 | elif os.path.isdir(win32): 179 | os.chdir(win32) 180 | elif os.path.isdir(win32d): 181 | os.chdir(win32d) 182 | elif os.path.isdir(mac): 183 | os.chdir(mac) 184 | elif os.path.isdir(linux): 185 | os.chdir(linux) 186 | else: 187 | raise QgsProcessingException(self.tr('Make sure your PostgreSQL version is correct!', 'Verifique se a versão do seu PostgreSQL está correta!')) 188 | 189 | # Realizando o Restore 190 | comando ='psql -d postgres -U '+user+' -h '+host+' -p '+port+' -f '+ '"' + file_path + '"' 191 | feedback.pushInfo('\n' + self.tr('Command: ','Comando: ') + comando) 192 | feedback.pushInfo('\n' + self.tr('Starting DB Restore process...', 'Iniciando processo de Restauracao do BD...')) 193 | result = os.system(comando) 194 | 195 | if result==0: 196 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 197 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 198 | else: 199 | feedback.pushInfo(self.tr('There was a problem while executing the command. Please check the input parameters.', 200 | 'Houve algum problema durante a execução do comando. Por favor, verifique os parâmetros de entrada.')) 201 | 202 | return {} 203 | -------------------------------------------------------------------------------- /processing_provider/Rast_extractRasterBand.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Rast_extractRasterBand.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2020-12-15' 16 | __copyright__ = '(C) 2020, Leandro França' 17 | 18 | from PyQt5.QtCore import QCoreApplication, QVariant 19 | from qgis.core import (QgsProcessing, 20 | QgsFeatureSink, 21 | QgsWkbTypes, 22 | QgsFields, 23 | QgsField, 24 | QgsFeature, 25 | QgsPointXY, 26 | QgsGeometry, 27 | QgsProcessingException, 28 | QgsProcessingAlgorithm, 29 | QgsProcessingParameterString, 30 | QgsProcessingParameterField, 31 | QgsProcessingParameterBoolean, 32 | QgsProcessingParameterCrs, 33 | QgsProcessingParameterEnum, 34 | QgsFeatureRequest, 35 | QgsExpression, 36 | QgsProcessingParameterFeatureSource, 37 | QgsProcessingParameterFeatureSink, 38 | QgsProcessingParameterFileDestination, 39 | QgsProcessingParameterRasterLayer, 40 | QgsProcessingParameterBand, 41 | QgsProcessingParameterRasterDestination, 42 | QgsApplication, 43 | QgsProject, 44 | QgsRasterLayer, 45 | QgsCoordinateTransform, 46 | QgsCoordinateReferenceSystem) 47 | 48 | from osgeo import osr, gdal_array, gdal #https://gdal.org/python/ 49 | from lftools.geocapt.imgs import Imgs 50 | from lftools.translations.translate import translate 51 | import os 52 | from qgis.PyQt.QtGui import QIcon 53 | 54 | class ExtractRasterBand(QgsProcessingAlgorithm): 55 | 56 | LOC = QgsApplication.locale()[:2] 57 | 58 | def tr(self, *string): 59 | return translate(string, self.LOC) 60 | 61 | def createInstance(self): 62 | return ExtractRasterBand() 63 | 64 | def name(self): 65 | return 'extractrasterband' 66 | 67 | def displayName(self): 68 | return self.tr('Extract raster band', 'Extrair banda de raster') 69 | 70 | def group(self): 71 | return self.tr('Raster') 72 | 73 | def groupId(self): 74 | return 'raster' 75 | 76 | def tags(self): 77 | return self.tr('bands,raster,extract,color,spectral,frequency,RGB,composite,channel').split(',') 78 | 79 | def icon(self): 80 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/raster.png')) 81 | 82 | txt_en = 'Extracts a difined band of a raster (for multiband rasters).' 83 | txt_pt = 'Extrai uma das bandas de um arquivo raster (para imagens multi-bandas/multi-canal).' 84 | figure = 'images/tutorial/raster_extract_band.jpg' 85 | 86 | def shortHelpString(self): 87 | social_BW = Imgs().social_BW 88 | footer = '''
89 | 90 |
91 |
92 |

93 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 94 |

'''+ social_BW + '''
95 | ''' 96 | return self.tr(self.txt_en, self.txt_pt) + footer 97 | 98 | INPUT = 'INPUT' 99 | BAND = 'BAND' 100 | OUTPUT = 'OUTPUT' 101 | OPEN = 'OPEN' 102 | 103 | def initAlgorithm(self, config=None): 104 | # INPUT 105 | self.addParameter( 106 | QgsProcessingParameterRasterLayer( 107 | self.INPUT, 108 | self.tr('Multiband Input Raster', 'Raster multibandas'), 109 | [QgsProcessing.TypeRaster] 110 | ) 111 | ) 112 | 113 | self.addParameter( 114 | QgsProcessingParameterBand( 115 | self.BAND, 116 | self.tr('Band number', 'Número da banda'), 117 | parentLayerParameterName=self.INPUT, 118 | ) 119 | ) 120 | 121 | # OUTPUT 122 | self.addParameter( 123 | QgsProcessingParameterFileDestination( 124 | self.OUTPUT, 125 | self.tr('Selected band', 'Banda selecionada'), 126 | fileFilter = 'GeoTIFF (*.tif)' 127 | ) 128 | ) 129 | 130 | self.addParameter( 131 | QgsProcessingParameterBoolean( 132 | self.OPEN, 133 | self.tr('Load output raster', 'Carregar raster de saída'), 134 | defaultValue= True 135 | ) 136 | ) 137 | 138 | def processAlgorithm(self, parameters, context, feedback): 139 | 140 | entrada = self.parameterAsRasterLayer( 141 | parameters, 142 | self.INPUT, 143 | context 144 | ) 145 | if entrada is None: 146 | raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) 147 | 148 | n_banda = self.parameterAsInt( 149 | parameters, 150 | self.BAND, 151 | context 152 | ) 153 | if n_banda is None: 154 | raise QgsProcessingException(self.invalidSourceError(parameters, self.BAND)) 155 | 156 | saida = self.parameterAsFileOutput( 157 | parameters, 158 | self.OUTPUT, 159 | context 160 | ) 161 | 162 | Carregar = self.parameterAsBool( 163 | parameters, 164 | self.OPEN, 165 | context 166 | ) 167 | 168 | # Abrir banda 169 | feedback.pushInfo(self.tr('Reading the selected band...', 'Lendo a banda selecionada...')) 170 | image = gdal.Open(entrada.dataProvider().dataSourceUri()) 171 | banda = image.GetRasterBand(n_banda).ReadAsArray() 172 | prj=image.GetProjection() 173 | geotransform = image.GetGeoTransform() 174 | 175 | # Criar objeto CRS 176 | CRS=osr.SpatialReference(wkt=prj) 177 | 178 | # Obter número de linhas e colunas 179 | cols = image.RasterXSize 180 | rows = image.RasterYSize 181 | image=None # fechar magem 182 | 183 | # Pegar tipo de dado do array 184 | GDT = gdal_array.NumericTypeCodeToGDALTypeCode(banda.dtype) 185 | 186 | # Criar imagem com uma única banda 187 | feedback.pushInfo(self.tr('Writing the selected band...', 'Escrevendo a banda selecionada...')) 188 | nova_imagem = gdal.GetDriverByName('GTiff').Create(saida, cols, rows, 1, GDT) 189 | nova_imagem.SetGeoTransform(geotransform) 190 | nova_imagem.SetProjection(CRS.ExportToWkt()) 191 | nova_imagem.GetRasterBand(1).WriteArray(banda) 192 | nova_imagem.FlushCache() # Escrever no disco 193 | nova_imagem = None # Salvar e fechar 194 | CRS = None 195 | 196 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 197 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 198 | self.CAMINHO = saida 199 | self.CARREGAR = Carregar 200 | return {self.OUTPUT: saida} 201 | 202 | def postProcessAlgorithm(self, context, feedback): 203 | if self.CARREGAR: 204 | rlayer = QgsRasterLayer(self.CAMINHO, self.tr('Extracted band', 'Banda extraída')) 205 | QgsProject.instance().addMapLayer(rlayer) 206 | return {} 207 | -------------------------------------------------------------------------------- /processing_provider/Vect_Overlapping.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Vect_Overlapping.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2023-05-14' 16 | __copyright__ = '(C) 2023, Leandro França' 17 | 18 | from qgis.PyQt.QtCore import QCoreApplication, QVariant 19 | from qgis.core import (QgsApplication, 20 | QgsGeometry, 21 | QgsWkbTypes, 22 | QgsFeature, 23 | QgsField, 24 | QgsFields, 25 | QgsProcessing, 26 | QgsSpatialIndex, 27 | QgsFeatureRequest, 28 | QgsProcessingParameterField, 29 | QgsProcessingParameterEnum, 30 | QgsProcessingParameterBoolean, 31 | QgsProcessingParameterNumber, 32 | QgsFeatureSink, 33 | QgsProcessingException, 34 | QgsProcessingAlgorithm, 35 | QgsProcessingParameterFeatureSource, 36 | QgsProcessingParameterFeatureSink) 37 | from lftools.geocapt.imgs import Imgs 38 | from lftools.translations.translate import translate 39 | from lftools.geocapt.cartography import OrientarPoligono 40 | import numpy as np 41 | import os 42 | from qgis.PyQt.QtGui import QIcon 43 | 44 | class Overlapping(QgsProcessingAlgorithm): 45 | 46 | LOC = QgsApplication.locale()[:2] 47 | 48 | def tr(self, *string): 49 | return translate(string, self.LOC) 50 | 51 | def createInstance(self): 52 | return Overlapping() 53 | 54 | def name(self): 55 | return 'overlapping' 56 | 57 | def displayName(self): 58 | return self.tr('Overlapping polygons', 'Sobreposição de polígonos') 59 | 60 | def group(self): 61 | return self.tr('Vector', 'Vetor') 62 | 63 | def groupId(self): 64 | return 'vector' 65 | 66 | def tags(self): 67 | return self.tr('cadastro,parcela,sequence,confrontante,vizinho,neighbours,sobreposição,overlap,cadastre,borderer,loteamento').split(',') 68 | 69 | def icon(self): 70 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/vetor.png')) 71 | 72 | txt_en = '''Identifies the overlap between features of a polygon type layer.''' 73 | txt_pt = '''Identifica a sobreposição entre feições de uma camada do tipo polígono.''' 74 | figure = 'images/tutorial/vect_overlapping.jpg' 75 | 76 | def shortHelpString(self): 77 | social_BW = Imgs().social_BW 78 | footer = '''
79 | 80 |
81 |
82 |

83 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 84 |

'''+ social_BW + '''
85 | ''' 86 | return self.tr(self.txt_en, self.txt_pt) + footer 87 | 88 | INPUT = 'INPUT' 89 | OUTPUT = 'OUTPUT' 90 | 91 | def initAlgorithm(self, config = None): 92 | self.addParameter( 93 | QgsProcessingParameterFeatureSource( 94 | self.INPUT, 95 | self.tr('Polygon layer', 'Camada de polígonos'), 96 | [QgsProcessing.TypeVectorPolygon] 97 | ) 98 | ) 99 | 100 | # OUTPUT 101 | self.addParameter( 102 | QgsProcessingParameterFeatureSink( 103 | self.OUTPUT, 104 | self.tr('Overlapping', 'Sobreposição') 105 | ) 106 | ) 107 | 108 | def processAlgorithm(self, parameters, context, feedback): 109 | 110 | layer = self.parameterAsSource( 111 | parameters, 112 | self.INPUT, 113 | context 114 | ) 115 | if layer is None: 116 | raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) 117 | 118 | 119 | # Camada de Saída 120 | Fields = QgsFields() 121 | itens = { 122 | 'ID1' : QVariant.Int, 123 | 'ID2' : QVariant.Int, 124 | } 125 | for item in itens: 126 | Fields.append(QgsField(item, itens[item])) 127 | (sink, dest_id) = self.parameterAsSink( 128 | parameters, 129 | self.OUTPUT, 130 | context, 131 | Fields, 132 | QgsWkbTypes.Polygon, 133 | layer.sourceCrs() 134 | ) 135 | if sink is None: 136 | raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) 137 | 138 | # Validar: 139 | # não pode ser multipolígono 140 | for feat in layer.getFeatures(): 141 | if feat.geometry().isMultipart(): 142 | raise QgsProcessingException(self.tr('Feature id {} is multipart! Multipart features are not allowed!', 'Feição de id {} é multiparte! Feições multipartes não são permitidas!' ).format(feat.id())) 143 | 144 | feedback.pushInfo(self.tr('Creating spatial index...', 'Criando índice espacial...')) 145 | 146 | index = QgsSpatialIndex(layer.getFeatures()) 147 | 148 | sobreposicoes = [] 149 | feedback.pushInfo(self.tr('Identifying overlapping polygons...', 'Idenficando sobreposição entre polígonos...')) 150 | total = 100.0 / layer.featureCount() if layer.featureCount() else 0 151 | 152 | for current, feat1 in enumerate(layer.getFeatures()): 153 | ID1 = feat1.id() 154 | geom1 = feat1.geometry() 155 | linha1 = QgsGeometry.fromPolylineXY(geom1.asPolygon()[0]) 156 | bbox1 = geom1.boundingBox() 157 | feat_ids = index.intersects(bbox1) 158 | for feat2 in layer.getFeatures(QgsFeatureRequest(feat_ids)): 159 | ID2 = feat2.id() 160 | if ID1 != ID2 and (ID2,ID1) not in sobreposicoes: 161 | geom2 = feat2.geometry() 162 | if geom1.intersects(geom2): 163 | inter = geom1.intersection(geom2) 164 | for item in inter.asGeometryCollection(): 165 | if item.type() == 2: #polygon 166 | sobreposicoes += [(ID1, ID2)] 167 | if item.isMultipart(): 168 | coords = item.asMultiPolygon() 169 | for coord in coords: 170 | feature = QgsFeature(Fields) 171 | feature.setGeometry(QgsGeometry.fromPolygonXY(coord)) 172 | feature.setAttributes([ID1, ID2]) 173 | sink.addFeature(feature, QgsFeatureSink.FastInsert) 174 | else: 175 | feature = QgsFeature(Fields) 176 | feature.setGeometry(item) 177 | feature.setAttributes([ID1, ID2]) 178 | sink.addFeature(feature, QgsFeatureSink.FastInsert) 179 | if feedback.isCanceled(): 180 | break 181 | feedback.setProgress(int((current+1) * total)) 182 | 183 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 184 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 185 | 186 | return {self.OUTPUT: dest_id} 187 | -------------------------------------------------------------------------------- /processing_provider/Vect_PointsToPolygon.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Vect_PointsToPolygon.py 5 | *************************************************************************** 6 | * * 7 | * This program is free software; you can redistribute it and/or modify * 8 | * it under the terms of the GNU General Public License as published by * 9 | * the Free Software Foundation; either version 2 of the License, or * 10 | * (at your option) any later version. * 11 | * * 12 | *************************************************************************** 13 | """ 14 | __author__ = 'Leandro França' 15 | __date__ = '2023-01-21' 16 | __copyright__ = '(C) 2023, Leandro França' 17 | 18 | from qgis.PyQt.QtCore import QCoreApplication, QVariant 19 | from qgis.core import (QgsApplication, 20 | QgsProcessingParameterFeatureSource, 21 | QgsGeometry, 22 | QgsFeature, 23 | QgsProcessing, 24 | QgsProject, 25 | QgsFields, 26 | QgsField, 27 | QgsWkbTypes, 28 | QgsLineString, 29 | QgsPolygon, 30 | QgsPoint, 31 | QgsPointXY, 32 | QgsProcessingParameterField, 33 | QgsProcessingParameterEnum, 34 | QgsProcessingParameterBoolean, 35 | QgsProcessingParameterNumber, 36 | QgsFeatureSink, 37 | QgsProcessingException, 38 | QgsProcessingAlgorithm, 39 | QgsCoordinateTransform, 40 | QgsProcessingParameterFeatureSink) 41 | from lftools.geocapt.imgs import Imgs 42 | from lftools.translations.translate import translate 43 | import os 44 | from qgis.PyQt.QtGui import QIcon 45 | 46 | class PointsToPolygon(QgsProcessingAlgorithm): 47 | 48 | LOC = QgsApplication.locale()[:2] 49 | 50 | def tr(self, *string): 51 | return translate(string, self.LOC) 52 | 53 | def createInstance(self): 54 | return PointsToPolygon() 55 | 56 | def name(self): 57 | return 'pointstopolygon' 58 | 59 | def displayName(self): 60 | return self.tr('Points to polygon', 'Pontos para polígono') 61 | 62 | def group(self): 63 | return self.tr('Vector', 'Vetor') 64 | 65 | def groupId(self): 66 | return 'vector' 67 | 68 | def tags(self): 69 | return self.tr('sequence,points,pontos,order,ordenar,orientar,polygon,polígono').split(',') 70 | 71 | def icon(self): 72 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/vetor.png')) 73 | 74 | txt_en = 'This tool generates a polygon layer from a point layer and its filled order (sequence) attributes.' 75 | txt_pt = 'Esta ferramenta gera uma camada de polígono a partir de uma camada de pontos e seus atributos de ordem (sequência) preenchidos.' 76 | figure = 'images/tutorial/vect_point2polygon.jpg' 77 | 78 | def shortHelpString(self): 79 | social_BW = Imgs().social_BW 80 | footer = '''
81 | 82 |
83 |
84 |

85 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 86 |

'''+ social_BW + '''
87 | ''' 88 | return self.tr(self.txt_en, self.txt_pt) + footer 89 | 90 | POINTS = 'POINTS' 91 | FIELD = 'FIELD' 92 | POLYGON = 'POLYGON' 93 | 94 | def initAlgorithm(self, config=None): 95 | self.addParameter( 96 | QgsProcessingParameterFeatureSource( 97 | self.POINTS, 98 | self.tr('Point layer', 'Camada de pontos'), 99 | [QgsProcessing.TypeVectorPoint] 100 | ) 101 | ) 102 | 103 | self.addParameter( 104 | QgsProcessingParameterField( 105 | self.FIELD, 106 | self.tr('Sequence Field', 'Campo de ordenação'), 107 | parentLayerParameterName=self.POINTS, 108 | type = QgsProcessingParameterField.Numeric 109 | ) 110 | ) 111 | 112 | self.addParameter( 113 | QgsProcessingParameterFeatureSink( 114 | self.POLYGON, 115 | self.tr('Polygon from points', 'Polígono a partir de pontos') 116 | ) 117 | ) 118 | 119 | def processAlgorithm(self, parameters, context, feedback): 120 | 121 | layer = self.parameterAsSource( 122 | parameters, 123 | self.POINTS, 124 | context 125 | ) 126 | if layer is None: 127 | raise QgsProcessingException(self.invalidSourceError(parameters, self.POINTS)) 128 | 129 | 130 | campo = self.parameterAsFields( 131 | parameters, 132 | self.FIELD, 133 | context 134 | ) 135 | if campo is None: 136 | raise QgsProcessingException(self.invalidSourceError(parameters, self.FIELD)) 137 | 138 | # OUTPUT 139 | Fields = QgsFields() 140 | 141 | itens = { 142 | 'id' : QVariant.Int, 143 | } 144 | for item in itens: 145 | Fields.append(QgsField(item, itens[item])) 146 | 147 | (sink, dest_id) = self.parameterAsSink( 148 | parameters, 149 | self.POLYGON, 150 | context, 151 | Fields, 152 | QgsWkbTypes.PolygonZ if layer.wkbType() != 1 else QgsWkbTypes.Polygon, 153 | layer.sourceCrs() 154 | ) 155 | if sink is None: 156 | raise QgsProcessingException(self.invalidSinkError(parameters, self.ANGLES)) 157 | 158 | # Validando atributos dos dados de entrada 159 | feedback.pushInfo(self.tr('Validating layer attributes...', 'Validando atributos das camadas...' )) 160 | # ponto_limite 161 | ordem_list = list(range(1,layer.featureCount()+1)) 162 | ordem_comp = [] 163 | for feat in layer.getFeatures(): 164 | if feat[campo[0]] > 0: 165 | ordem_comp += [feat[campo[0]]] 166 | else: 167 | raise QgsProcessingException(self.tr('All attributes of the order field (sequence) must be greater than zero and not null!', 'Todos atributos do campo ordem (sequência) devem ser maiores que zero e não nulos!')) 168 | ordem_comp.sort() 169 | if ordem_list != ordem_comp: 170 | raise QgsProcessingException(self.tr('The point sequence field must be filled in correctly!', 'O campo de sequência dos pontos deve preenchido corretamente!')) 171 | 172 | # Pegar coordenadas dos pontos 173 | pontos = {} 174 | for feat in layer.getFeatures(): 175 | geom = feat.geometry() 176 | pnt = geom.constGet() 177 | pontos[feat[campo[0]]] = QgsPoint(pnt.x(), pnt.y(), pnt.z()) if layer.wkbType() != 1 else QgsPointXY(pnt.x(), pnt.y()) 178 | 179 | # Gerar polígono: 180 | COORDS = [] 181 | for ordem in ordem_list: 182 | COORDS += [pontos[ordem]] 183 | COORDS = COORDS + [COORDS[0]] 184 | anel = QgsLineString(COORDS) 185 | pol = QgsPolygon(anel) 186 | Poligono = QgsGeometry(pol) 187 | 188 | feature = QgsFeature() 189 | feature.setGeometry(Poligono) 190 | feature.setAttributes([1]) 191 | sink.addFeature(feature, QgsFeatureSink.FastInsert) 192 | 193 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 194 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 195 | 196 | return {self.POLYGON: dest_id} 197 | -------------------------------------------------------------------------------- /processing_provider/Vect_reverseVertexOrder.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | """ 5 | Vect_reverseVertexOrder.py 6 | *************************************************************************** 7 | * * 8 | * This program is free software; you can redistribute it and/or modify * 9 | * it under the terms of the GNU General Public License as published by * 10 | * the Free Software Foundation; either version 2 of the License, or * 11 | * (at your option) any later version. * 12 | * * 13 | *************************************************************************** 14 | """ 15 | __author__ = 'Leandro França' 16 | __date__ = '2020-02-14' 17 | __copyright__ = '(C) 2021, Leandro França' 18 | 19 | from qgis.PyQt.QtCore import QCoreApplication 20 | from qgis.core import (QgsApplication, 21 | QgsProcessingParameterVectorLayer, 22 | QgsGeometry, 23 | QgsProcessing, 24 | QgsProcessingParameterField, 25 | QgsProcessingParameterBoolean, 26 | QgsFeatureSink, 27 | QgsProcessingException, 28 | QgsProcessingAlgorithm, 29 | QgsProcessingParameterFeatureSource, 30 | QgsProcessingParameterFeatureSink) 31 | from lftools.geocapt.imgs import Imgs 32 | from lftools.translations.translate import translate 33 | import os 34 | from qgis.PyQt.QtGui import QIcon 35 | 36 | class ReverseVertexOrder(QgsProcessingAlgorithm): 37 | 38 | LOC = QgsApplication.locale()[:2] 39 | 40 | def tr(self, *string): 41 | return translate(string, self.LOC) 42 | 43 | def createInstance(self): 44 | return ReverseVertexOrder() 45 | 46 | def name(self): 47 | return 'reversevertexorder' 48 | 49 | def displayName(self): 50 | return self.tr('Reverse vertex order', 'Inverter ordem dos vértices') 51 | 52 | def group(self): 53 | return self.tr('Vector', 'Vetor') 54 | 55 | def groupId(self): 56 | return 'vector' 57 | 58 | def tags(self): 59 | return self.tr('sequence,reverse,vertex,point,organize,orientar,orientation,topography').split(',') 60 | 61 | def icon(self): 62 | return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/vetor.png')) 63 | 64 | txt_en = 'Inverts vertex order for polygons and lines.' 65 | txt_pt = 'Inverte a ordem dos vértices para polígonos e linhas.' 66 | figure = 'images/tutorial/vect_reverse_vertex_sequence.jpg' 67 | 68 | def shortHelpString(self): 69 | social_BW = Imgs().social_BW 70 | footer = '''
71 | 72 |
73 |
74 |

75 | '''+self.tr('Author: Leandro Franca', 'Autor: Leandro França')+''' 76 |

'''+ social_BW + '''
77 | ''' 78 | return self.tr(self.txt_en, self.txt_pt) + footer 79 | 80 | 81 | 82 | INPUT = 'INPUT' 83 | SELECTED = 'SELECTED' 84 | SAVE = 'SAVE' 85 | 86 | def initAlgorithm(self, config=None): 87 | 88 | self.addParameter( 89 | QgsProcessingParameterVectorLayer( 90 | self.INPUT, 91 | self.tr('Input Layer', 'Camada de entrada'), 92 | [QgsProcessing.TypeVectorLine, 93 | QgsProcessing.TypeVectorPolygon] 94 | ) 95 | ) 96 | 97 | self.addParameter( 98 | QgsProcessingParameterBoolean( 99 | self.SELECTED, 100 | self.tr('Only selected', 'Apenas feições selecionadas'), 101 | defaultValue=False 102 | ) 103 | ) 104 | 105 | self.addParameter( 106 | QgsProcessingParameterBoolean( 107 | self.SAVE, 108 | self.tr('Save Editions', 'Salvar Edições'), 109 | defaultValue=True 110 | ) 111 | ) 112 | 113 | def processAlgorithm(self, parameters, context, feedback): 114 | 115 | camada = self.parameterAsVectorLayer( 116 | parameters, 117 | self.INPUT, 118 | context 119 | ) 120 | if camada is None: 121 | raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) 122 | 123 | selecionados = self.parameterAsBool( 124 | parameters, 125 | self.SELECTED, 126 | context 127 | ) 128 | if selecionados is None: 129 | raise QgsProcessingException(self.invalidSourceError(parameters, self.SELECTED)) 130 | 131 | salvar = self.parameterAsBool( 132 | parameters, 133 | self.SAVE, 134 | context 135 | ) 136 | if salvar is None: 137 | raise QgsProcessingException(self.invalidSourceError(parameters, self.SAVE)) 138 | 139 | camada.startEditing() # coloca no modo edição 140 | 141 | if not selecionados: 142 | total = 100.0 / camada.featureCount() if camada.featureCount() else 0 143 | for current, feat in enumerate(camada.getFeatures()): 144 | cont = 0 145 | geom = feat.geometry() 146 | new_geom = self.inv_vertex_order(geom) 147 | camada.changeGeometry(feat.id(), new_geom) 148 | feedback.setProgress(int(current * total)) 149 | else: 150 | total = 100.0 / camada.selectedFeatureCount() if camada.selectedFeatureCount() else 0 151 | for current, feat in enumerate(camada.getSelectedFeatures()): 152 | cont = 0 153 | geom = feat.geometry() 154 | new_geom = self.inv_vertex_order(geom) 155 | camada.changeGeometry(feat.id(), new_geom) 156 | feedback.setProgress(int(current * total)) 157 | 158 | if salvar: 159 | camada.commitChanges() # salva as edições 160 | 161 | feedback.pushInfo(self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) 162 | feedback.pushInfo(self.tr('Leandro Franca - Cartographic Engineer', 'Leandro França - Eng Cart')) 163 | 164 | return {} 165 | 166 | def inv_vertex_order(self, geom): 167 | if geom.type() == 1: #Line 168 | if geom.isMultipart(): 169 | linhas = geom.asMultiPolyline() 170 | newLines = [] 171 | for linha in linhas: 172 | newLine = linha[::-1] 173 | newLines += [newLine] 174 | newGeom = QgsGeometry.fromMultiPolylineXY(newLines) 175 | return newGeom 176 | else: 177 | linha = geom.asPolyline() 178 | newLine = linha[::-1] 179 | newGeom = QgsGeometry.fromPolylineXY(newLine) 180 | return newGeom 181 | elif geom.type() == 2: #Polygon 182 | if geom.isMultipart(): 183 | poligonos = geom.asMultiPolygon() 184 | newPolygons = [] 185 | for pol in poligonos: 186 | newPol = [] 187 | for anel in pol: 188 | newAnel = anel[::-1] 189 | newPol += [newAnel] 190 | newPolygons += [newPol] 191 | newGeom = QgsGeometry.fromMultiPolygonXY(newPolygons) 192 | return newGeom 193 | else: 194 | pol = geom.asPolygon() 195 | newPol = [] 196 | for anel in pol: 197 | newAnel = anel[::-1] 198 | newPol += [newAnel] 199 | newGeom = QgsGeometry.fromPolygonXY(newPol) 200 | return newGeom 201 | else: 202 | return None 203 | -------------------------------------------------------------------------------- /processing_provider/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/processing_provider/__init__.py -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pillow 2 | -------------------------------------------------------------------------------- /scripts/compile-strings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | LRELEASE=$1 3 | LOCALES=$2 4 | 5 | 6 | for LOCALE in ${LOCALES} 7 | do 8 | echo "Processing: ${LOCALE}.ts" 9 | # Note we don't use pylupdate with qt .pro file approach as it is flakey 10 | # about what is made available. 11 | $LRELEASE i18n/${LOCALE}.ts 12 | done 13 | -------------------------------------------------------------------------------- /scripts/run-env-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | QGIS_PREFIX_PATH=/usr/local/qgis-2.0 4 | if [ -n "$1" ]; then 5 | QGIS_PREFIX_PATH=$1 6 | fi 7 | 8 | echo ${QGIS_PREFIX_PATH} 9 | 10 | 11 | export QGIS_PREFIX_PATH=${QGIS_PREFIX_PATH} 12 | export QGIS_PATH=${QGIS_PREFIX_PATH} 13 | export LD_LIBRARY_PATH=${QGIS_PREFIX_PATH}/lib 14 | export PYTHONPATH=${QGIS_PREFIX_PATH}/share/qgis/python:${QGIS_PREFIX_PATH}/share/qgis/python/plugins:${PYTHONPATH} 15 | 16 | echo "QGIS PATH: $QGIS_PREFIX_PATH" 17 | export QGIS_DEBUG=0 18 | export QGIS_LOG_FILE=/tmp/inasafe/realtime/logs/qgis.log 19 | 20 | export PATH=${QGIS_PREFIX_PATH}/bin:$PATH 21 | 22 | echo "This script is intended to be sourced to set up your shell to" 23 | echo "use a QGIS 2.0 built in $QGIS_PREFIX_PATH" 24 | echo 25 | echo "To use it do:" 26 | echo "source $BASH_SOURCE /your/optional/install/path" 27 | echo 28 | echo "Then use the make file supplied here e.g. make guitest" 29 | -------------------------------------------------------------------------------- /scripts/update-strings.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | LOCALES=$* 3 | 4 | # Get newest .py files so we don't update strings unnecessarily 5 | 6 | CHANGED_FILES=0 7 | PYTHON_FILES=`find . -regex ".*\(ui\|py\)$" -type f` 8 | for PYTHON_FILE in $PYTHON_FILES 9 | do 10 | CHANGED=$(stat -c %Y $PYTHON_FILE) 11 | if [ ${CHANGED} -gt ${CHANGED_FILES} ] 12 | then 13 | CHANGED_FILES=${CHANGED} 14 | fi 15 | done 16 | 17 | # Qt translation stuff 18 | # for .ts file 19 | UPDATE=false 20 | for LOCALE in ${LOCALES} 21 | do 22 | TRANSLATION_FILE="i18n/$LOCALE.ts" 23 | if [ ! -f ${TRANSLATION_FILE} ] 24 | then 25 | # Force translation string collection as we have a new language file 26 | touch ${TRANSLATION_FILE} 27 | UPDATE=true 28 | break 29 | fi 30 | 31 | MODIFICATION_TIME=$(stat -c %Y ${TRANSLATION_FILE}) 32 | if [ ${CHANGED_FILES} -gt ${MODIFICATION_TIME} ] 33 | then 34 | # Force translation string collection as a .py file has been updated 35 | UPDATE=true 36 | break 37 | fi 38 | done 39 | 40 | if [ ${UPDATE} == true ] 41 | # retrieve all python files 42 | then 43 | echo ${PYTHON_FILES} 44 | # update .ts 45 | echo "Please provide translations by editing the translation files below:" 46 | for LOCALE in ${LOCALES} 47 | do 48 | echo "i18n/"${LOCALE}".ts" 49 | # Note we don't use pylupdate with qt .pro file approach as it is flakey 50 | # about what is made available. 51 | pylupdate4 -noobsolete ${PYTHON_FILES} -ts i18n/${LOCALE}.ts 52 | done 53 | else 54 | echo "No need to edit any translation files (.ts) because no python files" 55 | echo "has been updated since the last update translation. " 56 | fi 57 | -------------------------------------------------------------------------------- /styles/SVG/multidirectional.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 37 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 54 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- 1 | # import qgis libs so that ve set the correct sip api version 2 | import qgis # pylint: disable=W0611 # NOQA -------------------------------------------------------------------------------- /test/qgis_interface.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """QGIS plugin implementation. 3 | 4 | .. note:: This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | .. note:: This source code was copied from the 'postgis viewer' application 10 | with original authors: 11 | Copyright (c) 2010 by Ivan Mincik, ivan.mincik@gista.sk 12 | Copyright (c) 2011 German Carrillo, geotux_tuxman@linuxmail.org 13 | Copyright (c) 2014 Tim Sutton, tim@linfiniti.com 14 | 15 | """ 16 | 17 | __author__ = 'tim@linfiniti.com' 18 | __revision__ = '$Format:%H$' 19 | __date__ = '10/01/2011' 20 | __copyright__ = ( 21 | 'Copyright (c) 2010 by Ivan Mincik, ivan.mincik@gista.sk and ' 22 | 'Copyright (c) 2011 German Carrillo, geotux_tuxman@linuxmail.org' 23 | 'Copyright (c) 2014 Tim Sutton, tim@linfiniti.com' 24 | ) 25 | 26 | import logging 27 | from qgis.PyQt.QtCore import QObject, pyqtSlot, pyqtSignal 28 | from qgis.core import QgsMapLayerRegistry 29 | from qgis.gui import QgsMapCanvasLayer 30 | LOGGER = logging.getLogger('QGIS') 31 | 32 | 33 | #noinspection PyMethodMayBeStatic,PyPep8Naming 34 | class QgisInterface(QObject): 35 | """Class to expose QGIS objects and functions to plugins. 36 | 37 | This class is here for enabling us to run unit tests only, 38 | so most methods are simply stubs. 39 | """ 40 | currentLayerChanged = pyqtSignal(QgsMapCanvasLayer) 41 | 42 | def __init__(self, canvas): 43 | """Constructor 44 | :param canvas: 45 | """ 46 | QObject.__init__(self) 47 | self.canvas = canvas 48 | # Set up slots so we can mimic the behaviour of QGIS when layers 49 | # are added. 50 | LOGGER.debug('Initialising canvas...') 51 | # noinspection PyArgumentList 52 | QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayers) 53 | # noinspection PyArgumentList 54 | QgsMapLayerRegistry.instance().layerWasAdded.connect(self.addLayer) 55 | # noinspection PyArgumentList 56 | QgsMapLayerRegistry.instance().removeAll.connect(self.removeAllLayers) 57 | 58 | # For processing module 59 | self.destCrs = None 60 | 61 | @pyqtSlot('QStringList') 62 | def addLayers(self, layers): 63 | """Handle layers being added to the registry so they show up in canvas. 64 | 65 | :param layers: list list of map layers that were added 66 | 67 | .. note:: The QgsInterface api does not include this method, 68 | it is added here as a helper to facilitate testing. 69 | """ 70 | #LOGGER.debug('addLayers called on qgis_interface') 71 | #LOGGER.debug('Number of layers being added: %s' % len(layers)) 72 | #LOGGER.debug('Layer Count Before: %s' % len(self.canvas.layers())) 73 | current_layers = self.canvas.layers() 74 | final_layers = [] 75 | for layer in current_layers: 76 | final_layers.append(QgsMapCanvasLayer(layer)) 77 | for layer in layers: 78 | final_layers.append(QgsMapCanvasLayer(layer)) 79 | 80 | self.canvas.setLayerSet(final_layers) 81 | #LOGGER.debug('Layer Count After: %s' % len(self.canvas.layers())) 82 | 83 | @pyqtSlot('QgsMapLayer') 84 | def addLayer(self, layer): 85 | """Handle a layer being added to the registry so it shows up in canvas. 86 | 87 | :param layer: list list of map layers that were added 88 | 89 | .. note: The QgsInterface api does not include this method, it is added 90 | here as a helper to facilitate testing. 91 | 92 | .. note: The addLayer method was deprecated in QGIS 1.8 so you should 93 | not need this method much. 94 | """ 95 | pass 96 | 97 | @pyqtSlot() 98 | def removeAllLayers(self): 99 | """Remove layers from the canvas before they get deleted.""" 100 | self.canvas.setLayerSet([]) 101 | 102 | def newProject(self): 103 | """Create new project.""" 104 | # noinspection PyArgumentList 105 | QgsMapLayerRegistry.instance().removeAllMapLayers() 106 | 107 | # ---------------- API Mock for QgsInterface follows ------------------- 108 | 109 | def zoomFull(self): 110 | """Zoom to the map full extent.""" 111 | pass 112 | 113 | def zoomToPrevious(self): 114 | """Zoom to previous view extent.""" 115 | pass 116 | 117 | def zoomToNext(self): 118 | """Zoom to next view extent.""" 119 | pass 120 | 121 | def zoomToActiveLayer(self): 122 | """Zoom to extent of active layer.""" 123 | pass 124 | 125 | def addVectorLayer(self, path, base_name, provider_key): 126 | """Add a vector layer. 127 | 128 | :param path: Path to layer. 129 | :type path: str 130 | 131 | :param base_name: Base name for layer. 132 | :type base_name: str 133 | 134 | :param provider_key: Provider key e.g. 'ogr' 135 | :type provider_key: str 136 | """ 137 | pass 138 | 139 | def addRasterLayer(self, path, base_name): 140 | """Add a raster layer given a raster layer file name 141 | 142 | :param path: Path to layer. 143 | :type path: str 144 | 145 | :param base_name: Base name for layer. 146 | :type base_name: str 147 | """ 148 | pass 149 | 150 | def activeLayer(self): 151 | """Get pointer to the active layer (layer selected in the legend).""" 152 | # noinspection PyArgumentList 153 | layers = QgsMapLayerRegistry.instance().mapLayers() 154 | for item in layers: 155 | return layers[item] 156 | 157 | def addToolBarIcon(self, action): 158 | """Add an icon to the plugins toolbar. 159 | 160 | :param action: Action to add to the toolbar. 161 | :type action: QAction 162 | """ 163 | pass 164 | 165 | def removeToolBarIcon(self, action): 166 | """Remove an action (icon) from the plugin toolbar. 167 | 168 | :param action: Action to add to the toolbar. 169 | :type action: QAction 170 | """ 171 | pass 172 | 173 | def addToolBar(self, name): 174 | """Add toolbar with specified name. 175 | 176 | :param name: Name for the toolbar. 177 | :type name: str 178 | """ 179 | pass 180 | 181 | def mapCanvas(self): 182 | """Return a pointer to the map canvas.""" 183 | return self.canvas 184 | 185 | def mainWindow(self): 186 | """Return a pointer to the main window. 187 | 188 | In case of QGIS it returns an instance of QgisApp. 189 | """ 190 | pass 191 | 192 | def addDockWidget(self, area, dock_widget): 193 | """Add a dock widget to the main window. 194 | 195 | :param area: Where in the ui the dock should be placed. 196 | :type area: 197 | 198 | :param dock_widget: A dock widget to add to the UI. 199 | :type dock_widget: QDockWidget 200 | """ 201 | pass 202 | 203 | def legendInterface(self): 204 | """Get the legend.""" 205 | return self.canvas 206 | -------------------------------------------------------------------------------- /test/tenbytenraster.asc: -------------------------------------------------------------------------------- 1 | NCOLS 10 2 | NROWS 10 3 | XLLCENTER 1535380.000000 4 | YLLCENTER 5083260.000000 5 | DX 10 6 | DY 10 7 | NODATA_VALUE -9999 8 | 0 1 2 3 4 5 6 7 8 9 9 | 0 1 2 3 4 5 6 7 8 9 10 | 0 1 2 3 4 5 6 7 8 9 11 | 0 1 2 3 4 5 6 7 8 9 12 | 0 1 2 3 4 5 6 7 8 9 13 | 0 1 2 3 4 5 6 7 8 9 14 | 0 1 2 3 4 5 6 7 8 9 15 | 0 1 2 3 4 5 6 7 8 9 16 | 0 1 2 3 4 5 6 7 8 9 17 | 0 1 2 3 4 5 6 7 8 9 18 | CRS 19 | NOTES 20 | -------------------------------------------------------------------------------- /test/tenbytenraster.asc.aux.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Point 4 | 5 | 6 | 7 | 9 8 | 4.5 9 | 0 10 | 2.872281323269 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/tenbytenraster.keywords: -------------------------------------------------------------------------------- 1 | title: Tenbytenraster 2 | -------------------------------------------------------------------------------- /test/tenbytenraster.lic: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tim Sutton, Linfiniti Consulting CC 5 | 6 | 7 | 8 | tenbytenraster.asc 9 | 2700044251 10 | Yes 11 | Tim Sutton 12 | Tim Sutton (QGIS Source Tree) 13 | Tim Sutton 14 | This data is publicly available from QGIS Source Tree. The original 15 | file was created and contributed to QGIS by Tim Sutton. 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/tenbytenraster.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] -------------------------------------------------------------------------------- /test/tenbytenraster.qml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 0 26 | 27 | -------------------------------------------------------------------------------- /test/test_init.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Tests QGIS plugin init.""" 3 | 4 | __author__ = 'Tim Sutton ' 5 | __revision__ = '$Format:%H$' 6 | __date__ = '17/10/2010' 7 | __license__ = "GPL" 8 | __copyright__ = 'Copyright 2012, Australia Indonesia Facility for ' 9 | __copyright__ += 'Disaster Reduction' 10 | 11 | import os 12 | import unittest 13 | import logging 14 | import configparser 15 | 16 | LOGGER = logging.getLogger('QGIS') 17 | 18 | 19 | class TestInit(unittest.TestCase): 20 | """Test that the plugin init is usable for QGIS. 21 | 22 | Based heavily on the validator class by Alessandro 23 | Passoti available here: 24 | 25 | http://github.com/qgis/qgis-django/blob/master/qgis-app/ 26 | plugins/validator.py 27 | 28 | """ 29 | 30 | def test_read_init(self): 31 | """Test that the plugin __init__ will validate on plugins.qgis.org.""" 32 | 33 | # You should update this list according to the latest in 34 | # https://github.com/qgis/qgis-django/blob/master/qgis-app/ 35 | # plugins/validator.py 36 | 37 | required_metadata = [ 38 | 'name', 39 | 'description', 40 | 'version', 41 | 'qgisMinimumVersion', 42 | 'email', 43 | 'author'] 44 | 45 | file_path = os.path.abspath(os.path.join( 46 | os.path.dirname(__file__), os.pardir, 47 | 'metadata.txt')) 48 | LOGGER.info(file_path) 49 | metadata = [] 50 | parser = configparser.ConfigParser() 51 | parser.optionxform = str 52 | parser.read(file_path) 53 | message = 'Cannot find a section named "general" in %s' % file_path 54 | assert parser.has_section('general'), message 55 | metadata.extend(parser.items('general')) 56 | 57 | for expectation in required_metadata: 58 | message = ('Cannot find metadata "%s" in metadata source (%s).' % ( 59 | expectation, file_path)) 60 | 61 | self.assertIn(expectation, dict(metadata), message) 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /test/test_qgis_environment.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Tests for QGIS functionality. 3 | 4 | 5 | .. note:: This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | """ 11 | __author__ = 'tim@linfiniti.com' 12 | __date__ = '20/01/2011' 13 | __copyright__ = ('Copyright 2012, Australia Indonesia Facility for ' 14 | 'Disaster Reduction') 15 | 16 | import os 17 | import unittest 18 | from qgis.core import ( 19 | QgsProviderRegistry, 20 | QgsCoordinateReferenceSystem, 21 | QgsRasterLayer) 22 | 23 | from .utilities import get_qgis_app 24 | QGIS_APP = get_qgis_app() 25 | 26 | 27 | class QGISTest(unittest.TestCase): 28 | """Test the QGIS Environment""" 29 | 30 | def test_qgis_environment(self): 31 | """QGIS environment has the expected providers""" 32 | 33 | r = QgsProviderRegistry.instance() 34 | self.assertIn('gdal', r.providerList()) 35 | self.assertIn('ogr', r.providerList()) 36 | self.assertIn('postgres', r.providerList()) 37 | 38 | def test_projection(self): 39 | """Test that QGIS properly parses a wkt string. 40 | """ 41 | crs = QgsCoordinateReferenceSystem() 42 | wkt = ( 43 | 'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",' 44 | 'SPHEROID["WGS_1984",6378137.0,298.257223563]],' 45 | 'PRIMEM["Greenwich",0.0],UNIT["Degree",' 46 | '0.0174532925199433]]') 47 | crs.createFromWkt(wkt) 48 | auth_id = crs.authid() 49 | expected_auth_id = 'EPSG:4326' 50 | self.assertEqual(auth_id, expected_auth_id) 51 | 52 | # now test for a loaded layer 53 | path = os.path.join(os.path.dirname(__file__), 'tenbytenraster.asc') 54 | title = 'TestRaster' 55 | layer = QgsRasterLayer(path, title) 56 | auth_id = layer.crs().authid() 57 | self.assertEqual(auth_id, expected_auth_id) 58 | 59 | if __name__ == '__main__': 60 | unittest.main() 61 | -------------------------------------------------------------------------------- /test/test_translations.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Safe Translations Test. 3 | 4 | .. note:: This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | """ 10 | from .utilities import get_qgis_app 11 | 12 | __author__ = 'ismailsunni@yahoo.co.id' 13 | __date__ = '12/10/2011' 14 | __copyright__ = ('Copyright 2012, Australia Indonesia Facility for ' 15 | 'Disaster Reduction') 16 | import unittest 17 | import os 18 | 19 | from qgis.PyQt.QtCore import QCoreApplication, QTranslator 20 | 21 | QGIS_APP = get_qgis_app() 22 | 23 | 24 | class SafeTranslationsTest(unittest.TestCase): 25 | """Test translations work.""" 26 | 27 | def setUp(self): 28 | """Runs before each test.""" 29 | if 'LANG' in iter(os.environ.keys()): 30 | os.environ.__delitem__('LANG') 31 | 32 | def tearDown(self): 33 | """Runs after each test.""" 34 | if 'LANG' in iter(os.environ.keys()): 35 | os.environ.__delitem__('LANG') 36 | 37 | def test_qgis_translations(self): 38 | """Test that translations work.""" 39 | parent_path = os.path.join(__file__, os.path.pardir, os.path.pardir) 40 | dir_path = os.path.abspath(parent_path) 41 | file_path = os.path.join( 42 | dir_path, 'i18n', 'af.qm') 43 | translator = QTranslator() 44 | translator.load(file_path) 45 | QCoreApplication.installTranslator(translator) 46 | 47 | expected_message = 'Goeie more' 48 | real_message = QCoreApplication.translate("@default", 'Good morning') 49 | self.assertEqual(real_message, expected_message) 50 | 51 | 52 | if __name__ == "__main__": 53 | suite = unittest.makeSuite(SafeTranslationsTest) 54 | runner = unittest.TextTestRunner(verbosity=2) 55 | runner.run(suite) 56 | -------------------------------------------------------------------------------- /test/utilities.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | """Common functionality used by regression tests.""" 3 | 4 | import sys 5 | import logging 6 | 7 | 8 | LOGGER = logging.getLogger('QGIS') 9 | QGIS_APP = None # Static variable used to hold hand to running QGIS app 10 | CANVAS = None 11 | PARENT = None 12 | IFACE = None 13 | 14 | 15 | def get_qgis_app(): 16 | """ Start one QGIS application to test against. 17 | 18 | :returns: Handle to QGIS app, canvas, iface and parent. If there are any 19 | errors the tuple members will be returned as None. 20 | :rtype: (QgsApplication, CANVAS, IFACE, PARENT) 21 | 22 | If QGIS is already running the handle to that app will be returned. 23 | """ 24 | 25 | try: 26 | from qgis.PyQt import QtGui, QtCore 27 | from qgis.core import QgsApplication 28 | from qgis.gui import QgsMapCanvas 29 | from .qgis_interface import QgisInterface 30 | except ImportError: 31 | return None, None, None, None 32 | 33 | global QGIS_APP # pylint: disable=W0603 34 | 35 | if QGIS_APP is None: 36 | gui_flag = True # All test will run qgis in gui mode 37 | #noinspection PyPep8Naming 38 | QGIS_APP = QgsApplication(sys.argv, gui_flag) 39 | # Make sure QGIS_PREFIX_PATH is set in your env if needed! 40 | QGIS_APP.initQgis() 41 | s = QGIS_APP.showSettings() 42 | LOGGER.debug(s) 43 | 44 | global PARENT # pylint: disable=W0603 45 | if PARENT is None: 46 | #noinspection PyPep8Naming 47 | PARENT = QtGui.QWidget() 48 | 49 | global CANVAS # pylint: disable=W0603 50 | if CANVAS is None: 51 | #noinspection PyPep8Naming 52 | CANVAS = QgsMapCanvas(PARENT) 53 | CANVAS.resize(QtCore.QSize(400, 400)) 54 | 55 | global IFACE # pylint: disable=W0603 56 | if IFACE is None: 57 | # QgisInterface is a stub implementation of the QGIS plugin interface 58 | #noinspection PyPep8Naming 59 | IFACE = QgisInterface(CANVAS) 60 | 61 | return QGIS_APP, CANVAS, IFACE, PARENT 62 | -------------------------------------------------------------------------------- /translations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LEOXINGU/lftools/726cc5eeed13615d4478ade773b59555b47bf7be/translations/__init__.py -------------------------------------------------------------------------------- /translations/translate.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | *************************************************************************** 5 | * * 6 | * This program is free software; you can redistribute it and/or modify * 7 | * it under the terms of the GNU General Public License as published by * 8 | * the Free Software Foundation; either version 2 of the License, or * 9 | * (at your option) any later version. * 10 | * * 11 | *************************************************************************** 12 | """ 13 | __author__ = 'Leandro França' 14 | __date__ = '2024-06-23' 15 | 16 | from lftools.translations.dictionary import dic 17 | 18 | def translate(string, loc): 19 | # Português 20 | if loc == 'pt': 21 | if len(string) == 2: 22 | return string[1] 23 | else: 24 | return string[0] 25 | # Espanhol 26 | elif loc == 'es': 27 | if string[0] in dic: 28 | if loc in dic[string[0]]: 29 | return dic[string[0]][loc] 30 | else: 31 | return string[0] 32 | elif len(string) == 2: 33 | return string[1] 34 | else: 35 | return string[0] 36 | # Inglês 37 | else: 38 | return string[0] 39 | --------------------------------------------------------------------------------