2014-10-04 14:05:51 +03:00

273 lines
11 KiB
Python

# -*- coding: utf-8 -*-
"""
***************************************************************************
Grid.py
---------------------
Date : May 2010
Copyright : (C) 2010 by Michael Minn
Email : pyqgis at michaelminn dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Michael Minn'
__date__ = 'May 2010'
__copyright__ = '(C) 2010, Michael Minn'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import math
from PyQt4.QtCore import *
from qgis.core import *
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import \
GeoAlgorithmExecutionException
from processing.core.parameters import ParameterNumber
from processing.core.parameters import ParameterCrs
from processing.core.parameters import ParameterSelection
from processing.core.outputs import OutputVector
class Grid(GeoAlgorithm):
TYPE = 'TYPE'
WIDTH = 'WIDTH'
HEIGHT = 'HEIGHT'
HSPACING = 'HSPACING'
VSPACING = 'VSPACING'
CENTERX = 'CENTERX'
CENTERY = 'CENTERY'
CRS = 'CRS'
OUTPUT = 'OUTPUT'
TYPES = ['Rectangle (line)',
'Rectangle (polygon)',
'Diamond (polygon)',
'Hexagon (polygon)'
]
def defineCharacteristics(self):
self.name = 'Create grid'
self.group = 'Vector creation tools'
self.addParameter(ParameterSelection(
self.TYPE, 'Grid type', self.TYPES))
self.addParameter(ParameterNumber(
self.WIDTH, 'Width', default=360.0))
self.addParameter(ParameterNumber(
self.HEIGHT, 'Height', default=180.0))
self.addParameter(ParameterNumber(
self.HSPACING, 'Horizontal spacing', default=10.0))
self.addParameter(ParameterNumber(
self.VSPACING, 'Vertical spacing', default=10.0))
self.addParameter(ParameterNumber(
self.CENTERX, 'Center X', default=0.0))
self.addParameter(ParameterNumber(
self.CENTERY, 'Center Y', default=0.0))
self.addParameter(ParameterCrs(self.CRS, 'Output CRS'))
self.addOutput(OutputVector(self.OUTPUT, 'Output'))
def processAlgorithm(self, progress):
idx = self.getParameterValue(self.TYPE)
width = self.getParameterValue(self.WIDTH)
height = self.getParameterValue(self.HEIGHT)
hSpacing = self.getParameterValue(self.HSPACING)
vSpacing = self.getParameterValue(self.VSPACING)
centerX = self.getParameterValue(self.CENTERX)
centerY = self.getParameterValue(self.CENTERY)
originX = centerX - width / 2.0
originY = centerY - height / 2.0
crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.CRS))
if hSpacing <= 0 or vSpacing <= 0:
raise GeoAlgorithmExecutionException(
'Invalid grid spacing: %s/%s' % (hSpacing, vSpacing))
if width < hSpacing:
raise GeoAlgorithmExecutionException(
'Horizontal spacing is too small for the covered area')
if height < vSpacing:
raise GeoAlgorithmExecutionException(
'Vertical spacing is too small for the covered area')
if self.TYPES[idx].find('polygon') >= 0:
geometryType = QGis.WKBPolygon
else:
geometryType = QGis.WKBLineString
fields = [QgsField('left', QVariant.Double, '', 24, 16),
QgsField('top', QVariant.Double, '', 24, 16),
QgsField('right', QVariant.Double, '', 24, 16),
QgsField('bottom', QVariant.Double, '', 24, 16)
]
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields,
geometryType, crs)
if idx == 0:
self._rectangleGridLine(
writer, width, height, originX, originY, hSpacing, vSpacing)
elif idx == 1:
self._rectangleGridPoly(
writer, width, height, originX, originY, hSpacing, vSpacing)
elif idx == 2:
self._diamondGrid(
writer, width, height, originX, originY, hSpacing, vSpacing)
elif idx == 3:
self._hexagonGrid(
writer, width, height, originX, originY, hSpacing, vSpacing)
del writer
def _rectangleGridLine(self, writer, width, height, originX, originY,
hSpacing, vSpacing):
ft = QgsFeature()
columns = int(math.floor(float(width) / hSpacing))
rows = int(math.floor(float(height) / vSpacing))
# Longitude lines
for col in xrange(0, columns + 1):
polyline = []
x = originX + (col * hSpacing)
for row in xrange(0, rows + 1):
y = originY + (row * vSpacing)
polyline.append(QgsPoint(x, y))
ft.setGeometry(QgsGeometry.fromPolyline(polyline))
ft.setAttributes([x, originY, x, originY + (rows * vSpacing)])
writer.addFeature(ft)
# Latitude lines
for row in xrange(0, rows + 1):
polyline = []
y = originY + (row * vSpacing)
for col in xrange(0, columns + 1):
x = originX + (col * hSpacing)
polyline.append(QgsPoint(x, y))
ft.setGeometry(QgsGeometry.fromPolyline(polyline))
ft.setAttributes([originX, y, originX + (col * hSpacing), y])
writer.addFeature(feature)
def _rectangleGridPoly(self, writer, width, height, originX, originY,
hSpacing, vSpacing):
ft = QgsFeature()
columns = int(math.floor(float(width) / hSpacing))
rows = int(math.floor(float(height) / vSpacing))
for col in xrange(0, columns):
# (column + 1) and (row + 1) calculation is used to maintain
# topology between adjacent shapes and avoid overlaps/holes
# due to rounding errors
x1 = originX + (col * hSpacing)
x2 = originX + ((col + 1) * hSpacing)
for row in xrange(0, rows):
y1 = originY + (row * vSpacing)
y2 = originY + ((row + 1) * vSpacing)
polyline = []
polyline.append(QgsPoint(x1, y1))
polyline.append(QgsPoint(x2, y1))
polyline.append(QgsPoint(x2, y2))
polyline.append(QgsPoint(x1, y2))
polyline.append(QgsPoint(x1, y1))
ft.setGeometry(QgsGeometry.fromPolygon([polyline]))
ft.setAttributes([x1, y1, x2, y2])
writer.addFeature(ft)
def _diamondGrid(self, writer, width, height, originX, originY,
hSpacing, vSpacing):
ft = QgsFeature()
halfHSpacing = hSpacing / 2
halfVSpacing = vSpacing / 2
columns = int(math.floor(float(width) / halfHSpacing))
rows = int(math.floor(float(height) / vSpacing))
for col in xrange(0, columns):
x1 = originX + ((col + 0) * halfHSpacing)
x2 = originX + ((col + 1) * halfHSpacing)
x3 = originX + ((col + 2) * halfHSpacing)
for row in xrange(0, rows):
if (col % 2) == 0:
y1 = originY + (((row * 2) + 0) * halfVSpacing)
y2 = originY + (((row * 2) + 1) * halfVSpacing)
y3 = originY + (((row * 2) + 2) * halfVSpacing)
else:
y1 = originY + (((row * 2) + 1) * halfVSpacing)
y2 = originY + (((row * 2) + 2) * halfVSpacing)
y3 = originY + (((row * 2) + 3) * halfVSpacing)
polyline = []
polyline.append(QgsPoint(x1, y2))
polyline.append(QgsPoint(x2, y1))
polyline.append(QgsPoint(x3, y2))
polyline.append(QgsPoint(x2, y3))
polyline.append(QgsPoint(x1, y2))
ft.setGeometry(QgsGeometry.fromPolygon([polyline]))
ft.setAttributes([x1, y1, x3, y3])
writer.addFeature(ft)
def _hexagonGrid(self, writer, width, height, originX, originY,
hSpacing, vSpacing):
ft = QgsFeature()
# To preserve symmetry, hspacing is fixed relative to vspacing
xXertexLo = 0.288675134594813 * vSpacing;
xXertexHi = 0.577350269189626 * vSpacing;
hSpacing = xVertexLo + xVertexHi
halfVSpacing = vSpacing / 2
columns = int(math.floor(float(width) / hSpacing))
rows = int(math.floor(float(height) / vSpacing))
for col in xrange(0, columns):
# (column + 1) and (row + 1) calculation is used to maintain
# topology between adjacent shapes and avoid overlaps/holes
# due to rounding errors
x1 = originX + (col * hSpacing) # far left
x2 = x1 + (xVertexHi - xVertexLo) # left
x3 = originX + ((col + 1) * hSpacing) # right
x4 = x3 + (xVertexHi - xVertexLo) # far right
for row in xrange(0, rows):
if (col % 2) == 0:
y1 = originY + (((row * 2) + 0) * halfVSpacing) # hi
y2 = originY + (((row * 2) + 1) * halfVSpacing) # mid
y3 = originY + (((row * 2) + 2) * halfVSpacing) # lo
else:
y1 = originY + (((row * 2) + 1) * halfVSpacing) # hi
y2 = originY + (((row * 2) + 2) * halfVSpacing) # mid
y3 = originY + (((row * 2) + 3) * halfVSpacing) # lo
polyline = []
polyline.append(QgsPoint(x1, y2))
polyline.append(QgsPoint(x2, y1))
polyline.append(QgsPoint(x3, y1))
polyline.append(QgsPoint(x4, y2))
polyline.append(QgsPoint(x3, y3))
polyline.append(QgsPoint(x2, y3))
polyline.append(QgsPoint(x1, y2))
ft.setGeometry(QgsGeometry.fromPolygon([polyline]))
ft.setAttributes([x1, y1, x4, y3])
writer.addFeature(ft)