Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
Pushbroom Planner is a Python3 gui application that generates flight paths
for aircraft carrying pushbroom scanners.
## Installation
The installation of this package requires both Python3 and pip3. Python3 comes
with Ubuntu by default, but pip3 must be installed from the package manager
via `sudo apt install python3-pip`. On Windows, Python3 and pip3 can be
downloaded and installed from [the Python website](https://www.python.org/).

The installation of this package requires both Python3 and pip3. It's
currently targeted at Python 3.7. Python3 comes with Ubuntu by default,
but pip3 must be installed from the package manager via `sudo apt install
python3-pip`. On Windows, Python3 and pip3 can be downloaded and installed
from [the Python website](https://www.python.org/).

If using this application in production as a stand alone program, it's best
to put it in a Python virtual environement, ie: `python3.7 -m venv
ScanlineFlightPlanner` and then `. ScanFlightPlanner/bin/activate`.
After installing Python3 and downloading this package, just navigate to the
directory of this README and run the command `pip3 install .` A script called
`scan_route_plotter` will be added in your `$PATH`, running this script will
Expand Down
152 changes: 95 additions & 57 deletions RoutePlotter/SHPParse.py
Original file line number Diff line number Diff line change
@@ -1,108 +1,146 @@
import shapefile
import os

SHAPE_TYPES={'Polygon':5,'Point':1}
KEYS = 'lon','lat'
SHAPE_TYPES = {'Polygon': 5, 'Point': 1}
KEYS = 'lon', 'lat'


def findPointCoords(shpfile):
shpf = shapefile.Reader(shpfile)
coords = []
for shape in shpf.shapes():
if shape.shapeType == SHAPE_TYPES['Point']:
coords.append(dict(zip(KEYS,shape.points[0])))
coords.append(dict(zip(KEYS, shape.points[0])))
return coords


def findPolyCoords(shpfile):
shpf = shapefile.Reader(shpfile)
coords = []
for shape in shpf.shapes():
if shape.shapeType == SHAPE_TYPES['Polygon']:
coords+=[[dict(zip(KEYS,p))for p in shape.points]]
coords += [[dict(zip(KEYS, p)) for p in shape.points]]
return coords

def findRegionType(shpfile,types_to_check=("Polygon","Point")):

def findRegionType(shpfile, types_to_check=("Polygon", "Point")):
shpf = shapefile.Reader(shpfile)
for shape in shpf.shapes():
for t in types_to_check:
if shape.shapeType == SHAPE_TYPES[t]:
return t
return None


def findMeta(shpfile):
shpf = shapefile.Reader(shpfile)
keys = [key[0] for key in shpf.fields[1:]]
out = {key:[] for key in keys}
out = {key: [] for key in keys}
for record in shpf.records():
for idx,value in enumerate(record):
for idx, value in enumerate(record):
out[keys[idx]].append(value)
return out

def coordDictListToCoord2DList(coord_dict_list,alt=0):
coords = list(map(lambda c:[c['lon'],c['lat'],alt],coord_dict_list))
nested_coords = [[p1,p2]for p1,p2 in zip(coords[::2],coords[1::2])]

def coordDictListToCoord2DList(coord_dict_list, alt=0):
coords = list(map(lambda c: [c['lon'], c['lat'], alt], coord_dict_list))
nested_coords = [[p1, p2] for p1, p2 in zip(coords[::2], coords[1::2])]
return [coords]


def planOutlineFromCoords(fname,regions,alt,approach,bearing,sidelap,
inst,names,vehic='fullscale',units='US'):
polyw = shapefile.Writer(shapefile.POLYGON)
polyw.field('name','C',40)
polyw.field('alt','F',12)
polyw.field('approach','F',12)
polyw.field('bearing','F',12)
polyw.field('sidelap','F',12)
polyw.field('inst','C',40)
polyw.field('frame','S',6)
polyw.field('fov','S',8)
polyw.field('ifov','S',8)
polyw.field('pixels','F',10)
polyw.field('vehicle','C',20)
polyw.field('units','C',10)
for area,name in zip(regions,names):
bounds = coordDictListToCoord2DList(area,0)
polyw.poly(parts=bounds)
def planOutlineFromCoords(fname, regions, alt, approach, bearing, sidelap,
inst, names, vehic='fullscale', units='US', starttrig=0.5, endtrig=0.5):
polyw = shapefile.Writer(fname, shapeType=shapefile.POLYGON)
polyw.field('name', 'C', 40)
polyw.field('alt', 'F', 12)
polyw.field('approach', 'F', 12)
polyw.field('bearing', 'F', 12)
polyw.field('sidelap', 'F', 12)
polyw.field('inst', 'C', 40)
polyw.field('frame', 'S', 6)
polyw.field('fov', 'S', 8)
polyw.field('ifov', 'S', 8)
polyw.field('pixels', 'F', 10)
polyw.field('vehicle', 'C', 20)
polyw.field('units', 'C', 10)
polyw.field('trigstart', 'F', 6, 2)
polyw.field('trigend', 'F', 6, 2)
for area, name in zip(regions, names):
bounds = coordDictListToCoord2DList(area, 0)
polyw.poly(bounds)
#polyw.poly(parts=bounds)
polyw.record(
name,
alt,
approach,
bearing,
sidelap*100,
sidelap * 100,
inst.name,
inst.frame,
inst.fieldOfView,
inst.crossFieldOfView,
inst.pixels,
vehic,
units
units,
starttrig,
endtrig
)
polyw.save(fname)

def flightPlanFromCoords(outpath,coords,scanlinebounds,alt,speed):
#polyw.save(fname)
polyw.close()
#TODO: alt and speed do not seem to be used in writing shp files?
def flightPlanFromCoords(outpath, coords, scanlinebounds, alt, speed, trigcoords=None):
if not os.path.isdir(outpath):
os.makedirs(outpath)
linew = shapefile.Writer(shapefile.POLYLINE)
linew.field('idx','N',10)
footw = shapefile.Writer(shapefile.POLYGON)
footw.field('idx','N',10)
pointw = shapefile.Writer(shapefile.POINT)
pointw.field('idx','N',10)
pointw.field('type','C',40)
for i in range(int(len(coords)/4)):
#write the scan area first
bounds = coordDictListToCoord2DList(scanlinebounds[i],0)
footw.poly(parts=bounds)
footw.record(str(i),'Scanline Bounds')
#then the flight line
line=coordDictListToCoord2DList(coords[4*i:4*i+4])
linew.poly(parts=line,shapeType=shapefile.POLYLINE)
linew = shapefile.Writer(os.path.join(outpath, 'scanlines'), shapeType=shapefile.POLYLINEZ)
linew.field('idx', 'N', 10)
footw = shapefile.Writer(os.path.join(outpath, 'footprints'), shapeType=shapefile.POLYGONZ)
footw.field('idx', 'N', 10)
pointw = shapefile.Writer(os.path.join(outpath, 'points'), shapeType=shapefile.POINTZ)
pointw.field('idx', 'N', 10)
pointw.field('type', 'C', 40)

trigpointsw = None
triglinesw = None
if trigcoords:
trigpointsw = shapefile.Writer(os.path.join(outpath, 'trigger_points'), shapeType=shapefile.POINTZ)
triglinesw = shapefile.Writer(os.path.join(outpath, 'trigger_lines'), shapeType=shapefile.POLYLINEZ)

trigpointsw.field('idx', 'N', 10)
trigpointsw.field('type', 'C', 40)

triglinesw.field('idx', 'N', 10)

for i in range(int(len(coords) / 4)):
# write the scan area first
bounds = coordDictListToCoord2DList(scanlinebounds[i], 0)
#footw.poly(parts=bounds)
footw.polyz(bounds)
footw.record(str(i), 'Scanline Bounds')
# then the flight line
line = coordDictListToCoord2DList(coords[4 * i:4 * i + 4])
#linew.poly(parts=line, shapeType=shapefile.POLYLINE)
linew.linez(line)
linew.record(i)
#then the start/end/entry/exit points of the flight line
pointw.point(*line[0][0])
pointw.point(*line[0][1])
pointw.point(*line[0][2])
pointw.point(*line[0][3])
[pointw.record(i,p)for p in["START","ENTER","EXIT","END"]]
# then the start/end/entry/exit points of the flight line
pointw.pointz(*line[0][0])
pointw.pointz(*line[0][1])
pointw.pointz(*line[0][2])
pointw.pointz(*line[0][3])
[pointw.record(i, p) for p in ["START", "ENTER", "EXIT", "END"]]

if trigcoords:
trigline = coordDictListToCoord2DList(trigcoords[i])
triglinesw.linez(trigline)
triglinesw.record(i)

linew.save(os.path.join(outpath,'scanlines'))
footw.save(os.path.join(outpath,'footprints'))
pointw.save(os.path.join(outpath,'points'))
trigpointsw.pointz(*trigline[0][0])
trigpointsw.pointz(*trigline[0][1])
for p in ["START","END"]:
trigpointsw.record(i,p)

linew.close()
footw.close()
pointw.close()
if trigcoords:
triglinesw.close()
trigpointsw.close()
Loading