Skip to content

Commit

Permalink
Merge pull request #120 from johnkit/lidar-debug
Browse files Browse the repository at this point in the history
Debug/generalize geojson display
  • Loading branch information
johnkit committed Nov 21, 2018
2 parents fd5cf50 + 571bb15 commit 1fe5510
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 18 deletions.
176 changes: 176 additions & 0 deletions docs/examples/lidar_vectors.ipynb
@@ -0,0 +1,176 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['Icon_', 'Ground_Survey_Shapes', 'Contours', 'Water_Shape', 'Indices']"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"\n",
"#\n",
"# IMPORTANT! YOU MUST SET data_dir TO YOUR COPY OF THE LiDAR DATASET!\n",
"#\n",
"\n",
"data_dir = '/home/john/projects/data2models/data/EastRiverWashingtonGulch/LiDAR'\n",
"vectors_dir = os.path.join(data_dir, 'Vectors')\n",
"os.listdir(vectors_dir)\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0. .../Ground_Survey_Shapes/East_River_Washington_Gulch_Ground_Control_Monuments.shp\n",
"1. .../Ground_Survey_Shapes/East_River_Washington_Gulch_Ground_Control_Points.shp\n",
"2. .../Ground_Survey_Shapes/East_River_Washington_Gulch_Ground_Check_Points.shp\n",
"3. .../Contours/WAG_371.shp\n",
"4. .../Contours/WAG_025.shp\n",
"5. .../Contours/WAG_255.shp\n",
"6. .../Contours/WAG_004.shp\n",
"7. .../Contours/WAG_014.shp\n",
"8. .../Contours/WAG_003.shp\n",
"9. .../Contours/WAG_015.shp\n",
"10. .../Contours/WAG_352.shp\n",
"11. .../Contours/WAG_353.shp\n",
"12. .../Contours/WAG_003 (1).shp\n",
"13. .../Water_Shape/East_River_Washington_Gulch_Water_Breaklines.shp\n",
"14. .../Indices/East_River_Washington_Gulch_Boundary.shp\n",
"15. .../Indices/East_River_Washington_Gulch_Tile_Index.shp\n"
]
}
],
"source": [
"import glob\n",
"\n",
"pattern = '{}/**/*.shp'.format(vectors_dir)\n",
"# for filename in glob.iglob(pattern, recursive=True):\n",
"# print(filename)\n",
"shp_files = list(glob.iglob(pattern, recursive=True))\n",
"n = len(vectors_dir) + 1\n",
"for i,path in enumerate(shp_files):\n",
" print('{}. .../{}'.format(i, path[n:]))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import gaia\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "827ca39f0b854276b356aac5b3af9078",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"scene(center={'y': 0.0, 'x': 0.0}, layout=Layout(align_self='stretch', height='400px'))"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"monuments = gaia.create(shp_files[0])\n",
"wag371 = gaia.create(shp_files[3])\n",
"breaklines = gaia.create(shp_files[13])\n",
"boundary = gaia.create(shp_files[14])\n",
"tile_index = gaia.create(shp_files[15])\n",
"\n",
"scene = gaia.show([monuments, wag371, breaklines, boundary, tile_index])\n",
"display(scene)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# Add zoom slider\n",
"import ipywidgets as widgets\n",
"z = widgets.FloatSlider(min=1, max=18, value=scene.zoom, layout=dict(width='95%'))\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c6922f201160406cbf8c244102c68dcf",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"FloatSlider(value=11.058348, layout=Layout(width='95%'), max=18.0, min=1.0)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"newlink = widgets.jslink((z, 'value'), (scene, 'zoom'))\n",
"display(z)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
56 changes: 41 additions & 15 deletions gaia/display/pygeojs_adapter.py
Expand Up @@ -11,6 +11,8 @@
except ImportError:
IS_PYGEOJS_LOADED = False

import geopandas

import gaia.types
from gaia.util import GaiaException

Expand Down Expand Up @@ -53,12 +55,44 @@ def show(data_objects, **options):
combined_bounds = None
# Reverse order so that first item ends on top
for data_object in reversed(data_objects):
# Get bounds, in order to compute overall bounds
meta = data_object.get_metadata()
# print(meta)
meta_bounds = meta.get('bounds').get('coordinates')[0]
# print(meta_bounds)
assert meta_bounds, 'data_object missing bounds'
if data_object._getdatatype() == gaia.types.VECTOR:
# print('Adding vector object')
# Special handling for vector datasets:
# First, make a copy of the geopandas frame
df = geopandas.GeoDataFrame.copy(data_object.get_data())

# Convert to lon-lat if needed
epsg = data_object.get_epsg()
if epsg != '4236':
df[df.geometry.name] = df.geometry.to_crs(epsg='4236')

# Strip any z coordinates (force to z = 1)
df.geometry = df.geometry.scale(zfact=0.0).translate(zoff=1.0)
# df.to_file('/home/john/temp/df.pandas')
# print(df)
# print(df.geometry)

# Calculate bounds
geopandas_bounds = df.geometry.total_bounds
xmin, ymin, xmax, ymax = geopandas_bounds
meta_bounds = [
[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]
]

# Add map feature
if feature_layer is None:
feature_layer = scene.createLayer('feature')

# Use __geo_interface__ to get the geojson
feature_layer.readGeoJSON(df.__geo_interface__)
# print(df.__geo_interface__)
else:
# Get bounds, in order to compute overall bounds
meta = data_object.get_metadata()
# print(meta)
meta_bounds = meta.get('bounds').get('coordinates')[0]
# print(meta_bounds)
assert meta_bounds, 'data_object missing bounds'

# Bounds format is [xmin, ymin, xmax, ymax]
bounds = [
Expand Down Expand Up @@ -120,15 +154,7 @@ def show(data_objects, **options):
data_object._getdatatype()))

elif data_object._getdatatype() == gaia.types.VECTOR:
# print('Adding vector object')
if feature_layer is None:
feature_layer = scene.createLayer('feature')

# Use get_data() to get the GeoPandas object
data = data_object.get_data()
# Then use __geo_interface__ to get the geojson
feature_layer.readGeoJSON(data.__geo_interface__)

pass # vector objects handled above
else:
msg = 'Cannot display dataobject, type {}'.format(
data_object.__class__.__name__)
Expand Down
16 changes: 15 additions & 1 deletion gaia/gaia_data.py
Expand Up @@ -46,10 +46,24 @@ def get_epsg(self):
return self._epsg

def reproject(self, epsg):
repro = geopandas.GeoDataFrame.copy(self._data)
repro = geopandas.GeoDataFrame.copy(self.get_data())
repro[repro.geometry.name] = repro.geometry.to_crs(epsg=epsg)
repro.crs = fiona.crs.from_epsg(epsg)
self._data = repro
self._epsg = epsg

# Recompute bounds
geometry = repro['geometry']
geopandas_bounds = geometry.total_bounds
xmin, ymin, xmax, ymax = geopandas_bounds
coords = [[
[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]
]]
metadata = self.get_metadata()
bounds = metadata.get('bounds', {})
bounds['coordinates'] = coords
metadata['bounds'] = bounds
self.set_metadata(metadata)

def _getdatatype(self):
if not self._datatype:
Expand Down
4 changes: 2 additions & 2 deletions gaia/io/geojson_reader.py
Expand Up @@ -38,8 +38,8 @@ def can_read(url, *args, **kwargs):
if not isinstance(url, string_types):
return False

extension = get_uri_extension(url)
if extension == 'geojson':
extension = '.{}'.format(get_uri_extension(url))
if extension in formats.VECTOR:
return True
return False

Expand Down

0 comments on commit 1fe5510

Please sign in to comment.