Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
Conflicts:
	README.md
  • Loading branch information
ldesousa committed Nov 3, 2016
2 parents fef1823 + 6ffadaf commit 1f7f43d
Show file tree
Hide file tree
Showing 16 changed files with 346 additions and 218 deletions.
56 changes: 47 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,64 @@ and usage of hexagonal raster grids. These tools rely on the
Future work includes the development of a Graphical User Interface (GUI) for
these tools on QGIS, making the usage of hexagonal grids even simpler.


This tool suite can be installed from the [PyPi repository](https://pypi.python.org/pypi/hex-utils).



Software dependencies

Installation Requirements
-------------------------------------------------------------------------------

The `hasc2gml` script requires the GDAL library. On Debian based systems it can
be installed with the following command:
The `hasc2gml` script requires the Python GDAL library; the `asc2hasc` script
requires the `scipy` library. At this moment there are no functional universal
Python packages available for these libraries. Therefore system specific
packages are required in these cases. On Debian based systems they can be
installed with the following command:

`sudo apt install python3-gdal python3-scipy`

The Python package manager is required to install dependencies; on Debian based
systems it can be obtained like:

`sudo apt install python3-pip`

Installing from PyPi
-------------------------------------------------------------------------------

The easiest way to install `hex-utils` is through the universal package
available from the Python Package Index (PyPi); an example again on Debian
based systems:

`sudo pip3 install hex-utils`

Installing from GitHub
-------------------------------------------------------------------------------

Start by cloning the repository to your system:

`git clone [email protected]:ldesousa/hex-utils.git`

Change to the new folder:

`cd hex-utils.git`

It is possible to install directly from the `master` branch, but it is more
advisable to use of the [tagged releases](https://github.com/ldesousa/hex-utils/releases),
*e.g.*:

`git checkout tags/v2.2`

`apt install python-gdal`
Then install the scripts system wide:

It can also be installed from the PyPi repository (the best option for virtual
environments):
`sudo python3 setup.py install`

`pip instal GDAL`
Finally, install the remaining dependencies:

`sudo pip3 install -r requirements.txt`

Licence
-------------------------------------------------------------------------------

This suite of programmes is released under the EUPL 1.1 licence. For further
details please consult the LICENCE file.
This suite of programmes is released under the [EUPL 1.1 licence](https://joinup.ec.europa.eu/community/eupl/og_page/introduction-eupl-licence).
For full details please consult the LICENCE file.
8 changes: 4 additions & 4 deletions hex_utils/asc.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def _getNeighbourhoodGridCoords(self, i, j):
ii.append(i-1)
jj.append(j)

if j < self.nrows - 1:
if j < self._nrows - 1:
ii.append(i-1)
jj.append(j+1)

Expand All @@ -99,11 +99,11 @@ def _getNeighbourhoodGridCoords(self, i, j):
ii.append(i)
jj.append(j)

if j < self.nrows - 1:
if j < self._nrows - 1:
ii.append(i)
jj.append(j+1)

if i < self.ncols - 1:
if i < self._ncols - 1:

if j > 0:
ii.append(i+1)
Expand All @@ -112,7 +112,7 @@ def _getNeighbourhoodGridCoords(self, i, j):
ii.append(i+1)
jj.append(j)

if j < self.nrows - 1:
if j < self._nrows - 1:
ii.append(i+1)
jj.append(j+1)

Expand Down
81 changes: 58 additions & 23 deletions hex_utils/hasc.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,21 @@ def init(self, ncols, nrows, xll, yll, side, nodata = "", angle = None):
def _loadHeader(self):

# Mandatory header
self._set_ncols(self._loadHeaderLine(self._file.readline(), self._key_ncols, type(1)))
self._set_nrows(self._loadHeaderLine(self._file.readline(), self._key_nrows, type(1)))
self._xll = self._loadHeaderLine(self._file.readline(), self._key_xll, type(1.0))
self._yll = self._loadHeaderLine(self._file.readline(), self._key_yll, type(1.0))
self._set_side( self._loadHeaderLine(self._file.readline(), self._key_side, type(1.0)))
ncols = self._loadHeaderLine(self._file.readline(), self._key_ncols, type(1))
nrows = self._loadHeaderLine(self._file.readline(), self._key_nrows, type(1))
xll = self._loadHeaderLine(self._file.readline(), self._key_xll, type(1.0))
yll = self._loadHeaderLine(self._file.readline(), self._key_yll, type(1.0))
side = self._loadHeaderLine(self._file.readline(), self._key_side, type(1.0))
# Optional headers
self._nextLine = self._file.readline()
self._nodata = self._loadHeaderLine(self._nextLine, self._key_nodata, type("a"), True)
if self._nodata != "" :
nodata = self._loadHeaderLine(self._nextLine, self._key_nodata, type("a"), True)
if nodata != "" :
self._nextLine = self._file.readline()
self._angle = self._loadHeaderLine(self._nextLine, self._key_angle, type(1.0), True)
if self._angle != None :
angle = self._loadHeaderLine(self._nextLine, self._key_angle, type(1.0), True)
if angle != None :
self._nextLine = self._file.readline()

self.init(ncols, nrows, xll, yll, side, nodata, angle)


def _saveHeader(self, f):
Expand Down Expand Up @@ -111,11 +113,8 @@ def saveAsGML(self, outputFilePath):

newField = ogr.FieldDefn("value", ogr.OFTReal)
outLayer.GetLayerDefn().AddFieldDefn(newField)

# The perpendicular distance from cell center to cell edge
perp = math.sqrt(3) * self._side / 2

# Edge coordinates of an hexagon centered in (x,y) and a side of d:
# Edge coordinates of an hexagon centered in (x,y) having a side of d:
#
# [x-d/2, y+sqrt(3)*d/2] [x+d/2, y+sqrt(3)*d/2]
#
Expand All @@ -125,23 +124,59 @@ def saveAsGML(self, outputFilePath):

for j in range(self._nrows):
for i in range(self._ncols):

x = self._xll + i * 3 * self._side / 2
y = self._yll + j * 2 * perp
y = self._yll + j * 2 * self._hexPerp
if (i % 2) != 0:
y += perp
y += self._hexPerp

polygon = ogr.CreateGeometryFromWkt("POLYGON ((" +
str(x - self._side) + " " + str(y) + ", " +
str(x - self._side / 2) + " " + str(y - perp) + ", " +
str(x + self._side / 2) + " " + str(y - perp) + ", " +
str(x + self._side) + " " + str(y) + ", " +
str(x + self._side / 2) + " " + str(y + perp) + ", " +
str(x - self._side / 2) + " " + str(y + perp) + ", " +
str(x - self._side) + " " + str(y) + "))")
str(x - self._side) + " " + str(y) + ", " +
str(x - self._side / 2) + " " + str(y - self._hexPerp) + ", " +
str(x + self._side / 2) + " " + str(y - self._hexPerp) + ", " +
str(x + self._side) + " " + str(y) + ", " +
str(x + self._side / 2) + " " + str(y + self._hexPerp) + ", " +
str(x - self._side / 2) + " " + str(y + self._hexPerp) + ", " +
str(x - self._side) + " " + str(y) + "))")

outFeature = ogr.Feature(feature_def=outLayer.GetLayerDefn())
outFeature.SetGeometryDirectly(polygon)
outFeature.SetField("value", self._grid[i][self._nrows - j - 1])
outLayer.CreateFeature(outFeature)



def saveAsGeoJSON(self, outputFilePath):

try:
from geojson import Feature, Polygon, FeatureCollection, dump
except ImportError:
raise ImportError(""" ERROR: Could not find the GeoJSON Python library.""")

collection = FeatureCollection([])

for j in range(self._nrows):
for i in range(self._ncols):

x,y = self.getCellCentroidCoords(i, j)

collection.features.append(
Feature(
geometry = Polygon([[
(x - self._side, y ),
(x - self._side / 2, y - self._hexPerp ),
(x + self._side / 2, y - self._hexPerp ),
(x + self._side, y ),
(x + self._side / 2, y + self._hexPerp ),
(x - self._side / 2, y + self._hexPerp ),
(x - self._side, y )
]]),
properties = {"value": self._grid[i][self._nrows - j - 1]}))

with open(outputFilePath, 'w') as fp:
dump(collection, fp)






63 changes: 63 additions & 0 deletions hex_utils/hasc2geojson.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/python3
# coding=utf8
#
# Copyright (c) 2016 - Luís Moreira de Sousa
#
# Transforms ASCII encoded cartographic hexagonal grids [0] into GeoJSON.
# A geometric hexagon is generated for each grid cell and encoded as a feature
# in the output JSON file. The cell value is saved in the 'value' attribute of
# the new feature.
#
# Author: Luís Moreira de Sousa (luis.de.sousa[@]protonmail.ch)
# Date: 11-10-2016
#
# [0] https://github.com/ldesousa/HexAsciiBNF

import sys
from hex_utils.hasc import HASC

def wrongUsage():

print("This programme requires two arguments:\n" +
" - path to an input HASC file \n" +
" - path to the output GeoJSON file \n" +
"Usage example: \n"
" hasc2gml /path/to/input.hasc /path/to/output.json")
sys.exit()


def processArguments(args):

global inputFile
global outputFile

if len(args) < 3:
wrongUsage()
else:
inputFile = str(args[1])
outputFile = str(args[2])


# ----- Main ----- #
def main():

processArguments(sys.argv)

hexGrid = HASC()

try:
hexGrid.loadFromFile(inputFile)
except (ValueError, IOError) as ex:
print("Error loading the grid %s: %s" % (inputFile, ex))
sys.exit()
print ("Loaded input HASC, converting...")

try:
hexGrid.saveAsGeoJSON(outputFile)
except (ImportError, IOError) as ex:
print("Error saving the grid %s: %s" % (inputFile, ex))
sys.exit()
print ("Conversion successfully completed.")

main()

2 changes: 1 addition & 1 deletion hex_utils/surface2asc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
# Creates a rectangular ESRI ASCII grid by sampling a a given surface.
# Usage example:
# surface2asc -x 0 -y 0 -X 2000 -Y 2000 -s 20 -m surfaces.surfaceGaussian -f fun -o output.asc
# surface2asc -x 0 -y 0 -X 2000 -Y 2000 -s 20 -m surfaces.eat2Gaussian -f fun -o output.asc
#
# Author: Luís Moreira de Sousa (luis.de.sousa[@]protonmail.ch)
# Date: 03-06-2016
Expand Down
4 changes: 2 additions & 2 deletions hex_utils/surface2hasc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
#
# Creates an hexagonal ASCII grid [0] by sampling a a given surface.
# Usage examples:
# surface2hasc -x 0 -y 0 -X 2001 -Y 2001 -s 12.4080647880 -m surfaces.surfaceGaussian -f fun -o output.hasc
# surface2hasc -x 0 -y 0 -X 2001 -Y 2001 -s 13.2191028998 -m surfaces.surfaceGaussian -f fun -o output.hasc
# surface2hasc -x 0 -y 0 -X 2001 -Y 2001 -s 12.4080647880 -m surfaces.eat2Gaussian -f fun -o output.hasc
# surface2hasc -x 0 -y 0 -X 2001 -Y 2001 -s 13.2191028998 -m surfaces.eat2Gaussian -f fun -o output.hasc
#
# [0] https://github.com/ldesousa/HexAsciiBNF
#
Expand Down
11 changes: 9 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@

setup(
name = "hex-utils",
version = "0.2",
version = "0.2.2.3",
packages = find_packages(),#['utils'],
install_requires=[],
install_requires=[
'cycler',
'numpy',
'pyparsing',
'python-dateutil',
'pytz',
'six',
],
entry_points={
'console_scripts': [
'hasc2gml=hex_utils.hasc2gml:main',
Expand Down
48 changes: 48 additions & 0 deletions surfaces/channel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'''
Created on 12 Oct 2016
@author: desouslu
'''

import math
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from surfaces.surface import Surface

class Channel(Surface):

angle = 30
slope = 0.25
centre_x = 5
centre_y = 5
centre_z = 5
radius = 0.5
depth = 1


def __init__(self, slope = None):

if slope != None:
self.slope = slope


def fun(self, x, y):

plane = ((self.centre_x - x) * self.slope + self.centre_z) * math.cos(math.radians(self.angle)) + \
((self.centre_y - y) * self.slope + self.centre_z) * math.sin(math.radians(self.angle))

centre = (x - self.centre_x) / math.sin(math.radians(90 - self.angle)) * \
math.sin(math.radians(self.angle))

if (y - self.centre_y) >= (centre - self.radius) and \
(y - self.centre_y) <= (centre + self.radius):
return plane - self.depth
else:
return plane


# Uncomment these lines to test a single pit.
c = Channel()
c.plotWireFrame()

Loading

0 comments on commit 1f7f43d

Please sign in to comment.