Browse files

added functions, improved existing ones

  • Loading branch information...
1 parent 521dc18 commit 8a52268a3759d78f04690909a5cde55644cfd339 jyrome.112@gmail.com committed Apr 18, 2012
View
27 geocamLayer/management/commands/cleardb.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+from django.core.management.base import BaseCommand, CommandError
+from django.db import transaction
+from geocamLayer import models
+import sys
+
+class Command(BaseCommand):
+ args = ""
+ help = "This command clears the database of existing points"
+
+ @transaction.commit_manually
+ def handle(self, *args, **options):
+ self.stdout.write("Getting all objects...\n")
+ features = list(models.Feature.objects.all())
+ self.stdout.write("%s objects in total\n" % len(features))
+ numpoints = len(features)
+ self.stdout.write("Deleting all objects...\n")
+ for i,point in enumerate(features):
+ self.stdout.write('\r')
+ self.stdout.write(str(int((float(i)/numpoints)*100)))
+ self.stdout.write('%')
+ self.stdout.flush()
+ point.delete()
+ self.stdout.write('\nCommitting...\n')
+ transaction.commit()
+ self.stdout.write('Done.\n')
+
View
16 geocamLayer/management/commands/clearstruct.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+from django.core.management.base import BaseCommand, CommandError
+from django.conf import settings
+import os, os.path, shutil
+
+class Command(BaseCommand):
+ args = ""
+ help = "This command deletes an existing file structure for points"
+
+ root = os.path.join(settings.MEDIA_ROOT, "tiles")
+
+ def handle(self, *args, **options):
+ self.stdout.write("Clearing existing files...\n")
+ if os.path.exists(self.root):
+ shutil.rmtree(self.root)
+ self.stdout.write("Done.\n")
View
2 geocamLayer/management/commands/refreshdb.py
@@ -40,5 +40,7 @@ def handle(self, *args, **options):
feature = Feature.randomFeature()
feature.save()
print
+ print "Committing..."
transaction.commit()
+ print "Done."
sys.stdout = stdout
View
141 geocamLayer/management/commands/restruct.py
@@ -2,21 +2,27 @@
from django.core.management.base import BaseCommand, CommandError
from geocamLayer import models
from django.conf import settings
-import os, os.path, math, json
+from optparse import make_option
+import os, os.path, shutil, math, json, datetime, random
try: import cPickle as pickle
except ImportError: import pickle
CELLS_PER_TILE = 10
+NUMBER_ZOOMS = 10
class Cluster(object):
- def __init__(self):
+ def __init__(self, finalZoom = False):
self.numPoints = 0
self.xSum, self.ySum = 0,0
self.south = self.west = self.east = self.north = None
+ self.points = []
+ self.finalZoom = finalZoom
def add_point(self, point):
self.numPoints += 1
+ if self.numPoints == 1 or self.finalZoom:
+ self.points.append(point)
x, y = point.getPosition()
self.xSum += x
self.ySum += y
@@ -30,31 +36,67 @@ def add_point(self, point):
self.north = y
def get_json(self):
- return {'type': 'Feature',
- 'geometry': {
- 'type': 'Point',
- 'coordinates': [
- self.xSum / float(self.numPoints),
- self.ySum / float(self.numPoints),
- ],
- },
- 'properties': {
- 'subtype': 'Cluster',
- 'numPoints': self.numPoints,
- 'bbox': [self.west, self.south, self.east, self.north],
- }
- }
+ data = []
+ if self.numPoints > 1 and not self.finalZoom:
+ data.append({'type': 'Feature',
+ 'geometry': {
+ 'type': 'Point',
+ 'coordinates': [
+ self.xSum / float(self.numPoints),
+ self.ySum / float(self.numPoints),
+ ],
+ },
+ 'properties': {
+ 'subtype': 'Cluster',
+ 'numPoints': self.numPoints,
+ 'bbox': [self.north, self.east, self.south, self.west],
+ }
+ }
+ )
+ for point in self.points:
+ data.append({'type': 'Feature',
+ 'geometry': {
+ 'type': 'point',
+ 'coordinates': [
+ point.getPosition()[0],
+ point.getPosition()[1],
+ ],
+ },
+ 'properties': {
+ 'subtype': 'point',
+ 'timestamp': str(point.getTimeStamp()),
+ 'timespan': str(point.getTimeSpan()),
+ 'name': point.getName(),
+ 'description': point.getDescriptionHTML()
+ }
+ }
+ )
+
+ return data
class Command(BaseCommand):
args = ""
help = "This command restructures the json data"
+
+ option_list = BaseCommand.option_list + (
+ make_option('--clear',
+ action="store_true",
+ dest="clear_files",
+ default=False,
+ help="Delete directory structure before writing out (be careful!)"
+ ),
+ make_option('--noaa', dest="noaaFile",
+ help="Uses noaa file instead of database",
+ metavar="FILE", default=None),
+ )
+
root = os.path.join(settings.MEDIA_ROOT, "tiles")
tiles = {}
def process_point(self, point):
lng,lat = point.getPosition()
- for zoom in xrange(10):
+ for zoom in xrange(NUMBER_ZOOMS):
# fragment this
xf = float(lng + 180) / (360. / (2**(zoom+1)))
yf = float(lat + 90) / (360. / (2**(zoom+1)))
@@ -71,23 +113,82 @@ def process_point(self, point):
for y in range(int(ymin),int(ymax+1)):
tile_file = os.path.join(tile_path, str(y)+'.json')
tile = self.tiles.get(tile_file, {})
- cell = tile.setdefault((xcell,ycell),Cluster())
+ cell = tile.setdefault((xcell,ycell),Cluster(finalZoom=True if zoom == NUMBER_ZOOMS-1 else False))
cell.add_point(point)
self.tiles[tile_file] = tile
def write_out(self):
for tile_file, tile in self.tiles.iteritems():
clusters = []
for pos, cluster in tile.iteritems():
- clusters.append(cluster.get_json())
+ clusters.extend(cluster.get_json())
data = {'type': 'FeatureCollection',
'features': clusters}
json.dump(data, open(tile_file,'w'), sort_keys=True, indent=4)
+ def clear_files(self):
+ if os.path.exists(self.root):
+ shutil.rmtree(self.root)
+
+ def parseDegrees(self, data, positiveDirection):
+ direction = data[-1]
+ direction = 1 if direction == positiveDirection else -1
+ data = data[:-1]
+ fields = [float(x) for x in data.split('-')]
+ degrees, minutes = fields[:2]
+ val = degrees + minutes / 60.0
+ if len(fields) == 3:
+ seconds = fields[2]
+ val += seconds / 3600.0
+ return direction * val
+
+ def parseLatitude(self, latStr):
+ return self.parseDegrees(latStr, 'N')
+
+ def parseLongitude(self, latStr):
+ return self.parseDegrees(latStr, 'E')
+
+ def get_database_objects(self):
+ return models.Feature.objects.all()
+
+ def get_noaa_objects(self, fname):
+ assert(os.path.exists(fname))
+ features = []
+
+ for line in open(fname):
+ data = line.strip().split(';')
+
+ blockNumber, stationNumber, ICAOLocation, placeName,\
+ state, countryName, WMORegion, stationLatitude,\
+ stationLongitude, upperAirLatitude, upperAirLongitude,\
+ stationElevation, upperAirElevation, RBSNIndicator\
+ = data
+
+ stationLatitude = self.parseLatitude(stationLatitude)
+ stationLongitude = self.parseLongitude(stationLongitude)
+
+ feature = models.Feature()
+ feature.lat = stationLatitude
+ feature.lng = stationLongitude
+ feature.timestamp = datetime.datetime.now()
+ feature.timespan = random.randint(0,3)
+ feature.name = placeName
+ feature.description = countryName
+
+ features.append(feature)
+
+ return features
+
def handle(self, *args, **options):
self.stdout.write("Getting all objects...\n")
- features = models.Feature.objects.all()
+ if options['noaaFile'] is not None:
+ features = self.get_noaa_objects(options['noaaFile'])
+ else:
+ features = self.get_database_objects()
self.stdout.write("%s objects in total\n" % len(features))
+ if options['clear_files']:
+ self.stdout.write("Clearing existing files...\n")
+ self.clear_files()
self.stdout.write("Clustering...\n")
for point in features:
self.process_point(point)
View
57 geocamLayer/static/geocamLayer/static_tiles.js
@@ -5,6 +5,9 @@ function initialize() {
window.points = new Array();
window.bboxes = new Object();
window.conn = null;
+ window.currentZoom = null;
+ window.currentX = new Array();
+ window.currentY = new Array();
//window.updating = false;
//window.concurent = false;
@@ -63,20 +66,25 @@ function boundsChanged() {
zoom = Math.ceil(Math.log(360/size)/Math.log(2));
if (isNaN(zoom)) zoom = 1;
- tile_size = 360/Math.pow(2,zoom)
+ tile_size = 360/Math.pow(2,zoom);
- west_x = Math.floor((west-(-180))/tile_size)
- south_y = Math.floor((south-(-90))/tile_size)
- east_x = Math.ceil((east-(-180))/tile_size)
- north_y = Math.ceil((east-(-180))/tile_size)
+ x = Math.floor((west-(-180))/tile_size)*2;
+ y = Math.floor((south-(-90))/tile_size)*2;
- clearPoints();
+ if (currentZoom != zoom) {
+ clearPoints();
+ currentZoom = zoom;
+ }
- for (x=west_x; x < east_x; x++) {
- for (y=south_y; y < north_y; y++) {
- loadTile(zoom,x,y);
- }
+ if (currentZoom != zoom ||
+ currentX.indexOf(x) == -1 ||
+ currentY.indexOf(y) == -1
+ ) {
+ loadTile(zoom,x,y);
+ currentX[currentX.length] = x;
+ currentY[currentY.length] = y;
}
+
}
function loadTile(zoom,x,y) {
@@ -93,6 +101,8 @@ function clearPoints() {
}
points = new Array();
bboxes = new Object();
+ currentX = new Array();
+ currentY = new Array();
}
function processTile() {
@@ -111,16 +121,21 @@ function processTile() {
for (x in parsed['features']) {
cluster = parsed['features'][x];
pos = cluster['geometry']['coordinates'].toString().split(',');
- marker = new google.maps.Marker({position:new google.maps.LatLng(pos[0], pos[1]), map:map, clickable:true, icon:new google.maps.MarkerImage(url='/static/arrow.png')});
- bboxes[new google.maps.LatLng(pos[0], pos[1])] = cluster['properties']['bbox'];
- google.maps.event.addListener(marker,"click",function(event){
- clearPoints();
- bbox = bboxes[event.latLng];
- bounds = new google.maps.LatLngBounds(new google.maps.LatLng(bbox[0],bbox[1]),
- new google.maps.LatLng(bbox[2],bbox[3]));
- map.fitBounds(bounds);
- }
- );
- points[points.length] = marker;
+ if (cluster['properties']['subtype'] == 'point') {
+ marker = new google.maps.Marker({position:new google.maps.LatLng(pos[0], pos[1]), map:map});
+ points[points.length] = marker;
+ } else {
+ marker = new google.maps.Marker({position:new google.maps.LatLng(pos[0], pos[1]), map:map, clickable:true, icon:new google.maps.MarkerImage(url='/static/arrow.png')});
+ bboxes[new google.maps.LatLng(pos[0], pos[1])] = cluster['properties']['bbox'];
+ google.maps.event.addListener(marker,"click",function(event){
+ bbox = bboxes[event.latLng];
+ console.log(bbox);
+ bounds = new google.maps.LatLngBounds(new google.maps.LatLng(bbox[0],bbox[1]),
+ new google.maps.LatLng(bbox[2],bbox[3]));
+ map.fitBounds(bounds);
+ }
+ );
+ points[points.length] = marker;
+ }
}
}

0 comments on commit 8a52268

Please sign in to comment.