├── .gitignore
├── grid
├── __init__.py
├── proj_util.py
├── lambert_grid_core.py
└── lambert_grid_algorithm.py
├── china_offset
├── __init__.py
├── transform.py
├── bd2wgs.py
├── bd2gcj.py
├── gcj2bd.py
├── wgs2gcj.py
├── gcj2wgs.py
└── wgs2bd.py
├── test
├── tenbytenraster.keywords
├── __init__.py
├── tenbytenraster.prj
├── tenbytenraster.asc
├── tenbytenraster.asc.aux.xml
├── tenbytenraster.lic
├── tenbytenraster.qml
├── test_translations.py
├── utilities.py
├── test_init.py
├── test_qgis_environment.py
└── qgis_interface.py
├── icon.png
├── scripts
├── compile-strings.sh
├── run-env-linux.sh
└── update-strings.sh
├── i18n
└── af.ts
├── help
├── source
│ ├── index.rst
│ └── conf.py
├── make.bat
└── Makefile
├── README.txt
├── metadata.txt
├── __init__.py
├── README.html
├── geohey_toolbox.py
├── pb_tool.cfg
├── geohey_toolbox_provider.py
├── plugin_upload.py
├── Makefile
└── pylintrc
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
--------------------------------------------------------------------------------
/grid/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/china_offset/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/tenbytenraster.keywords:
--------------------------------------------------------------------------------
1 | title: Tenbytenraster
2 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/liuxspro/qgis-geohey-toolbox/qgis3/icon.png
--------------------------------------------------------------------------------
/test/__init__.py:
--------------------------------------------------------------------------------
1 | # import qgis libs so that ve set the correct sip api version
2 | import qgis # pylint: disable=W0611 # NOQA
--------------------------------------------------------------------------------
/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]]
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/i18n/af.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @default
5 |
6 |
7 | Good morning
8 | Goeie more
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/help/source/index.rst:
--------------------------------------------------------------------------------
1 | .. GeoHeyToolbox 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 GeoHeyToolbox'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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | Plugin Builder Results
2 |
3 | Your plugin GeoHeyToolbox was created in:
4 | /Users/sshuair/GIS/GeoHey-Toolbox-qgis3/geoheytoolbox
5 |
6 | Your QGIS plugin directory is located at:
7 | /Users/sshuair/Library/Application Support/QGIS/QGIS3/profiles/default/python/plugins
8 |
9 | What's Next:
10 |
11 | * Copy the entire directory containing your new plugin to the QGIS plugin
12 | directory
13 |
14 | * Run the tests (``make test``)
15 |
16 | * Test the plugin by enabling it in the QGIS plugin manager
17 |
18 | * Customize it by editing the implementation file: ``geoHey_toolbox.py``
19 |
20 | * You can use the Makefile to compile your Ui and resource files when
21 | you make changes. This requires GNU make (gmake)
22 |
23 | For more information, see the PyQGIS Developer Cookbook at:
24 | http://www.qgis.org/pyqgis-cookbook/index.html
25 |
26 | (C) 2011-2018 GeoApt LLC - geoapt.com
27 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/metadata.txt:
--------------------------------------------------------------------------------
1 | # This file contains metadata for your plugin. Since
2 | # version 2.0 of QGIS this is the proper way to supply
3 | # information about a plugin. The old method of
4 | # embedding metadata in __init__.py will
5 | # is no longer supported since version 2.0.
6 |
7 | # This file should be included when you package your plugin.# Mandatory items:
8 |
9 | [general]
10 | name=GeoHey Toolbox
11 | qgisMinimumVersion=3.0
12 | description=GeoHey Toolbox
13 | version=0.4
14 | author=GeoHey
15 | email=sshuair@gmail.com
16 |
17 | about=Currently, the toolbox contain China mars coordinate(火星坐标) convert(WGS, GCJ02 and BaiDu coordinate). 因国家法律规定,不提供转WGS84的工具
18 |
19 | tracker=https://github.com/GeoHey-Team/qgis-geohey-toolbox/issues
20 | repository=https://github.com/GeoHey-Team/qgis-geohey-toolbox
21 | # End of mandatory metadata
22 |
23 | # Recommended items:
24 |
25 | # Uncomment the following line and add your changelog:
26 | changelog=0.4.1
27 | - China mars coordinate convert
28 | - equal area grid
29 | - add QGIS 3 support
30 |
31 | # Tags are comma separated with spaces allowed
32 | tags=China, vector, coordinate, grid
33 |
34 | homepage=https://github.com/GeoHey-Team/qgis-geohey-toolbox
35 | category=Analysis
36 | icon=icon.png
37 | # experimental flag
38 | experimental=False
39 |
40 | # deprecated flag (applies to the whole plugin, not just a single version)
41 | deprecated=False
42 |
43 |
--------------------------------------------------------------------------------
/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 | print ${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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | /***************************************************************************
4 | GeoHeyToolbox
5 | A QGIS plugin
6 | GeoHey Toolbox
7 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
8 | -------------------
9 | begin : 2019-11-09
10 | copyright : (C) 2018 by GeoHey
11 | email : sshuair@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__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 |
30 | # noinspection PyPep8Naming
31 | def classFactory(iface): # pylint: disable=invalid-name
32 | """Load GeoHeyToolbox class from file GeoHeyToolbox.
33 |
34 | :param iface: A QGIS interface instance.
35 | :type iface: QgsInterface
36 | """
37 | #
38 | from .geohey_toolbox import GeoHeyToolboxPlugin
39 | return GeoHeyToolboxPlugin()
40 |
--------------------------------------------------------------------------------
/README.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Plugin Builder Results
4 |
5 | Congratulations! You just built a plugin for QGIS!
6 |
7 |
8 | Your plugin GeoHeyToolbox was created in:
9 | /Users/sshuair/GIS/GeoHey-Toolbox-qgis3/geoheytoolbox
10 |
11 | Your QGIS plugin directory is located at:
12 | /Users/sshuair/Library/Application Support/QGIS/QGIS3/profiles/default/python/plugins
13 |
14 |
What's Next
15 |
16 |
Test the generated sources using make test (or run tests from your IDE)
17 |
Copy the entire directory containing your new plugin to the QGIS plugin directory (see Notes below)
18 |
Test the plugin by enabling it in the QGIS plugin manager and enabling the provider in the Processing Options
19 |
Customize it by editing the implementation file geoHey_toolbox_algorithm.py
20 |
21 | Notes:
22 |
23 |
You can use the Makefile to compile and deploy when you
24 | make changes. This requires GNU make (gmake). The Makefile is ready to use, however you
25 | will have to edit it to add addional Python source files, dialogs, and translations.
26 |
You can also use pb_tool to compile and deploy your plugin. Tweak the pb_tool.cfg file included with your plugin as you add files. Install pb_tool using
27 | pip or easy_install. See http://loc8.cc/pb_tool for more information.
28 |
29 |
30 |
31 |
32 | For information on writing PyQGIS code, see http://loc8.cc/pyqgis_resources for a list of resources.
33 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/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 PyQt5.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 |
--------------------------------------------------------------------------------
/grid/proj_util.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | earth_radius = 6378137.0
4 | radians_per_degree = math.pi / 180.0
5 | degrees_per_radian = 180.0 / math.pi
6 | mercator_boundary = 20037508.342787
7 |
8 | def lonlat2lambert(pt):
9 | lon = pt[0]
10 | lat = pt[1]
11 | if lon > 180:
12 | lon = lon - 180
13 |
14 | x = lon
15 | y = math.sin(lat* radians_per_degree)
16 |
17 | return [x, y]
18 |
19 |
20 | def lambert2lonlat(pt):
21 | x = pt[0]
22 | y = pt[1]
23 | lon = x
24 | lat = math.asin(y) / radians_per_degree
25 |
26 | return [lon, lat]
27 |
28 |
29 | def lonlat2mercator(pt):
30 | lon = pt[0]
31 | if lon > 180:
32 | lon = lon - 180
33 |
34 | lat = pt[1]
35 | x = lon * mercator_boundary / 180
36 | y = math.log(math.tan((90 + lat) * math.pi / 360)) / radians_per_degree
37 | y = y * mercator_boundary / 180
38 |
39 | return [x, y]
40 |
41 | def mercator2lonlat(pt):
42 | lon = pt[0] / mercator_boundary * 180
43 | lat = pt[1] / mercator_boundary * 180
44 | lat = 180 / math.pi * (2 * math.atan(math.exp(lat * radians_per_degree)) - math.pi / 2)
45 |
46 | return [lon, lat]
47 |
48 | # the same as lonlat2mercator
49 | def lonlat2webmercator(ll):
50 | xy = [
51 | earth_radius * ll[0] * radians_per_degree,
52 | earth_radius * math.log(math.tan((math.pi * 0.25) + (0.5 * ll[1] * radians_per_degree)))
53 | ]
54 |
55 | if xy[0] > mercator_boundary:
56 | xy[0] = mercator_boundary
57 | if xy[0] < -mercator_boundary:
58 | xy[0] = -mercator_boundary
59 |
60 | if xy[1] > mercator_boundary:
61 | xy[1] = mercator_boundary
62 | if xy[1] < -mercator_boundary:
63 | xy[1] = -mercator_boundary
64 | return xy
65 |
66 |
67 | # the same to mercator2lonlat
68 | def webmercator2lonlat(xy):
69 | return [
70 | (xy[0] * degrees_per_radian / earth_radius),
71 | ((math.pi * 0.5) - 2.0 * math.atan(math.exp(-xy[1] / earth_radius))) * degrees_per_radian
72 | ]
--------------------------------------------------------------------------------
/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 PyQt5 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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/geohey_toolbox.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | import os
34 | import sys
35 | import inspect
36 |
37 | from qgis.core import QgsProcessingAlgorithm, QgsApplication
38 | from .geohey_toolbox_provider import GeoHeyToolboxProvider
39 |
40 | cmd_folder = os.path.split(inspect.getfile(inspect.currentframe()))[0]
41 |
42 | if cmd_folder not in sys.path:
43 | sys.path.insert(0, cmd_folder)
44 |
45 |
46 | class GeoHeyToolboxPlugin(object):
47 |
48 | def __init__(self):
49 | self.provider = GeoHeyToolboxProvider()
50 |
51 | def initGui(self):
52 | QgsApplication.processingRegistry().addProvider(self.provider)
53 |
54 | def unload(self):
55 | QgsApplication.processingRegistry().removeProvider(self.provider)
56 |
--------------------------------------------------------------------------------
/pb_tool.cfg:
--------------------------------------------------------------------------------
1 | #/***************************************************************************
2 | # GeoHeyToolbox
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 : 2019-11-09
8 | # copyright : (C) 2018 by GeoHey
9 | # email : sshuair@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: geoHey_toolbox
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 geoHey_toolbox.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 |
--------------------------------------------------------------------------------
/geohey_toolbox_provider.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | import os
34 |
35 | from PyQt5.QtGui import QIcon
36 | from qgis.core import QgsProcessingProvider
37 |
38 | from .china_offset.wgs2gcj import WGS2GCJ
39 | from .china_offset.gcj2wgs import GCJ2WGS
40 | from .china_offset.gcj2bd import GCJ2BD
41 | from .china_offset.bd2gcj import BD2GCJ
42 | from .china_offset.wgs2bd import WGS2BD
43 | from .china_offset.bd2wgs import BD2WGS
44 |
45 |
46 | class GeoHeyToolboxProvider(QgsProcessingProvider):
47 |
48 | def __init__(self):
49 | QgsProcessingProvider.__init__(self)
50 |
51 | # Load algorithms
52 | self.alglist = [WGS2GCJ, GCJ2WGS, GCJ2BD, BD2GCJ, WGS2BD, BD2WGS]
53 |
54 | def unload(self):
55 | """
56 | Unloads the provider. Any tear-down steps required by the provider
57 | should be implemented here.
58 | """
59 | pass
60 |
61 | def loadAlgorithms(self):
62 | """
63 | Loads all algorithms belonging to this provider.
64 | """
65 | for alg in self.alglist:
66 | self.addAlgorithm( alg() )
67 |
68 | def id(self):
69 | """
70 | Returns the unique provider id, used for identifying the provider. This
71 | string should be a unique, short, character only string, eg "qgis" or
72 | "gdal". This string should not be localised.
73 | """
74 | return 'GeoHey'
75 |
76 | def name(self):
77 | """
78 | Returns the provider name, which is used to describe the provider
79 | within the GUI.
80 |
81 | This string should be short (e.g. "Lastools") and localised.
82 | """
83 | return self.tr('GeoHey')
84 |
85 | def longName(self):
86 | """
87 | Returns the a longer version of the provider name, which can include
88 | extra details such as version numbers. E.g. "Lastools LIDAR tools
89 | (version 2.2.1)". This string should be localised. The default
90 | implementation returns the same string as name().
91 | """
92 | return self.name()
93 |
94 | def icon(self):
95 | return QIcon(os.path.dirname(__file__) + '/icon.png')
--------------------------------------------------------------------------------
/plugin_upload.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # coding=utf-8
3 | """This script uploads a plugin package on the server.
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 | # Configuration
14 | PROTOCOL = 'http'
15 | SERVER = 'plugins.qgis.org'
16 | PORT = '80'
17 | ENDPOINT = '/plugins/RPC2/'
18 | VERBOSE = False
19 |
20 |
21 | def main(parameters, arguments):
22 | """Main entry point.
23 |
24 | :param parameters: Command line parameters.
25 | :param arguments: Command line arguments.
26 | """
27 | address = "%s://%s:%s@%s:%s%s" % (
28 | PROTOCOL,
29 | parameters.username,
30 | parameters.password,
31 | parameters.server,
32 | parameters.port,
33 | ENDPOINT)
34 | print("Connecting to: %s" % hide_password(address))
35 |
36 | server = xmlrpc.client.ServerProxy(address, verbose=VERBOSE)
37 |
38 | try:
39 | plugin_id, version_id = server.plugin.upload(
40 | xmlrpc.client.Binary(open(arguments[0]).read()))
41 | print("Plugin ID: %s" % plugin_id)
42 | print("Version ID: %s" % version_id)
43 | except xmlrpc.client.ProtocolError as err:
44 | print("A protocol error occurred")
45 | print("URL: %s" % hide_password(err.url, 0))
46 | print("HTTP/HTTPS headers: %s" % err.headers)
47 | print("Error code: %d" % err.errcode)
48 | print("Error message: %s" % err.errmsg)
49 | except xmlrpc.client.Fault as err:
50 | print("A fault occurred")
51 | print("Fault code: %d" % err.faultCode)
52 | print("Fault string: %s" % err.faultString)
53 |
54 |
55 | def hide_password(url, start=6):
56 | """Returns the http url with password part replaced with '*'.
57 |
58 | :param url: URL to upload the plugin to.
59 | :type url: str
60 |
61 | :param start: Position of start of password.
62 | :type start: int
63 | """
64 | start_position = url.find(':', start) + 1
65 | end_position = url.find('@')
66 | return "%s%s%s" % (
67 | url[:start_position],
68 | '*' * (end_position - start_position),
69 | url[end_position:])
70 |
71 |
72 | if __name__ == "__main__":
73 | parser = OptionParser(usage="%prog [options] plugin.zip")
74 | parser.add_option(
75 | "-w", "--password", dest="password",
76 | help="Password for plugin site", metavar="******")
77 | parser.add_option(
78 | "-u", "--username", dest="username",
79 | help="Username of plugin site", metavar="user")
80 | parser.add_option(
81 | "-p", "--port", dest="port",
82 | help="Server port to connect to", metavar="80")
83 | parser.add_option(
84 | "-s", "--server", dest="server",
85 | help="Specify server name", metavar="plugins.qgis.org")
86 | options, args = parser.parse_args()
87 | if len(args) != 1:
88 | print("Please specify zip file.\n")
89 | parser.print_help()
90 | sys.exit(1)
91 | if not options.server:
92 | options.server = SERVER
93 | if not options.port:
94 | options.port = PORT
95 | if not options.username:
96 | # interactive mode
97 | username = getpass.getuser()
98 | print("Please enter user name [%s] :" % username, end=' ')
99 | res = input()
100 | if res != "":
101 | options.username = res
102 | else:
103 | options.username = username
104 | if not options.password:
105 | # interactive mode
106 | options.password = getpass.getpass()
107 | main(options, args)
108 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/grid/lambert_grid_core.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | LambertGrid
6 | lambert grid defination
7 | general grid defination and related operations
8 | -------------------
9 | begin : 2016-11-14
10 | copyright : (C) 2016 by GeoHey
11 | email : xux@geohey.com
12 | ***************************************************************************/
13 | partition equal-area grids using Lambert cylindrical equal-area projection
14 | The Formulae is:
15 | x = longitude - central_meridian
16 | y = sin(latitude)
17 |
18 | grid area(km2) of each level
19 | (0, 255603946.7)
20 | (1, 63900986.7)
21 | (2, 15975246.7)
22 | (3, 3993811.7)
23 | (4, 998452.92)
24 | (5, 249613.23)
25 | (6, 62403.307)
26 | (7, 15600.827)
27 | (8, 3900.2067)
28 | (9, 975.05168)
29 | (10, 243.7629)
30 | (11, 60.94073)
31 | (12, 15.23518)
32 | (13, 3.808796)
33 | (14, 0.952199)
34 | (15, 0.238050)
35 | (16, 0.059512)*
36 | (17, 0.014878)
37 | (18, 0.003720)
38 | """
39 |
40 | from builtins import range
41 | from builtins import object
42 | import math
43 |
44 | class LambertGrid(object):
45 | """LambertGrid Class"""
46 | def __init__(self, level, minx, maxx, miny, maxy, flip=False):
47 | # default y-axe direction is up
48 | # set self.flip = True to set y-axe direction to point down(this is what mercator webmap do)
49 | self.flip = flip
50 |
51 | # constant variables
52 | self.pow_of_two = [1]
53 | for i in range(1, 20):
54 | self.pow_of_two.append(self.pow_of_two[i - 1] * 2)
55 |
56 | # world original
57 | self.world_originalx = 0
58 | self.world_originaly = 0
59 |
60 | # world extent
61 | self.world_minx = -180.0
62 | self.world_maxx = 180.0
63 |
64 | self.world_miny = -1.0
65 | self.world_maxy = 1.0
66 |
67 | # small grid resolution at @level
68 | self.res_x = (self.world_maxx - self.world_minx) / self.pow_of_two[level + 1]
69 | self.res_y = (self.world_maxy - self.world_miny) / self.pow_of_two[level]
70 |
71 | # big grid extent
72 | self.minx = minx # -180
73 | self.maxx = maxx # 180
74 | self.miny = miny # -1
75 | self.maxy = maxy # 1
76 |
77 | # update big grid index
78 | self.update_boundary()
79 | # get big grid extent
80 | self.grids()
81 |
82 |
83 | def update_boundary(self):
84 | self.min_col = int(math.floor((self.minx - self.world_originalx) / self.res_x))
85 | self.max_col = int(math.floor((self.maxx - self.world_originalx) / self.res_x))
86 |
87 | if self.flip:
88 | self.min_row = int(math.floor((self.world_originaly - self.maxy) / self.res_y))
89 | self.max_row = int(math.floor((self.world_originaly - self.miny) / self.res_y))
90 | else:
91 | self.min_row = int(math.floor((self.miny - self.world_originaly) / self.res_y))
92 | self.max_row = int(math.floor((self.maxy - self.world_originaly) / self.res_y))
93 |
94 | self.total_grids = (self.max_col - self.min_col + 1) * (self.max_row - self.min_row + 1)
95 | return self.total_grids
96 |
97 |
98 | def grids(self):
99 | self.grid_list = {}
100 |
101 | for row in range(self.min_row, self.max_row + 1):
102 | for col in range(self.min_col, self.max_col + 1):
103 | key = '%d_%d' % (row, col)
104 | x0 = self.world_originalx + col * self.res_x
105 | x1 = x0 + self.res_x
106 |
107 | if self.flip:
108 | y1 = self.world_originaly - row * self.res_y
109 | y0 = y1 - self.res_y
110 | else:
111 | y0 = self.world_originaly + row * self.res_y
112 | y1 = y0 + self.res_y
113 |
114 | self.grid_list[key] = [x0, x1, y0, y1]
115 |
116 | return self.grid_list
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/china_offset/transform.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | ##########################################################################################
3 | """
4 | /***************************************************************************
5 | OffsetWGS84Core
6 | A QGIS plugin
7 | Class with methods for geometry and attributes processing
8 | -------------------
9 | begin : 2016-10-11
10 | git sha : $Format:%H$
11 | copyright : (C) 2017 by sshuair
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 | from __future__ import print_function
25 | ##########################################################################################
26 | from builtins import zip
27 | import math
28 | from math import sin, cos, sqrt, fabs, atan2
29 | from math import pi as PI
30 | # from numba import jit
31 |
32 |
33 | # =================================================sshuair=============================================================
34 | # define ellipsoid
35 | a = 6378245.0
36 | f = 1 / 298.3
37 | b = a * (1 - f)
38 | ee = 1 - (b * b) / (a * a)
39 |
40 | # check if the point in china
41 | def outOfChina(lng, lat):
42 | return not (72.004 <= lng <= 137.8347 and 0.8293 <= lat <= 55.8271)
43 |
44 | # @jit
45 | def geohey_transformLat(x, y):
46 | ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x))
47 | ret = ret + (20.0 * sin(6.0 * x * PI) + 20.0 * sin(2.0 * x * PI)) * 2.0 / 3.0
48 | ret = ret + (20.0 * sin(y * PI) + 40.0 * sin(y / 3.0 * PI)) * 2.0 / 3.0
49 | ret = ret + (160.0 * sin(y / 12.0 * PI) + 320.0 * sin(y * PI / 30.0)) * 2.0 / 3.0
50 | return ret
51 |
52 | # @jit
53 | def geohey_transformLon(x, y):
54 | ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x))
55 | ret = ret + (20.0 * sin(6.0 * x * PI) + 20.0 * sin(2.0 * x * PI)) * 2.0 / 3.0
56 | ret = ret + (20.0 * sin(x * PI) + 40.0 * sin(x / 3.0 * PI)) * 2.0 / 3.0
57 | ret = ret + (150.0 * sin(x / 12.0 * PI) + 300.0 * sin(x * PI / 30.0)) * 2.0 / 3.0
58 | return ret
59 |
60 | # @jit
61 | def wgs2gcj(wgsLon, wgsLat):
62 | if outOfChina(wgsLon, wgsLat):
63 | return wgsLon, wgsLat
64 | dLat = geohey_transformLat(wgsLon - 105.0, wgsLat - 35.0)
65 | dLon = geohey_transformLon(wgsLon - 105.0, wgsLat - 35.0)
66 | radLat = wgsLat / 180.0 * PI
67 | magic = math.sin(radLat)
68 | magic = 1 - ee * magic * magic
69 | sqrtMagic = sqrt(magic)
70 | dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI)
71 | dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * PI)
72 | gcjLat = wgsLat + dLat
73 | gcjLon = wgsLon + dLon
74 | return (gcjLon, gcjLat)
75 |
76 |
77 | def gcj2wgs(gcjLon, gcjLat):
78 | g0 = (gcjLon, gcjLat)
79 | w0 = g0
80 | g1 = wgs2gcj(w0[0], w0[1])
81 | # w1 = w0 - (g1 - g0)
82 | w1 = tuple([x[0]-(x[1]-x[2]) for x in zip(w0,g1,g0)])
83 | # delta = w1 - w0
84 | delta = tuple([x[0] - x[1] for x in zip(w1, w0)])
85 | while (abs(delta[0]) >= 1e-6 or abs(delta[1]) >= 1e-6):
86 | w0 = w1
87 | g1 = wgs2gcj(w0[0], w0[1])
88 | # w1 = w0 - (g1 - g0)
89 | w1 = tuple([x[0]-(x[1]-x[2]) for x in zip(w0,g1,g0)])
90 | # delta = w1 - w0
91 | delta = tuple([x[0] - x[1] for x in zip(w1, w0)])
92 | return w1
93 |
94 |
95 | def gcj2bd(gcjLon, gcjLat):
96 | z = sqrt(gcjLon * gcjLon + gcjLat * gcjLat) + 0.00002 * sin(gcjLat * PI * 3000.0 / 180.0)
97 | theta = atan2(gcjLat, gcjLon) + 0.000003 * cos(gcjLon * PI * 3000.0 / 180.0)
98 | bdLon = z * cos(theta) + 0.0065
99 | bdLat = z * sin(theta) + 0.006
100 | return (bdLon, bdLat)
101 |
102 |
103 | def bd2gcj(bdLon, bdLat):
104 | x = bdLon - 0.0065
105 | y = bdLat - 0.006
106 | z = sqrt(x * x + y * y) - 0.00002 * sin(y * PI * 3000.0 / 180.0)
107 | theta = atan2(y, x) - 0.000003 * cos(x * PI * 3000.0 / 180.0)
108 | gcjLon = z * cos(theta)
109 | gcjLat = z * sin(theta)
110 | return (gcjLon, gcjLat)
111 |
112 |
113 | def wgs2bd(wgsLon, wgsLat):
114 | gcj = wgs2gcj(wgsLon, wgsLat)
115 | return gcj2bd(gcj[0], gcj[1])
116 |
117 |
118 | def bd2wgs(bdLon, bdLat):
119 | gcj = bd2gcj(bdLon, bdLat)
120 | return gcj2wgs(gcj[0], gcj[1])
121 |
122 |
123 | if __name__ == '__main__':
124 | # wgs2gcj
125 | # coord = (112, 40)
126 | # trans = WGS2GCJ()
127 | print(wgs2gcj(112, 40))
128 | print(gcj2wgs(112.00678230985764, 40.00112245823686))
129 |
130 | # gcj2wgs
--------------------------------------------------------------------------------
/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 PyQt5.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 |
--------------------------------------------------------------------------------
/help/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # GeoHeyToolbox 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.pngmath', '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'GeoHeyToolbox'
44 | copyright = u'2013, GeoHey'
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.3'
52 | # The full version, including alpha/beta/rc tags.
53 | release = '0.3'
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', 'GeoHeyToolbox.tex', u'GeoHeyToolbox Documentation',
182 | u'GeoHey', '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'GeoHeyToolbox Documentation',
215 | [u'GeoHey'], 1)
216 | ]
217 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #/***************************************************************************
2 | # GeoHeyToolbox
3 | #
4 | # GeoHey Toolbox
5 | # -------------------
6 | # begin : 2019-11-09
7 | # git sha : $Format:%H$
8 | # copyright : (C) 2018 by GeoHey
9 | # email : sshuair@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 | # Edit the following to match your sources lists
23 | #################################################
24 |
25 |
26 | #Add iso code for any locales you want to support here (space separated)
27 | # default is no locales
28 | # LOCALES = af
29 | LOCALES =
30 |
31 | # If locales are enabled, set the name of the lrelease binary on your system. If
32 | # you have trouble compiling the translations, you may have to specify the full path to
33 | # lrelease
34 | #LRELEASE = lrelease
35 | #LRELEASE = lrelease-qt4
36 |
37 |
38 | # translation
39 | SOURCES = \
40 | __init__.py \
41 | geoHey_toolbox.py
42 |
43 | PLUGINNAME = geoHey_toolbox
44 |
45 | PY_FILES = \
46 | __init__.py \
47 | geoHey_toolbox.py
48 |
49 | UI_FILES =
50 |
51 | EXTRAS = metadata.txt
52 |
53 | EXTRA_DIRS =
54 |
55 | COMPILED_RESOURCE_FILES =
56 |
57 | PEP8EXCLUDE=pydev,resources.py,conf.py,third_party,ui
58 |
59 |
60 | #################################################
61 | # Normally you would not need to edit below here
62 | #################################################
63 |
64 | HELP = help/build/html
65 |
66 | PLUGIN_UPLOAD = $(c)/plugin_upload.py
67 |
68 | RESOURCE_SRC=$(shell grep '^ *@@g;s/.*>//g' | tr '\n' ' ')
69 |
70 | QGISDIR=.qgis2
71 |
72 | default: compile
73 |
74 | compile: $(COMPILED_RESOURCE_FILES)
75 |
76 | %.py : %.qrc $(RESOURCES_SRC)
77 | pyrcc5 -o $*.py $<
78 |
79 | %.qm : %.ts
80 | $(LRELEASE) $<
81 |
82 | test: compile transcompile
83 | @echo
84 | @echo "----------------------"
85 | @echo "Regression Test Suite"
86 | @echo "----------------------"
87 |
88 | @# Preceding dash means that make will continue in case of errors
89 | @-export PYTHONPATH=`pwd`:$(PYTHONPATH); \
90 | export QGIS_DEBUG=0; \
91 | export QGIS_LOG_FILE=/dev/null; \
92 | nosetests -v --with-id --with-coverage --cover-package=. \
93 | 3>&1 1>&2 2>&3 3>&- || true
94 | @echo "----------------------"
95 | @echo "If you get a 'no module named qgis.core error, try sourcing"
96 | @echo "the helper script we have provided first then run make test."
97 | @echo "e.g. source run-env-linux.sh ; make test"
98 | @echo "----------------------"
99 |
100 | deploy: compile doc transcompile
101 | @echo
102 | @echo "------------------------------------------"
103 | @echo "Deploying plugin to your .qgis2 directory."
104 | @echo "------------------------------------------"
105 | # The deploy target only works on unix like operating system where
106 | # the Python plugin directory is located at:
107 | # $HOME/$(QGISDIR)/python/plugins
108 | mkdir -p $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
109 | cp -vf $(PY_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
110 | cp -vf $(UI_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
111 | cp -vf $(COMPILED_RESOURCE_FILES) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
112 | cp -vf $(EXTRAS) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
113 | cp -vfr i18n $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
114 | cp -vfr $(HELP) $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)/help
115 | # Copy extra directories if any
116 | (foreach EXTRA_DIR,(EXTRA_DIRS), cp -R (EXTRA_DIR) (HOME)/(QGISDIR)/python/plugins/(PLUGINNAME)/;)
117 |
118 |
119 | # The dclean target removes compiled python files from plugin directory
120 | # also deletes any .git entry
121 | dclean:
122 | @echo
123 | @echo "-----------------------------------"
124 | @echo "Removing any compiled python files."
125 | @echo "-----------------------------------"
126 | find $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) -iname "*.pyc" -delete
127 | find $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME) -iname ".git" -prune -exec rm -Rf {} \;
128 |
129 |
130 | derase:
131 | @echo
132 | @echo "-------------------------"
133 | @echo "Removing deployed plugin."
134 | @echo "-------------------------"
135 | rm -Rf $(HOME)/$(QGISDIR)/python/plugins/$(PLUGINNAME)
136 |
137 | zip: deploy dclean
138 | @echo
139 | @echo "---------------------------"
140 | @echo "Creating plugin zip bundle."
141 | @echo "---------------------------"
142 | # The zip target deploys the plugin and creates a zip file with the deployed
143 | # content. You can then upload the zip file on http://plugins.qgis.org
144 | rm -f $(PLUGINNAME).zip
145 | cd $(HOME)/$(QGISDIR)/python/plugins; zip -9r $(CURDIR)/$(PLUGINNAME).zip $(PLUGINNAME)
146 |
147 | package: compile
148 | # Create a zip package of the plugin named $(PLUGINNAME).zip.
149 | # This requires use of git (your plugin development directory must be a
150 | # git repository).
151 | # To use, pass a valid commit or tag as follows:
152 | # make package VERSION=Version_0.3.2
153 | @echo
154 | @echo "------------------------------------"
155 | @echo "Exporting plugin to zip package. "
156 | @echo "------------------------------------"
157 | rm -f $(PLUGINNAME).zip
158 | git archive --prefix=$(PLUGINNAME)/ -o $(PLUGINNAME).zip $(VERSION)
159 | echo "Created package: $(PLUGINNAME).zip"
160 |
161 | upload: zip
162 | @echo
163 | @echo "-------------------------------------"
164 | @echo "Uploading plugin to QGIS Plugin repo."
165 | @echo "-------------------------------------"
166 | $(PLUGIN_UPLOAD) $(PLUGINNAME).zip
167 |
168 | transup:
169 | @echo
170 | @echo "------------------------------------------------"
171 | @echo "Updating translation files with any new strings."
172 | @echo "------------------------------------------------"
173 | @chmod +x scripts/update-strings.sh
174 | @scripts/update-strings.sh $(LOCALES)
175 |
176 | transcompile:
177 | @echo
178 | @echo "----------------------------------------"
179 | @echo "Compiled translation files to .qm files."
180 | @echo "----------------------------------------"
181 | @chmod +x scripts/compile-strings.sh
182 | @scripts/compile-strings.sh $(LRELEASE) $(LOCALES)
183 |
184 | transclean:
185 | @echo
186 | @echo "------------------------------------"
187 | @echo "Removing compiled translation files."
188 | @echo "------------------------------------"
189 | rm -f i18n/*.qm
190 |
191 | clean:
192 | @echo
193 | @echo "------------------------------------"
194 | @echo "Removing uic and rcc generated files"
195 | @echo "------------------------------------"
196 | rm $(COMPILED_UI_FILES) $(COMPILED_RESOURCE_FILES)
197 |
198 | doc:
199 | @echo
200 | @echo "------------------------------------"
201 | @echo "Building documentation using sphinx."
202 | @echo "------------------------------------"
203 | cd help; make html
204 |
205 | pylint:
206 | @echo
207 | @echo "-----------------"
208 | @echo "Pylint violations"
209 | @echo "-----------------"
210 | @pylint --reports=n --rcfile=pylintrc . || true
211 | @echo
212 | @echo "----------------------"
213 | @echo "If you get a 'no module named qgis.core' error, try sourcing"
214 | @echo "the helper script we have provided first then run make pylint."
215 | @echo "e.g. source run-env-linux.sh ; make pylint"
216 | @echo "----------------------"
217 |
218 |
219 | # Run pep8 style checking
220 | #http://pypi.python.org/pypi/pep8
221 | pep8:
222 | @echo
223 | @echo "-----------"
224 | @echo "PEP8 issues"
225 | @echo "-----------"
226 | @pep8 --repeat --ignore=E203,E121,E122,E123,E124,E125,E126,E127,E128 --exclude $(PEP8EXCLUDE) . || true
227 | @echo "-----------"
228 | @echo "Ignored in PEP8 check:"
229 | @echo $(PEP8EXCLUDE)
230 |
--------------------------------------------------------------------------------
/grid/lambert_grid_algorithm.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | LambertGrid
6 | A QGIS plugin
7 | Equal area lambert grid
8 | -------------------
9 | begin : 2016-11-15
10 | copyright : (C) 2016 by GeoHey
11 | email : xux@geohey.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 __future__ import absolute_import
24 |
25 | from builtins import str
26 | __author__ = 'GeoHey'
27 | __date__ = '2016-11-15'
28 | __copyright__ = '(C) 2016 by GeoHey'
29 |
30 | # This will get replaced with a git SHA1 when you do a git archive
31 |
32 | __revision__ = '$Format:%H$'
33 |
34 | import os
35 | from qgis.PyQt.QtCore import QSettings, QVariant
36 | from qgis.core import QgsVectorFileWriter, QgsMessageLog, QgsFeature, QGis, QgsGeometry, QgsPoint, QgsFields, QgsCoordinateReferenceSystem
37 | from qgis.PyQt.QtGui import QIcon
38 |
39 | # from processing.tools.system import *
40 | from processing.core.GeoAlgorithm import GeoAlgorithm
41 | from processing.core.parameters import ParameterNumber, ParameterCrs, ParameterExtent, ParameterSelection
42 | from processing.core.outputs import OutputVector
43 | from processing.tools import dataobjects, vector
44 | from .lambert_grid_core import LambertGrid
45 | from . import proj_util
46 |
47 |
48 | class LambertGridAlgorithm(GeoAlgorithm):
49 | """This is an example algorithm that takes a vector layer and
50 | creates a new one just with just those features of the input
51 | layer that are selected.
52 |
53 | It is meant to be used as an example of how to create your own
54 | algorithms and explain methods and variables used to do it. An
55 | algorithm like this will be available in all elements, and there
56 | is not need for additional work.
57 |
58 | All Processing algorithms should extend the GeoAlgorithm class.
59 | """
60 |
61 | # Constants used to refer to parameters and outputs. They will be
62 | # used when calling the algorithm from another algorithm, or when
63 | # calling from the QGIS console.
64 |
65 | OUTPUT_LAYER = 'OUTPUT_LAYER'
66 | INPUT_LAYER = 'INPUT_LAYER'
67 |
68 | YAXE = 'up'
69 | YAXE_OPTIONS = ['up', 'down']
70 |
71 | CRS = 'EPSG:4326'
72 |
73 | EXTENT = ''
74 |
75 | LEVEL = 10
76 |
77 | def getIcon(self):
78 | return QIcon(os.path.dirname(__file__) + '/geohey.png')
79 |
80 | def defineCharacteristics(self):
81 | """Here we define the inputs and output of the algorithm, along
82 | with some other properties.
83 | """
84 |
85 | # The name that the user will see in the toolbox
86 | self.name = 'Create equal area lambert grids'
87 |
88 | # The branch of the toolbox under which the algorithm will appear
89 | self.group = 'Grid tools'
90 |
91 | # We add the input vector layer. It can have any kind of geometry
92 | # It is a mandatory (not optional) one, hence the False argument
93 | self.addParameter(ParameterExtent(self.EXTENT, self.tr('Grid Extent')))
94 |
95 | self.addParameter(ParameterSelection(self.YAXE, self.tr('Y-direction'), self.YAXE_OPTIONS))
96 |
97 | self.addParameter(ParameterNumber(self.LEVEL, self.tr('Grid Level'), 0, 19, 9))
98 |
99 | self.addParameter(ParameterCrs(self.CRS, self.tr('Coordinate System'), self.tr('EPSG:4326')))
100 |
101 | # We add a vector layer as output
102 | self.addOutput(OutputVector(self.OUTPUT_LAYER, self.tr('Output Grid')))
103 |
104 | def processAlgorithm(self, progress):
105 | """Here is where the processing itself takes place."""
106 |
107 | # The first thing to do is retrieve the values of the parameters
108 | # entered by the user
109 | extent = str(self.getParameterValue(self.EXTENT))
110 | flip = self.getParameterValue(self.YAXE)
111 | level = self.getParameterValue(self.LEVEL)
112 | crs = str(self.getParameterValue(self.CRS))
113 |
114 | QgsMessageLog.logMessage(extent, 'LambertGrid', QgsMessageLog.INFO)
115 | QgsMessageLog.logMessage(str(flip), 'LambertGrid', QgsMessageLog.INFO)
116 | QgsMessageLog.logMessage(str(level), 'LambertGrid', QgsMessageLog.INFO)
117 |
118 | output = self.getOutputValue(self.OUTPUT_LAYER)
119 | extent_arr = [float(extent.split(',')[0]), float(extent.split(',')[1]), float(extent.split(',')[2]), float(extent.split(',')[3])]
120 | QgsMessageLog.logMessage('specified extent' + str(extent_arr), 'LambertGrid', QgsMessageLog.INFO)
121 |
122 | if (crs == 'EPSG:4326'):
123 | QgsMessageLog.logMessage(crs, 'LambertGrid', QgsMessageLog.INFO)
124 | [xmin, ymin] = proj_util.lonlat2lambert([extent_arr[0], extent_arr[2]])
125 | [xmax, ymax] = proj_util.lonlat2lambert([extent_arr[1], extent_arr[3]])
126 | else:
127 | # opts.srs == 'epsg:3857'
128 | QgsMessageLog.logMessage(crs, 'LambertGrid', QgsMessageLog.INFO)
129 | [xmin, ymin] = proj_util.webmercator2lonlat([extent_arr[0], extent_arr[2]])
130 | [xmax, ymax] = proj_util.webmercator2lonlat([extent_arr[1], extent_arr[3]])
131 | [xmin, ymin] = proj_util.lonlat2lambert([xmin, ymin])
132 | [xmax, ymax] = proj_util.lonlat2lambert([xmax, ymax])
133 |
134 | QgsMessageLog.logMessage('specified lambert extent' + str([xmin, ymin, xmax, ymax]), 'LambertGrid', QgsMessageLog.INFO)
135 |
136 | grids = LambertGrid(level, xmin, xmax, ymin, ymax, flip)
137 |
138 | total_cnt = grids.total_grids
139 | cnt = 0
140 | step = int(total_cnt / 100)
141 | if step == 0:
142 | step = 1
143 |
144 | msg = 'total grids %d' % total_cnt
145 | QgsMessageLog.logMessage(msg, 'LambertGrid', QgsMessageLog.INFO)
146 |
147 | # First we create the output layer. The output value entered by
148 | # the user is a string containing a filename, so we can use it
149 | # directly
150 | settings = QSettings()
151 | systemEncoding = settings.value('/UI/encoding', 'System')
152 | # provider = vectorLayer.dataProvider()
153 |
154 | fields = QgsFields()
155 | fields.append(QgsField("id", QVariant.String))
156 | writer = QgsVectorFileWriter(output, systemEncoding, fields, QGis.WKBPolygon, QgsCoordinateReferenceSystem(crs))
157 |
158 | for k in grids.grid_list:
159 | ext = grids.grid_list[k]
160 |
161 | # QgsMessageLog.logMessage('processing small grid lambert extent ' + str(ext), 'LambertGrid', QgsMessageLog.INFO)
162 | # transform coordinates
163 | if (crs == 'EPSG:4326'):
164 | [xmin, ymin] = proj_util.lambert2lonlat([ext[0], ext[2]])
165 | [xmax, ymax] = proj_util.lambert2lonlat([ext[1], ext[3]])
166 | else:
167 | # opts.srs == 'epsg:3857'
168 | [xmin, ymin] = proj_util.lambert2lonlat([ext[0], ext[2]])
169 | [xmax, ymax] = proj_util.lambert2lonlat([ext[1], ext[3]])
170 | [xmin, ymin] = proj_util.lonlat2webmercator([xmin, ymin])
171 | [xmax, ymax] = proj_util.lonlat2webmercator([xmax, ymax])
172 |
173 | # QgsMessageLog.logMessage('processing small grid extent ' + str([xmin, ymin, xmax, ymax]), 'LambertGrid', QgsMessageLog.INFO)
174 |
175 | feat = QgsFeature()
176 |
177 | verts = []
178 | ring_verts = []
179 | ring_verts.append(QgsPoint(xmin, ymin))
180 | ring_verts.append(QgsPoint(xmax, ymin))
181 | ring_verts.append(QgsPoint(xmax, ymax))
182 | ring_verts.append(QgsPoint(xmin, ymax))
183 | ring_verts.append(QgsPoint(xmin, ymin))
184 | verts.append(ring_verts)
185 |
186 | geom = QgsGeometry.fromPolygon(verts)
187 | # QgsMessageLog.logMessage('small grid geometry ' + str(geom.asPolygon()), 'LambertGrid', QgsMessageLog.INFO)
188 |
189 | feat.setGeometry(geom)
190 | feat.setAttributes([str(level) + '_' + k])
191 |
192 | writer.addFeature(feat)
193 |
194 | cnt = cnt + 1
195 | if (cnt % step == 0):
196 | progress.setPercentage((float(cnt) / float(total_cnt) * 100))
--------------------------------------------------------------------------------
/pylintrc:
--------------------------------------------------------------------------------
1 | [MASTER]
2 |
3 | # Specify a configuration file.
4 | #rcfile=
5 |
6 | # Python code to execute, usually for sys.path manipulation such as
7 | # pygtk.require().
8 | #init-hook=
9 |
10 | # Profiled execution.
11 | profile=no
12 |
13 | # Add files or directories to the blacklist. They should be base names, not
14 | # paths.
15 | ignore=CVS
16 |
17 | # Pickle collected data for later comparisons.
18 | persistent=yes
19 |
20 | # List of plugins (as comma separated values of python modules names) to load,
21 | # usually to register additional checkers.
22 | load-plugins=
23 |
24 |
25 | [MESSAGES CONTROL]
26 |
27 | # Enable the message, report, category or checker with the given id(s). You can
28 | # either give multiple identifier separated by comma (,) or put this option
29 | # multiple time. See also the "--disable" option for examples.
30 | #enable=
31 |
32 | # Disable the message, report, category or checker with the given id(s). You
33 | # can either give multiple identifiers separated by comma (,) or put this
34 | # option multiple times (only on the command line, not in the configuration
35 | # file where it should appear only once).You can also use "--disable=all" to
36 | # disable everything first and then reenable specific checks. For example, if
37 | # you want to run only the similarities checker, you can use "--disable=all
38 | # --enable=similarities". If you want to run only the classes checker, but have
39 | # no Warning level messages displayed, use"--disable=all --enable=classes
40 | # --disable=W"
41 | # see http://stackoverflow.com/questions/21487025/pylint-locally-defined-disables-still-give-warnings-how-to-suppress-them
42 | disable=locally-disabled,C0103
43 |
44 |
45 | [REPORTS]
46 |
47 | # Set the output format. Available formats are text, parseable, colorized, msvs
48 | # (visual studio) and html. You can also give a reporter class, eg
49 | # mypackage.mymodule.MyReporterClass.
50 | output-format=text
51 |
52 | # Put messages in a separate file for each module / package specified on the
53 | # command line instead of printing them on stdout. Reports (if any) will be
54 | # written in a file name "pylint_global.[txt|html]".
55 | files-output=no
56 |
57 | # Tells whether to display a full report or only the messages
58 | reports=yes
59 |
60 | # Python expression which should return a note less than 10 (10 is the highest
61 | # note). You have access to the variables errors warning, statement which
62 | # respectively contain the number of errors / warnings messages and the total
63 | # number of statements analyzed. This is used by the global evaluation report
64 | # (RP0004).
65 | evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
66 |
67 | # Add a comment according to your evaluation note. This is used by the global
68 | # evaluation report (RP0004).
69 | comment=no
70 |
71 | # Template used to display messages. This is a python new-style format string
72 | # used to format the message information. See doc for all details
73 | #msg-template=
74 |
75 |
76 | [BASIC]
77 |
78 | # Required attributes for module, separated by a comma
79 | required-attributes=
80 |
81 | # List of builtins function names that should not be used, separated by a comma
82 | bad-functions=map,filter,apply,input
83 |
84 | # Regular expression which should only match correct module names
85 | module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
86 |
87 | # Regular expression which should only match correct module level names
88 | const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
89 |
90 | # Regular expression which should only match correct class names
91 | class-rgx=[A-Z_][a-zA-Z0-9]+$
92 |
93 | # Regular expression which should only match correct function names
94 | function-rgx=[a-z_][a-z0-9_]{2,30}$
95 |
96 | # Regular expression which should only match correct method names
97 | method-rgx=[a-z_][a-z0-9_]{2,30}$
98 |
99 | # Regular expression which should only match correct instance attribute names
100 | attr-rgx=[a-z_][a-z0-9_]{2,30}$
101 |
102 | # Regular expression which should only match correct argument names
103 | argument-rgx=[a-z_][a-z0-9_]{2,30}$
104 |
105 | # Regular expression which should only match correct variable names
106 | variable-rgx=[a-z_][a-z0-9_]{2,30}$
107 |
108 | # Regular expression which should only match correct attribute names in class
109 | # bodies
110 | class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
111 |
112 | # Regular expression which should only match correct list comprehension /
113 | # generator expression variable names
114 | inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
115 |
116 | # Good variable names which should always be accepted, separated by a comma
117 | good-names=i,j,k,ex,Run,_
118 |
119 | # Bad variable names which should always be refused, separated by a comma
120 | bad-names=foo,bar,baz,toto,tutu,tata
121 |
122 | # Regular expression which should only match function or class names that do
123 | # not require a docstring.
124 | no-docstring-rgx=__.*__
125 |
126 | # Minimum line length for functions/classes that require docstrings, shorter
127 | # ones are exempt.
128 | docstring-min-length=-1
129 |
130 |
131 | [MISCELLANEOUS]
132 |
133 | # List of note tags to take in consideration, separated by a comma.
134 | notes=FIXME,XXX,TODO
135 |
136 |
137 | [TYPECHECK]
138 |
139 | # Tells whether missing members accessed in mixin class should be ignored. A
140 | # mixin class is detected if its name ends with "mixin" (case insensitive).
141 | ignore-mixin-members=yes
142 |
143 | # List of classes names for which member attributes should not be checked
144 | # (useful for classes with attributes dynamically set).
145 | ignored-classes=SQLObject
146 |
147 | # When zope mode is activated, add a predefined set of Zope acquired attributes
148 | # to generated-members.
149 | zope=no
150 |
151 | # List of members which are set dynamically and missed by pylint inference
152 | # system, and so shouldn't trigger E0201 when accessed. Python regular
153 | # expressions are accepted.
154 | generated-members=REQUEST,acl_users,aq_parent
155 |
156 |
157 | [VARIABLES]
158 |
159 | # Tells whether we should check for unused import in __init__ files.
160 | init-import=no
161 |
162 | # A regular expression matching the beginning of the name of dummy variables
163 | # (i.e. not used).
164 | dummy-variables-rgx=_$|dummy
165 |
166 | # List of additional names supposed to be defined in builtins. Remember that
167 | # you should avoid to define new builtins when possible.
168 | additional-builtins=
169 |
170 |
171 | [FORMAT]
172 |
173 | # Maximum number of characters on a single line.
174 | max-line-length=80
175 |
176 | # Regexp for a line that is allowed to be longer than the limit.
177 | ignore-long-lines=^\s*(# )??$
178 |
179 | # Allow the body of an if to be on the same line as the test if there is no
180 | # else.
181 | single-line-if-stmt=no
182 |
183 | # List of optional constructs for which whitespace checking is disabled
184 | no-space-check=trailing-comma,dict-separator
185 |
186 | # Maximum number of lines in a module
187 | max-module-lines=1000
188 |
189 | # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
190 | # tab).
191 | indent-string=' '
192 |
193 |
194 | [SIMILARITIES]
195 |
196 | # Minimum lines number of a similarity.
197 | min-similarity-lines=4
198 |
199 | # Ignore comments when computing similarities.
200 | ignore-comments=yes
201 |
202 | # Ignore docstrings when computing similarities.
203 | ignore-docstrings=yes
204 |
205 | # Ignore imports when computing similarities.
206 | ignore-imports=no
207 |
208 |
209 | [IMPORTS]
210 |
211 | # Deprecated modules which should not be used, separated by a comma
212 | deprecated-modules=regsub,TERMIOS,Bastion,rexec
213 |
214 | # Create a graph of every (i.e. internal and external) dependencies in the
215 | # given file (report RP0402 must not be disabled)
216 | import-graph=
217 |
218 | # Create a graph of external dependencies in the given file (report RP0402 must
219 | # not be disabled)
220 | ext-import-graph=
221 |
222 | # Create a graph of internal dependencies in the given file (report RP0402 must
223 | # not be disabled)
224 | int-import-graph=
225 |
226 |
227 | [DESIGN]
228 |
229 | # Maximum number of arguments for function / method
230 | max-args=5
231 |
232 | # Argument names that match this expression will be ignored. Default to name
233 | # with leading underscore
234 | ignored-argument-names=_.*
235 |
236 | # Maximum number of locals for function / method body
237 | max-locals=15
238 |
239 | # Maximum number of return / yield for function / method body
240 | max-returns=6
241 |
242 | # Maximum number of branch for function / method body
243 | max-branches=12
244 |
245 | # Maximum number of statements in function / method body
246 | max-statements=50
247 |
248 | # Maximum number of parents for a class (see R0901).
249 | max-parents=7
250 |
251 | # Maximum number of attributes for a class (see R0902).
252 | max-attributes=7
253 |
254 | # Minimum number of public methods for a class (see R0903).
255 | min-public-methods=2
256 |
257 | # Maximum number of public methods for a class (see R0904).
258 | max-public-methods=20
259 |
260 |
261 | [CLASSES]
262 |
263 | # List of interface methods to ignore, separated by a comma. This is used for
264 | # instance to not check methods defines in Zope's Interface base class.
265 | ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
266 |
267 | # List of method names used to declare (i.e. assign) instance attributes.
268 | defining-attr-methods=__init__,__new__,setUp
269 |
270 | # List of valid names for the first argument in a class method.
271 | valid-classmethod-first-arg=cls
272 |
273 | # List of valid names for the first argument in a metaclass class method.
274 | valid-metaclass-classmethod-first-arg=mcs
275 |
276 |
277 | [EXCEPTIONS]
278 |
279 | # Exceptions that will emit a warning when being caught. Defaults to
280 | # "Exception"
281 | overgeneral-exceptions=Exception
282 |
--------------------------------------------------------------------------------
/china_offset/bd2wgs.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | from PyQt5.QtCore import QCoreApplication
34 | from qgis.core import (QgsProcessing,QgsFeature, QgsGeometry, QgsPointXY, QgsMultiPoint,
35 | QgsFeatureSink,
36 | QgsProcessingAlgorithm,
37 | QgsProcessingParameterFeatureSource,
38 | QgsProcessingParameterFeatureSink)
39 | from .transform import bd2wgs
40 |
41 | class BD2WGS(QgsProcessingAlgorithm):
42 | """
43 | This is an example algorithm that takes a vector layer and
44 | creates a new identical one.
45 |
46 | It is meant to be used as an example of how to create your own
47 | algorithms and explain methods and variables used to do it. An
48 | algorithm like this will be available in all elements, and there
49 | is not need for additional work.
50 |
51 | All Processing algorithms should extend the QgsProcessingAlgorithm
52 | class.
53 | """
54 |
55 | # Constants used to refer to parameters and outputs. They will be
56 | # used when calling the algorithm from another algorithm, or when
57 | # calling from the QGIS console.
58 |
59 | OUTPUT = 'OUTPUT'
60 | INPUT = 'INPUT'
61 |
62 | def initAlgorithm(self, config):
63 | """
64 | Here we define the inputs and output of the algorithm, along
65 | with some other properties.
66 | """
67 |
68 | # We add the input vector features source. It can have any kind of
69 | # geometry.
70 | self.addParameter(
71 | QgsProcessingParameterFeatureSource(
72 | self.INPUT,
73 | self.tr('Input layer'),
74 | [QgsProcessing.TypeVectorAnyGeometry]
75 | )
76 | )
77 |
78 | # We add a feature sink in which to store our processed features (this
79 | # usually takes the form of a newly created vector layer when the
80 | # algorithm is run in QGIS).
81 | self.addParameter(
82 | QgsProcessingParameterFeatureSink(
83 | self.OUTPUT,
84 | self.tr('Output layer')
85 | )
86 | )
87 |
88 | def processAlgorithm(self, parameters, context, feedback):
89 | """
90 | Here is where the processing itself takes place.
91 | """
92 |
93 | # Retrieve the feature source and sink. The 'dest_id' variable is used
94 | # to uniquely identify the feature sink, and must be included in the
95 | # dictionary returned by the processAlgorithm function.
96 | source = self.parameterAsSource(parameters, self.INPUT, context)
97 | (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
98 | context, source.fields(), source.wkbType(), source.sourceCrs())
99 |
100 | # Compute the number of steps to display within the progress bar and
101 | # get features from source
102 | total = 100.0 / source.featureCount() if source.featureCount() else 0
103 | features = source.getFeatures()
104 | print(features)
105 |
106 | for current, feature in enumerate(features):
107 | # Stop the algorithm if cancel button has been clicked
108 | if feedback.isCanceled():
109 | break
110 | # sshuair begin
111 | geom = feature.geometry()
112 | attrs = feature.attributes()
113 | geom_type = geom.wkbType()
114 |
115 | feature_new = QgsFeature()
116 |
117 | # Point
118 | if geom_type == 1:
119 | vertices = geom.asPoint()
120 | vert_new = bd2wgs(vertices[0], vertices[1])
121 | feature_new.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(vert_new[0], vert_new[1])))
122 |
123 | # LineString
124 | elif geom_type == 2:
125 | vert_new = []
126 | vertices = geom.asPolyline()
127 | for pt in vertices:
128 | pt_new = bd2wgs(pt[0], pt[1])
129 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
130 | feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))
131 |
132 | # Polygon
133 | elif geom_type == 3:
134 | vertices = geom.asPolygon()
135 | vert_new = []
136 | for ring in vertices:
137 | ring_vert = []
138 | for pt in ring:
139 | pt_new = bd2wgs(pt[0], pt[1])
140 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
141 | vert_new.append(ring_vert)
142 | feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))
143 |
144 | # MultiPoint
145 | elif geom_type == 4:
146 | vert_new = []
147 | vertices = geom.asMultiPoint()
148 | for pt in vertices:
149 | pt_new = bd2wgs(pt[0], pt[1])
150 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
151 | feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))
152 |
153 | # MultiLineString
154 | elif geom_type == 5:
155 | vertices = geom.asMultiPolyline()
156 | vert_new = []
157 | for part in vertices:
158 | linestring = []
159 | for pt in part:
160 | pt_new = bd2wgs(pt[0], pt[1])
161 | linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
162 | vert_new.append(linestring)
163 | feature_new.setGeometry(QgsGeometry.fromMultiPolylineXY(vert_new))
164 |
165 | # MultiPolygon
166 | elif geom_type == 6:
167 | vertices = geom.asMultiPolygon()
168 | vert_new = []
169 | for part in vertices:
170 | poly = []
171 | for ring in part:
172 | ring_vert = []
173 | for pt in ring:
174 | pt_new = bd2wgs(pt[0], pt[1])
175 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
176 | poly.append(ring_vert)
177 | vert_new.append(poly)
178 | feature_new.setGeometry(QgsGeometry.fromMultiPolygonXY(vert_new))
179 | else:
180 | continue
181 |
182 | feature_new.setAttributes(attrs)
183 | # sshuair end
184 |
185 |
186 |
187 | # feature = feature+0.1
188 | # Add a feature in the sink
189 | sink.addFeature(feature_new, QgsFeatureSink.FastInsert)
190 |
191 | # Update the progress bar
192 | feedback.setProgress(int(current * total))
193 | print(feature)
194 |
195 | # Return the results of the algorithm. In this case our only result is
196 | # the feature sink which contains the processed features, but some
197 | # algorithms may return multiple feature sinks, calculated numeric
198 | # statistics, etc. These should all be included in the returned
199 | # dictionary, with keys matching the feature corresponding parameter
200 | # or output names.
201 | return {self.OUTPUT: dest_id}
202 |
203 | def name(self):
204 | """
205 | Returns the algorithm name, used for identifying the algorithm. This
206 | string should be fixed for the algorithm, and must not be localised.
207 | The name should be unique within each provider. Names should contain
208 | lowercase alphanumeric characters only and no spaces or other
209 | formatting characters.
210 | """
211 | return 'BD09 to WGS'
212 |
213 | def displayName(self):
214 | """
215 | Returns the translated algorithm name, which should be used for any
216 | user-visible display of the algorithm name.
217 | """
218 | return self.tr(self.name())
219 |
220 | def group(self):
221 | """
222 | Returns the name of the group this algorithm belongs to. This string
223 | should be localised.
224 | """
225 | return self.tr(self.groupId())
226 |
227 | def groupId(self):
228 | """
229 | Returns the unique ID of the group this algorithm belongs to. This
230 | string should be fixed for the algorithm, and must not be localised.
231 | The group id should be unique within each provider. Group id should
232 | contain lowercase alphanumeric characters only and no spaces or other
233 | formatting characters.
234 | """
235 | return 'China Coord Convert'
236 |
237 | def tr(self, string):
238 | return QCoreApplication.translate('Processing', string)
239 |
240 | def createInstance(self):
241 | return BD2WGS()
242 |
--------------------------------------------------------------------------------
/china_offset/bd2gcj.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | from PyQt5.QtCore import QCoreApplication
34 | from qgis.core import (QgsProcessing,QgsFeature, QgsGeometry, QgsPointXY, QgsMultiPoint,
35 | QgsFeatureSink,
36 | QgsProcessingAlgorithm,
37 | QgsProcessingParameterFeatureSource,
38 | QgsProcessingParameterFeatureSink)
39 | from .transform import bd2gcj
40 |
41 | class BD2GCJ(QgsProcessingAlgorithm):
42 | """
43 | This is an example algorithm that takes a vector layer and
44 | creates a new identical one.
45 |
46 | It is meant to be used as an example of how to create your own
47 | algorithms and explain methods and variables used to do it. An
48 | algorithm like this will be available in all elements, and there
49 | is not need for additional work.
50 |
51 | All Processing algorithms should extend the QgsProcessingAlgorithm
52 | class.
53 | """
54 |
55 | # Constants used to refer to parameters and outputs. They will be
56 | # used when calling the algorithm from another algorithm, or when
57 | # calling from the QGIS console.
58 |
59 | OUTPUT = 'OUTPUT'
60 | INPUT = 'INPUT'
61 |
62 | def initAlgorithm(self, config):
63 | """
64 | Here we define the inputs and output of the algorithm, along
65 | with some other properties.
66 | """
67 |
68 | # We add the input vector features source. It can have any kind of
69 | # geometry.
70 | self.addParameter(
71 | QgsProcessingParameterFeatureSource(
72 | self.INPUT,
73 | self.tr('Input layer'),
74 | [QgsProcessing.TypeVectorAnyGeometry]
75 | )
76 | )
77 |
78 | # We add a feature sink in which to store our processed features (this
79 | # usually takes the form of a newly created vector layer when the
80 | # algorithm is run in QGIS).
81 | self.addParameter(
82 | QgsProcessingParameterFeatureSink(
83 | self.OUTPUT,
84 | self.tr('Output layer')
85 | )
86 | )
87 |
88 | def processAlgorithm(self, parameters, context, feedback):
89 | """
90 | Here is where the processing itself takes place.
91 | """
92 |
93 | # Retrieve the feature source and sink. The 'dest_id' variable is used
94 | # to uniquely identify the feature sink, and must be included in the
95 | # dictionary returned by the processAlgorithm function.
96 | source = self.parameterAsSource(parameters, self.INPUT, context)
97 | (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
98 | context, source.fields(), source.wkbType(), source.sourceCrs())
99 |
100 | # Compute the number of steps to display within the progress bar and
101 | # get features from source
102 | total = 100.0 / source.featureCount() if source.featureCount() else 0
103 | features = source.getFeatures()
104 | print(features)
105 |
106 | for current, feature in enumerate(features):
107 | # Stop the algorithm if cancel button has been clicked
108 | if feedback.isCanceled():
109 | break
110 | # sshuair begin
111 | geom = feature.geometry()
112 | attrs = feature.attributes()
113 | geom_type = geom.wkbType()
114 |
115 | feature_new = QgsFeature()
116 |
117 | # Point
118 | if geom_type == 1:
119 | vertices = geom.asPoint()
120 | vert_new = bd2gcj(vertices[0], vertices[1])
121 | feature_new.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(vert_new[0], vert_new[1])))
122 |
123 | # LineString
124 | elif geom_type == 2:
125 | vert_new = []
126 | vertices = geom.asPolyline()
127 | for pt in vertices:
128 | pt_new = bd2gcj(pt[0], pt[1])
129 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
130 | feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))
131 |
132 | # Polygon
133 | elif geom_type == 3:
134 | vertices = geom.asPolygon()
135 | vert_new = []
136 | for ring in vertices:
137 | ring_vert = []
138 | for pt in ring:
139 | pt_new = bd2gcj(pt[0], pt[1])
140 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
141 | vert_new.append(ring_vert)
142 | feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))
143 |
144 | # MultiPoint
145 | elif geom_type == 4:
146 | vert_new = []
147 | vertices = geom.asMultiPoint()
148 | for pt in vertices:
149 | pt_new = bd2gcj(pt[0], pt[1])
150 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
151 | feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))
152 |
153 | # MultiLineString
154 | elif geom_type == 5:
155 | vertices = geom.asMultiPolyline()
156 | vert_new = []
157 | for part in vertices:
158 | linestring = []
159 | for pt in part:
160 | pt_new = bd2gcj(pt[0], pt[1])
161 | linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
162 | vert_new.append(linestring)
163 | feature_new.setGeometry(QgsGeometry.fromMultiPolylineXY(vert_new))
164 |
165 | # MultiPolygon
166 | elif geom_type == 6:
167 | vertices = geom.asMultiPolygon()
168 | vert_new = []
169 | for part in vertices:
170 | poly = []
171 | for ring in part:
172 | ring_vert = []
173 | for pt in ring:
174 | pt_new = bd2gcj(pt[0], pt[1])
175 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
176 | poly.append(ring_vert)
177 | vert_new.append(poly)
178 | feature_new.setGeometry(QgsGeometry.fromMultiPolygonXY(vert_new))
179 | else:
180 | continue
181 |
182 | feature_new.setAttributes(attrs)
183 | # sshuair end
184 |
185 |
186 |
187 | # feature = feature+0.1
188 | # Add a feature in the sink
189 | sink.addFeature(feature_new, QgsFeatureSink.FastInsert)
190 |
191 | # Update the progress bar
192 | feedback.setProgress(int(current * total))
193 | print(feature)
194 |
195 | # Return the results of the algorithm. In this case our only result is
196 | # the feature sink which contains the processed features, but some
197 | # algorithms may return multiple feature sinks, calculated numeric
198 | # statistics, etc. These should all be included in the returned
199 | # dictionary, with keys matching the feature corresponding parameter
200 | # or output names.
201 | return {self.OUTPUT: dest_id}
202 |
203 | def name(self):
204 | """
205 | Returns the algorithm name, used for identifying the algorithm. This
206 | string should be fixed for the algorithm, and must not be localised.
207 | The name should be unique within each provider. Names should contain
208 | lowercase alphanumeric characters only and no spaces or other
209 | formatting characters.
210 | """
211 | return 'BD09 to GCJ02'
212 |
213 | def displayName(self):
214 | """
215 | Returns the translated algorithm name, which should be used for any
216 | user-visible display of the algorithm name.
217 | """
218 | return self.tr(self.name())
219 |
220 | def group(self):
221 | """
222 | Returns the name of the group this algorithm belongs to. This string
223 | should be localised.
224 | """
225 | return self.tr(self.groupId())
226 |
227 | def groupId(self):
228 | """
229 | Returns the unique ID of the group this algorithm belongs to. This
230 | string should be fixed for the algorithm, and must not be localised.
231 | The group id should be unique within each provider. Group id should
232 | contain lowercase alphanumeric characters only and no spaces or other
233 | formatting characters.
234 | """
235 | return 'China Coord Convert'
236 |
237 | def tr(self, string):
238 | return QCoreApplication.translate('Processing', string)
239 |
240 | def createInstance(self):
241 | return BD2GCJ()
242 |
--------------------------------------------------------------------------------
/china_offset/gcj2bd.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | from PyQt5.QtCore import QCoreApplication
34 | from qgis.core import (QgsProcessing,QgsFeature, QgsGeometry, QgsPointXY, QgsMultiPoint,
35 | QgsFeatureSink,
36 | QgsProcessingAlgorithm,
37 | QgsProcessingParameterFeatureSource,
38 | QgsProcessingParameterFeatureSink)
39 | from .transform import gcj2bd
40 |
41 | class GCJ2BD(QgsProcessingAlgorithm):
42 | """
43 | This is an example algorithm that takes a vector layer and
44 | creates a new identical one.
45 |
46 | It is meant to be used as an example of how to create your own
47 | algorithms and explain methods and variables used to do it. An
48 | algorithm like this will be available in all elements, and there
49 | is not need for additional work.
50 |
51 | All Processing algorithms should extend the QgsProcessingAlgorithm
52 | class.
53 | """
54 |
55 | # Constants used to refer to parameters and outputs. They will be
56 | # used when calling the algorithm from another algorithm, or when
57 | # calling from the QGIS console.
58 |
59 | OUTPUT = 'OUTPUT'
60 | INPUT = 'INPUT'
61 |
62 | def initAlgorithm(self, config):
63 | """
64 | Here we define the inputs and output of the algorithm, along
65 | with some other properties.
66 | """
67 |
68 | # We add the input vector features source. It can have any kind of
69 | # geometry.
70 | self.addParameter(
71 | QgsProcessingParameterFeatureSource(
72 | self.INPUT,
73 | self.tr('Input layer'),
74 | [QgsProcessing.TypeVectorAnyGeometry]
75 | )
76 | )
77 |
78 | # We add a feature sink in which to store our processed features (this
79 | # usually takes the form of a newly created vector layer when the
80 | # algorithm is run in QGIS).
81 | self.addParameter(
82 | QgsProcessingParameterFeatureSink(
83 | self.OUTPUT,
84 | self.tr('Output layer')
85 | )
86 | )
87 |
88 | def processAlgorithm(self, parameters, context, feedback):
89 | """
90 | Here is where the processing itself takes place.
91 | """
92 |
93 | # Retrieve the feature source and sink. The 'dest_id' variable is used
94 | # to uniquely identify the feature sink, and must be included in the
95 | # dictionary returned by the processAlgorithm function.
96 | source = self.parameterAsSource(parameters, self.INPUT, context)
97 | (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
98 | context, source.fields(), source.wkbType(), source.sourceCrs())
99 |
100 | # Compute the number of steps to display within the progress bar and
101 | # get features from source
102 | total = 100.0 / source.featureCount() if source.featureCount() else 0
103 | features = source.getFeatures()
104 | print(features)
105 |
106 | for current, feature in enumerate(features):
107 | # Stop the algorithm if cancel button has been clicked
108 | if feedback.isCanceled():
109 | break
110 | # sshuair begin
111 | geom = feature.geometry()
112 | attrs = feature.attributes()
113 | geom_type = geom.wkbType()
114 |
115 | feature_new = QgsFeature()
116 |
117 | # Point
118 | if geom_type == 1:
119 | vertices = geom.asPoint()
120 | vert_new = gcj2bd(vertices[0], vertices[1])
121 | feature_new.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(vert_new[0], vert_new[1])))
122 |
123 | # LineString
124 | elif geom_type == 2:
125 | vert_new = []
126 | vertices = geom.asPolyline()
127 | for pt in vertices:
128 | pt_new = gcj2bd(pt[0], pt[1])
129 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
130 | feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))
131 |
132 | # Polygon
133 | elif geom_type == 3:
134 | vertices = geom.asPolygon()
135 | vert_new = []
136 | for ring in vertices:
137 | ring_vert = []
138 | for pt in ring:
139 | pt_new = gcj2bd(pt[0], pt[1])
140 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
141 | vert_new.append(ring_vert)
142 | feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))
143 |
144 | # MultiPoint
145 | elif geom_type == 4:
146 | vert_new = []
147 | vertices = geom.asMultiPoint()
148 | for pt in vertices:
149 | pt_new = gcj2bd(pt[0], pt[1])
150 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
151 | feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))
152 |
153 | # MultiLineString
154 | elif geom_type == 5:
155 | vertices = geom.asMultiPolyline()
156 | vert_new = []
157 | for part in vertices:
158 | linestring = []
159 | for pt in part:
160 | pt_new = gcj2bd(pt[0], pt[1])
161 | linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
162 | vert_new.append(linestring)
163 | feature_new.setGeometry(QgsGeometry.fromMultiPolylineXY(vert_new))
164 |
165 | # MultiPolygon
166 | elif geom_type == 6:
167 | vertices = geom.asMultiPolygon()
168 | vert_new = []
169 | for part in vertices:
170 | poly = []
171 | for ring in part:
172 | ring_vert = []
173 | for pt in ring:
174 | pt_new = gcj2bd(pt[0], pt[1])
175 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
176 | poly.append(ring_vert)
177 | vert_new.append(poly)
178 | feature_new.setGeometry(QgsGeometry.fromMultiPolygonXY(vert_new))
179 | else:
180 | continue
181 |
182 | feature_new.setAttributes(attrs)
183 | # sshuair end
184 |
185 |
186 |
187 | # feature = feature+0.1
188 | # Add a feature in the sink
189 | sink.addFeature(feature_new, QgsFeatureSink.FastInsert)
190 |
191 | # Update the progress bar
192 | feedback.setProgress(int(current * total))
193 | print(feature)
194 |
195 | # Return the results of the algorithm. In this case our only result is
196 | # the feature sink which contains the processed features, but some
197 | # algorithms may return multiple feature sinks, calculated numeric
198 | # statistics, etc. These should all be included in the returned
199 | # dictionary, with keys matching the feature corresponding parameter
200 | # or output names.
201 | return {self.OUTPUT: dest_id}
202 |
203 | def name(self):
204 | """
205 | Returns the algorithm name, used for identifying the algorithm. This
206 | string should be fixed for the algorithm, and must not be localised.
207 | The name should be unique within each provider. Names should contain
208 | lowercase alphanumeric characters only and no spaces or other
209 | formatting characters.
210 | """
211 | return 'GCJ02 to BD09'
212 |
213 | def displayName(self):
214 | """
215 | Returns the translated algorithm name, which should be used for any
216 | user-visible display of the algorithm name.
217 | """
218 | return self.tr(self.name())
219 |
220 | def group(self):
221 | """
222 | Returns the name of the group this algorithm belongs to. This string
223 | should be localised.
224 | """
225 | return self.tr(self.groupId())
226 |
227 | def groupId(self):
228 | """
229 | Returns the unique ID of the group this algorithm belongs to. This
230 | string should be fixed for the algorithm, and must not be localised.
231 | The group id should be unique within each provider. Group id should
232 | contain lowercase alphanumeric characters only and no spaces or other
233 | formatting characters.
234 | """
235 | return 'China Coord Convert'
236 |
237 | def tr(self, string):
238 | return QCoreApplication.translate('Processing', string)
239 |
240 | def createInstance(self):
241 | return GCJ2BD()
242 |
--------------------------------------------------------------------------------
/china_offset/wgs2gcj.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | from PyQt5.QtCore import QCoreApplication
34 | from qgis.core import (QgsProcessing,QgsFeature, QgsGeometry, QgsPointXY, QgsMultiPoint,
35 | QgsFeatureSink,
36 | QgsProcessingAlgorithm,
37 | QgsProcessingParameterFeatureSource,
38 | QgsProcessingParameterFeatureSink)
39 | from .transform import wgs2gcj
40 |
41 | class WGS2GCJ(QgsProcessingAlgorithm):
42 | """
43 | This is an example algorithm that takes a vector layer and
44 | creates a new identical one.
45 |
46 | It is meant to be used as an example of how to create your own
47 | algorithms and explain methods and variables used to do it. An
48 | algorithm like this will be available in all elements, and there
49 | is not need for additional work.
50 |
51 | All Processing algorithms should extend the QgsProcessingAlgorithm
52 | class.
53 | """
54 |
55 | # Constants used to refer to parameters and outputs. They will be
56 | # used when calling the algorithm from another algorithm, or when
57 | # calling from the QGIS console.
58 |
59 | OUTPUT = 'OUTPUT'
60 | INPUT = 'INPUT'
61 |
62 | def initAlgorithm(self, config):
63 | """
64 | Here we define the inputs and output of the algorithm, along
65 | with some other properties.
66 | """
67 |
68 | # We add the input vector features source. It can have any kind of
69 | # geometry.
70 | self.addParameter(
71 | QgsProcessingParameterFeatureSource(
72 | self.INPUT,
73 | self.tr('Input layer'),
74 | [QgsProcessing.TypeVectorAnyGeometry]
75 | )
76 | )
77 |
78 | # We add a feature sink in which to store our processed features (this
79 | # usually takes the form of a newly created vector layer when the
80 | # algorithm is run in QGIS).
81 | self.addParameter(
82 | QgsProcessingParameterFeatureSink(
83 | self.OUTPUT,
84 | self.tr('Output layer')
85 | )
86 | )
87 |
88 | def processAlgorithm(self, parameters, context, feedback):
89 | """
90 | Here is where the processing itself takes place.
91 | """
92 |
93 | # Retrieve the feature source and sink. The 'dest_id' variable is used
94 | # to uniquely identify the feature sink, and must be included in the
95 | # dictionary returned by the processAlgorithm function.
96 | source = self.parameterAsSource(parameters, self.INPUT, context)
97 | (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
98 | context, source.fields(), source.wkbType(), source.sourceCrs())
99 |
100 | # Compute the number of steps to display within the progress bar and
101 | # get features from source
102 | total = 100.0 / source.featureCount() if source.featureCount() else 0
103 | features = source.getFeatures()
104 | print(features)
105 |
106 | for current, feature in enumerate(features):
107 | # Stop the algorithm if cancel button has been clicked
108 | if feedback.isCanceled():
109 | break
110 | # sshuair begin
111 | geom = feature.geometry()
112 | attrs = feature.attributes()
113 | geom_type = geom.wkbType()
114 |
115 | feature_new = QgsFeature()
116 |
117 | # Point
118 | if geom_type == 1:
119 | vertices = geom.asPoint()
120 | vert_new = wgs2gcj(vertices[0], vertices[1])
121 | feature_new.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(vert_new[0], vert_new[1])))
122 |
123 | # LineString
124 | elif geom_type == 2:
125 | vert_new = []
126 | vertices = geom.asPolyline()
127 | for pt in vertices:
128 | pt_new = wgs2gcj(pt[0], pt[1])
129 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
130 | feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))
131 |
132 | # Polygon
133 | elif geom_type == 3:
134 | vertices = geom.asPolygon()
135 | vert_new = []
136 | for ring in vertices:
137 | ring_vert = []
138 | for pt in ring:
139 | pt_new = wgs2gcj(pt[0], pt[1])
140 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
141 | vert_new.append(ring_vert)
142 | feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))
143 |
144 | # MultiPoint
145 | elif geom_type == 4:
146 | vert_new = []
147 | vertices = geom.asMultiPoint()
148 | for pt in vertices:
149 | pt_new = wgs2gcj(pt[0], pt[1])
150 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
151 | feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))
152 |
153 | # MultiLineString
154 | elif geom_type == 5:
155 | vertices = geom.asMultiPolyline()
156 | vert_new = []
157 | for part in vertices:
158 | linestring = []
159 | for pt in part:
160 | pt_new = wgs2gcj(pt[0], pt[1])
161 | linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
162 | vert_new.append(linestring)
163 | feature_new.setGeometry(QgsGeometry.fromMultiPolylineXY(vert_new))
164 |
165 | # MultiPolygon
166 | elif geom_type == 6:
167 | vertices = geom.asMultiPolygon()
168 | vert_new = []
169 | for part in vertices:
170 | poly = []
171 | for ring in part:
172 | ring_vert = []
173 | for pt in ring:
174 | pt_new = wgs2gcj(pt[0], pt[1])
175 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
176 | poly.append(ring_vert)
177 | vert_new.append(poly)
178 | feature_new.setGeometry(QgsGeometry.fromMultiPolygonXY(vert_new))
179 | else:
180 | continue
181 |
182 | feature_new.setAttributes(attrs)
183 | # sshuair end
184 |
185 |
186 |
187 | # feature = feature+0.1
188 | # Add a feature in the sink
189 | sink.addFeature(feature_new, QgsFeatureSink.FastInsert)
190 |
191 | # Update the progress bar
192 | feedback.setProgress(int(current * total))
193 | print(feature)
194 |
195 | # Return the results of the algorithm. In this case our only result is
196 | # the feature sink which contains the processed features, but some
197 | # algorithms may return multiple feature sinks, calculated numeric
198 | # statistics, etc. These should all be included in the returned
199 | # dictionary, with keys matching the feature corresponding parameter
200 | # or output names.
201 | return {self.OUTPUT: dest_id}
202 |
203 | def name(self):
204 | """
205 | Returns the algorithm name, used for identifying the algorithm. This
206 | string should be fixed for the algorithm, and must not be localised.
207 | The name should be unique within each provider. Names should contain
208 | lowercase alphanumeric characters only and no spaces or other
209 | formatting characters.
210 | """
211 | return 'WGS to GCJ02'
212 |
213 | def displayName(self):
214 | """
215 | Returns the translated algorithm name, which should be used for any
216 | user-visible display of the algorithm name.
217 | """
218 | return self.tr(self.name())
219 |
220 | def group(self):
221 | """
222 | Returns the name of the group this algorithm belongs to. This string
223 | should be localised.
224 | """
225 | return self.tr(self.groupId())
226 |
227 | def groupId(self):
228 | """
229 | Returns the unique ID of the group this algorithm belongs to. This
230 | string should be fixed for the algorithm, and must not be localised.
231 | The group id should be unique within each provider. Group id should
232 | contain lowercase alphanumeric characters only and no spaces or other
233 | formatting characters.
234 | """
235 | return 'China Coord Convert'
236 |
237 | def tr(self, string):
238 | return QCoreApplication.translate('Processing', string)
239 |
240 | def createInstance(self):
241 | return WGS2GCJ()
242 |
--------------------------------------------------------------------------------
/china_offset/gcj2wgs.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | from PyQt5.QtCore import QCoreApplication
34 | from qgis.core import (QgsProcessing,QgsFeature, QgsGeometry, QgsPointXY, QgsMultiPoint,
35 | QgsFeatureSink,
36 | QgsProcessingAlgorithm,
37 | QgsProcessingParameterFeatureSource,
38 | QgsProcessingParameterFeatureSink)
39 | from .transform import gcj2wgs
40 |
41 | class GCJ2WGS(QgsProcessingAlgorithm):
42 | """
43 | This is an example algorithm that takes a vector layer and
44 | creates a new identical one.
45 |
46 | It is meant to be used as an example of how to create your own
47 | algorithms and explain methods and variables used to do it. An
48 | algorithm like this will be available in all elements, and there
49 | is not need for additional work.
50 |
51 | All Processing algorithms should extend the QgsProcessingAlgorithm
52 | class.
53 | """
54 |
55 | # Constants used to refer to parameters and outputs. They will be
56 | # used when calling the algorithm from another algorithm, or when
57 | # calling from the QGIS console.
58 |
59 | OUTPUT = 'OUTPUT'
60 | INPUT = 'INPUT'
61 |
62 | def initAlgorithm(self, config):
63 | """
64 | Here we define the inputs and output of the algorithm, along
65 | with some other properties.
66 | """
67 |
68 | # We add the input vector features source. It can have any kind of
69 | # geometry.
70 | self.addParameter(
71 | QgsProcessingParameterFeatureSource(
72 | self.INPUT,
73 | self.tr('Input layer'),
74 | [QgsProcessing.TypeVectorAnyGeometry]
75 | )
76 | )
77 |
78 | # We add a feature sink in which to store our processed features (this
79 | # usually takes the form of a newly created vector layer when the
80 | # algorithm is run in QGIS).
81 | self.addParameter(
82 | QgsProcessingParameterFeatureSink(
83 | self.OUTPUT,
84 | self.tr('Output layer')
85 | )
86 | )
87 |
88 | def processAlgorithm(self, parameters, context, feedback):
89 | """
90 | Here is where the processing itself takes place.
91 | """
92 |
93 | # Retrieve the feature source and sink. The 'dest_id' variable is used
94 | # to uniquely identify the feature sink, and must be included in the
95 | # dictionary returned by the processAlgorithm function.
96 | source = self.parameterAsSource(parameters, self.INPUT, context)
97 | (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
98 | context, source.fields(), source.wkbType(), source.sourceCrs())
99 |
100 | # Compute the number of steps to display within the progress bar and
101 | # get features from source
102 | total = 100.0 / source.featureCount() if source.featureCount() else 0
103 | features = source.getFeatures()
104 | print(features)
105 |
106 | for current, feature in enumerate(features):
107 | # Stop the algorithm if cancel button has been clicked
108 | if feedback.isCanceled():
109 | break
110 | # sshuair begin
111 | geom = feature.geometry()
112 | attrs = feature.attributes()
113 | geom_type = geom.wkbType()
114 |
115 | feature_new = QgsFeature()
116 |
117 | # Point
118 | if geom_type == 1:
119 | vertices = geom.asPoint()
120 | vert_new = gcj2wgs(vertices[0], vertices[1])
121 | feature_new.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(vert_new[0], vert_new[1])))
122 |
123 | # LineString
124 | elif geom_type == 2:
125 | vert_new = []
126 | vertices = geom.asPolyline()
127 | for pt in vertices:
128 | pt_new = gcj2wgs(pt[0], pt[1])
129 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
130 | feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))
131 |
132 | # Polygon
133 | elif geom_type == 3:
134 | vertices = geom.asPolygon()
135 | vert_new = []
136 | for ring in vertices:
137 | ring_vert = []
138 | for pt in ring:
139 | pt_new = gcj2wgs(pt[0], pt[1])
140 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
141 | vert_new.append(ring_vert)
142 | feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))
143 |
144 | # MultiPoint
145 | elif geom_type == 4:
146 | vert_new = []
147 | vertices = geom.asMultiPoint()
148 | for pt in vertices:
149 | pt_new = gcj2wgs(pt[0], pt[1])
150 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
151 | feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))
152 |
153 | # MultiLineString
154 | elif geom_type == 5:
155 | vertices = geom.asMultiPolyline()
156 | vert_new = []
157 | for part in vertices:
158 | linestring = []
159 | for pt in part:
160 | pt_new = gcj2wgs(pt[0], pt[1])
161 | linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
162 | vert_new.append(linestring)
163 | feature_new.setGeometry(QgsGeometry.fromMultiPolylineXY(vert_new))
164 |
165 | # MultiPolygon
166 | elif geom_type == 6:
167 | vertices = geom.asMultiPolygon()
168 | vert_new = []
169 | for part in vertices:
170 | poly = []
171 | for ring in part:
172 | ring_vert = []
173 | for pt in ring:
174 | pt_new = gcj2wgs(pt[0], pt[1])
175 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
176 | poly.append(ring_vert)
177 | vert_new.append(poly)
178 | feature_new.setGeometry(QgsGeometry.fromMultiPolygonXY(vert_new))
179 | else:
180 | continue
181 |
182 | feature_new.setAttributes(attrs)
183 | # sshuair end
184 |
185 |
186 |
187 | # feature = feature+0.1
188 | # Add a feature in the sink
189 | sink.addFeature(feature_new, QgsFeatureSink.FastInsert)
190 |
191 | # Update the progress bar
192 | feedback.setProgress(int(current * total))
193 | print(feature)
194 |
195 | # Return the results of the algorithm. In this case our only result is
196 | # the feature sink which contains the processed features, but some
197 | # algorithms may return multiple feature sinks, calculated numeric
198 | # statistics, etc. These should all be included in the returned
199 | # dictionary, with keys matching the feature corresponding parameter
200 | # or output names.
201 | return {self.OUTPUT: dest_id}
202 |
203 | def name(self):
204 | """
205 | Returns the algorithm name, used for identifying the algorithm. This
206 | string should be fixed for the algorithm, and must not be localised.
207 | The name should be unique within each provider. Names should contain
208 | lowercase alphanumeric characters only and no spaces or other
209 | formatting characters.
210 | """
211 | return 'GCJ02 to WGS'
212 |
213 | def displayName(self):
214 | """
215 | Returns the translated algorithm name, which should be used for any
216 | user-visible display of the algorithm name.
217 | """
218 | return self.tr(self.name())
219 |
220 | def group(self):
221 | """
222 | Returns the name of the group this algorithm belongs to. This string
223 | should be localised.
224 | """
225 | return self.tr(self.groupId())
226 |
227 | def groupId(self):
228 | """
229 | Returns the unique ID of the group this algorithm belongs to. This
230 | string should be fixed for the algorithm, and must not be localised.
231 | The group id should be unique within each provider. Group id should
232 | contain lowercase alphanumeric characters only and no spaces or other
233 | formatting characters.
234 | """
235 | return 'China Coord Convert'
236 |
237 | def tr(self, string):
238 | return QCoreApplication.translate('Processing', string)
239 |
240 | def createInstance(self):
241 | return GCJ2WGS()
242 |
243 |
--------------------------------------------------------------------------------
/china_offset/wgs2bd.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | /***************************************************************************
5 | GeoHeyToolbox
6 | A QGIS plugin
7 | GeoHey Toolbox
8 | Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
9 | -------------------
10 | begin : 2019-11-09
11 | copyright : (C) 2018 by GeoHey
12 | email : sshuair@gmail.com
13 | ***************************************************************************/
14 |
15 | /***************************************************************************
16 | * *
17 | * This program is free software; you can redistribute it and/or modify *
18 | * it under the terms of the GNU General Public License as published by *
19 | * the Free Software Foundation; either version 2 of the License, or *
20 | * (at your option) any later version. *
21 | * *
22 | ***************************************************************************/
23 | """
24 |
25 | __author__ = 'GeoHey'
26 | __date__ = '2019-11-09'
27 | __copyright__ = '(C) 2018 by GeoHey'
28 |
29 | # This will get replaced with a git SHA1 when you do a git archive
30 |
31 | __revision__ = '$Format:%H$'
32 |
33 | # import os
34 | from PyQt5.QtCore import QCoreApplication
35 | # from PyQt5.QtGui import QIcon
36 | from qgis.core import (QgsProcessing,QgsFeature, QgsGeometry, QgsPointXY, QgsMultiPoint,
37 | QgsFeatureSink,
38 | QgsProcessingAlgorithm,
39 | QgsProcessingParameterFeatureSource,
40 | QgsProcessingParameterFeatureSink)
41 | from .transform import wgs2bd
42 |
43 | class WGS2BD(QgsProcessingAlgorithm):
44 | """
45 | This is an example algorithm that takes a vector layer and
46 | creates a new identical one.
47 |
48 | It is meant to be used as an example of how to create your own
49 | algorithms and explain methods and variables used to do it. An
50 | algorithm like this will be available in all elements, and there
51 | is not need for additional work.
52 |
53 | All Processing algorithms should extend the QgsProcessingAlgorithm
54 | class.
55 | """
56 |
57 | # Constants used to refer to parameters and outputs. They will be
58 | # used when calling the algorithm from another algorithm, or when
59 | # calling from the QGIS console.
60 |
61 | OUTPUT = 'OUTPUT'
62 | INPUT = 'INPUT'
63 |
64 | def initAlgorithm(self, config):
65 | """
66 | Here we define the inputs and output of the algorithm, along
67 | with some other properties.
68 | """
69 |
70 | # We add the input vector features source. It can have any kind of
71 | # geometry.
72 | self.addParameter(
73 | QgsProcessingParameterFeatureSource(
74 | self.INPUT,
75 | self.tr('Input layer'),
76 | [QgsProcessing.TypeVectorAnyGeometry]
77 | )
78 | )
79 |
80 | # We add a feature sink in which to store our processed features (this
81 | # usually takes the form of a newly created vector layer when the
82 | # algorithm is run in QGIS).
83 | self.addParameter(
84 | QgsProcessingParameterFeatureSink(
85 | self.OUTPUT,
86 | self.tr('Output layer')
87 | )
88 | )
89 |
90 | def processAlgorithm(self, parameters, context, feedback):
91 | """
92 | Here is where the processing itself takes place.
93 | """
94 |
95 | # Retrieve the feature source and sink. The 'dest_id' variable is used
96 | # to uniquely identify the feature sink, and must be included in the
97 | # dictionary returned by the processAlgorithm function.
98 | source = self.parameterAsSource(parameters, self.INPUT, context)
99 | (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
100 | context, source.fields(), source.wkbType(), source.sourceCrs())
101 |
102 | # Compute the number of steps to display within the progress bar and
103 | # get features from source
104 | total = 100.0 / source.featureCount() if source.featureCount() else 0
105 | features = source.getFeatures()
106 | print(features)
107 |
108 | for current, feature in enumerate(features):
109 | # Stop the algorithm if cancel button has been clicked
110 | if feedback.isCanceled():
111 | break
112 | # sshuair begin
113 | geom = feature.geometry()
114 | attrs = feature.attributes()
115 | geom_type = geom.wkbType()
116 |
117 | feature_new = QgsFeature()
118 |
119 | # Point
120 | if geom_type == 1:
121 | vertices = geom.asPoint()
122 | vert_new = wgs2bd(vertices[0], vertices[1])
123 | feature_new.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(vert_new[0], vert_new[1])))
124 |
125 | # LineString
126 | elif geom_type == 2:
127 | vert_new = []
128 | vertices = geom.asPolyline()
129 | for pt in vertices:
130 | pt_new = wgs2bd(pt[0], pt[1])
131 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
132 | feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new))
133 |
134 | # Polygon
135 | elif geom_type == 3:
136 | vertices = geom.asPolygon()
137 | vert_new = []
138 | for ring in vertices:
139 | ring_vert = []
140 | for pt in ring:
141 | pt_new = wgs2bd(pt[0], pt[1])
142 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
143 | vert_new.append(ring_vert)
144 | feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new))
145 |
146 | # MultiPoint
147 | elif geom_type == 4:
148 | vert_new = []
149 | vertices = geom.asMultiPoint()
150 | for pt in vertices:
151 | pt_new = wgs2bd(pt[0], pt[1])
152 | vert_new.append(QgsPointXY(pt_new[0], pt_new[1]))
153 | feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new))
154 |
155 | # MultiLineString
156 | elif geom_type == 5:
157 | vertices = geom.asMultiPolyline()
158 | vert_new = []
159 | for part in vertices:
160 | linestring = []
161 | for pt in part:
162 | pt_new = wgs2bd(pt[0], pt[1])
163 | linestring.append(QgsPointXY(pt_new[0], pt_new[1]))
164 | vert_new.append(linestring)
165 | feature_new.setGeometry(QgsGeometry.fromMultiPolylineXY(vert_new))
166 |
167 | # MultiPolygon
168 | elif geom_type == 6:
169 | vertices = geom.asMultiPolygon()
170 | vert_new = []
171 | for part in vertices:
172 | poly = []
173 | for ring in part:
174 | ring_vert = []
175 | for pt in ring:
176 | pt_new = wgs2bd(pt[0], pt[1])
177 | ring_vert.append(QgsPointXY(pt_new[0], pt_new[1]))
178 | poly.append(ring_vert)
179 | vert_new.append(poly)
180 | feature_new.setGeometry(QgsGeometry.fromMultiPolygonXY(vert_new))
181 | else:
182 | continue
183 |
184 | feature_new.setAttributes(attrs)
185 | # sshuair end
186 |
187 |
188 |
189 | # feature = feature+0.1
190 | # Add a feature in the sink
191 | sink.addFeature(feature_new, QgsFeatureSink.FastInsert)
192 |
193 | # Update the progress bar
194 | feedback.setProgress(int(current * total))
195 | print(feature)
196 |
197 | # Return the results of the algorithm. In this case our only result is
198 | # the feature sink which contains the processed features, but some
199 | # algorithms may return multiple feature sinks, calculated numeric
200 | # statistics, etc. These should all be included in the returned
201 | # dictionary, with keys matching the feature corresponding parameter
202 | # or output names.
203 | return {self.OUTPUT: dest_id}
204 |
205 | def name(self):
206 | """
207 | Returns the algorithm name, used for identifying the algorithm. This
208 | string should be fixed for the algorithm, and must not be localised.
209 | The name should be unique within each provider. Names should contain
210 | lowercase alphanumeric characters only and no spaces or other
211 | formatting characters.
212 | """
213 | return 'WGS to BD09'
214 |
215 | def displayName(self):
216 | """
217 | Returns the translated algorithm name, which should be used for any
218 | user-visible display of the algorithm name.
219 | """
220 | return self.tr(self.name())
221 |
222 | def group(self):
223 | """
224 | Returns the name of the group this algorithm belongs to. This string
225 | should be localised.
226 | """
227 | return self.tr(self.groupId())
228 |
229 | def groupId(self):
230 | """
231 | Returns the unique ID of the group this algorithm belongs to. This
232 | string should be fixed for the algorithm, and must not be localised.
233 | The group id should be unique within each provider. Group id should
234 | contain lowercase alphanumeric characters only and no spaces or other
235 | formatting characters.
236 | """
237 | return 'China Coord Convert'
238 |
239 | def tr(self, string):
240 | return QCoreApplication.translate('Processing', string)
241 |
242 | def createInstance(self):
243 | return WGS2BD()
244 |
245 | # def icon(self):
246 | # return QIcon(os.path.dirname(__file__) + '/icon.png')
247 |
--------------------------------------------------------------------------------