Skip to content
Browse files

Implemented searching algorithm instead of ManyToManyField, but found…

… new problem: more than one cell at a specific zoom, x, and y are being created.
  • Loading branch information...
1 parent d376762 commit c60605e2fc534a7ba8e6fc2c8bb5e460ef4465f9 @jrasky jrasky committed May 28, 2012
Showing with 63 additions and 24 deletions.
  1. +52 −12 geocamLayer/models.py
  2. +1 −2 geocamLayer/noaaExampleParser.py
  3. +5 −7 geocamLayer/quadTree.py
  4. +5 −3 geocamLayer/views.py
View
64 geocamLayer/models.py
@@ -48,8 +48,6 @@ class Feature(BaseFeature):
name = models.CharField(max_length=80)
description = models.TextField()
cell = models.ForeignKey('QuadTreeCell', null=True, blank=True)
- # primary key because
- pkey = models.FloatField(primary_key=True)
def __unicode__(self):
return u'Feature "%s" (%.6f, %.6f)' % (self.name, self.lng, self.lat)
@@ -63,7 +61,6 @@ def randomFeature():
feature.timespan = random.randint(0,3)
feature.name = "Random Feature"
feature.description = "Random Feature"
- feature.pkey = random.random()
return feature
def getPosition(self): return (self.lng,self.lat)
@@ -87,10 +84,6 @@ class QuadTreeCell(models.Model):
south = models.FloatField(null=True, blank=True)
east = models.FloatField(null=True, blank=True)
north = models.FloatField(null=True, blank=True)
- # many-to-many for features
- features = models.ManyToManyField("Feature")
- # primary key because we need one
- pkey = models.FloatField(primary_key=True)
class Meta:
ordering = ('zoom', 'x', 'y')
@@ -111,16 +104,66 @@ def getIndexAtLonLat(zoom, lonLat):
return (zoom, x, y)
@staticmethod
+ def getLonLatAtIndex(zoom, x, y):
+ size = QuadTreeCell.getSizeForZoom(zoom)
+ lng = float((x * size) + (-180))
+ lat = float((y * size) + (-90))
+ return (zoom, lng, lat)
+
+ @staticmethod
def getCellAtIndex(coords):
- zoom, x, y = coords
- cell, _created = QuadTreeCell.objects.get_or_create(zoom=zoom, x=x, y=y, pkey=random.random())
+ assert(isinstance(coords, (list,tuple)))
+ zoom, x, y = [int(x) for x in coords]
+ cell, _created = QuadTreeCell.objects.get_or_create(zoom=zoom, x=x, y=y)
+ if _created:
+ print "didn't find cell %s/%s/%s" % (zoom, x, y)
+ cell.isLeaf = True
return cell
@staticmethod
def getCellAtLonLat(zoom, lonLat):
return (QuadTreeCell.getCellAtIndex
(QuadTreeCell.getIndexAtLonLat(zoom, lonLat)))
+ @staticmethod
+ def getCellsUnderIndex(zoom, x, y):
+ cell = QuadTreeCell.getCellAtIndex(zoom, (x, y))
+ if cell.isLeaf: return None
+ cells = []
+ zoom, lng, lat = QuadTreeCell.getLonLatAtIndex(zoom, (x, y))
+ size = QuadTreeCell.getSizeForZoom(zoom)
+ cells.append(QuadTreeCell.getCellAtLonLat(zoom+1, (lng,lat)))
+ cells.append(QuadTreeCell.getCellAtLonLat(zoom+1, (lng+size,lat)))
+ cells.append(QuadTreeCell.getCellAtLonLat(zoom+1, (lng,lat+size)))
+ cells.append(QuadTreeCell.getCellAtLonLat(zoom+1, (lng+size,lat+size)))
+ return cells
+
+ @staticmethod
+ def getLeavesUnderLonLat(zoom, lonLat):
+ cell = QuadTreeCell.getCellAtLonLat(zoom, lonLat)
+ if cell.isLeaf: return [cell]
+ lng, lat = lonLat
+ cells = []
+ size = QuadTreeCell.getSizeForZoom(zoom)
+ cells.extend(QuadTreeCell.getLeavesUnderLonLat(zoom+1, (lng,lat)))
+ cells.extend(QuadTreeCell.getLeavesUnderLonLat(zoom+1, (lng+size,lat)))
+ cells.extend(QuadTreeCell.getLeavesUnderLonLat(zoom+1, (lng,lat+size)))
+ cells.extend(QuadTreeCell.getLeavesUnderLonLat(zoom+1, (lng+size,lat+size)))
+ return cells
+
+ @staticmethod
+ def getLeavesUnderIndex(zoom, x, y):
+ zoom, lng, lat = QuadTreeCell.getLonLatAtIndex(zoom, x, y)
+ return QuadTreeCell.getLeavesUnderLonLat(zoom, (lng,lat))
+
+ @staticmethod
+ def getFeaturesFromCells(cells):
+ features = []
+ for cell in cells:
+ # there's probably a faster way to do this
+ features.extend(Feature.objects.filter(cell=cell))
+ return features
+
def getSize(self):
return QuadTreeCell.getSizeForZoom(self.zoom)
@@ -150,9 +193,6 @@ def updateStats(self, feature):
self.north = feature.lat
self.count += 1
- self.save()
- feature.save()
- self.features.add(feature)
def getDiameter(self):
if self.count:
View
3 geocamLayer/noaaExampleParser.py
@@ -42,5 +42,4 @@ def readNoaaWeatherStations(fname):
yield Feature(lat=parseLatitude(stationLatitude),
lng=parseLongitude(stationLongitude),
name=placeName,
- description=countryName,
- pkey=random.random())
+ description=countryName)
View
12 geocamLayer/quadTree.py
@@ -31,7 +31,7 @@ def getCellAtIndex(self, index):
cell = self.cells[index]
else:
zoom, x, y = index
- cell = self.cells.setdefault(index, QuadTreeCell(zoom=zoom, x=x, y=y, pkey=random.random()))
+ cell = self.cells.setdefault(index, QuadTreeCell(zoom=zoom, x=x, y=y))
return cell
def getCellAtLonLat(self, zoom, lonLat):
@@ -42,15 +42,13 @@ def addFeature(self, feature):
def addFeatureToCell(self, feature, cell):
cell.updateStats(feature)
- cell.save()
- feature.save()
if cell.isLeaf:
feature.cell = cell
self.features.append(feature)
- #if not hasattr(cell, 'features'):
- # cell.features = []
- cell.features.add(feature)
+ if not hasattr(cell, 'features'):
+ cell.features = []
+ cell.features.append(feature)
if cell.count >= MAX_FEATURES_PER_CELL and cell.zoom < MAX_ZOOM - 1:
self.splitCell(cell)
@@ -64,7 +62,7 @@ def addFeatureToZoom(self, feature, zoom):
def splitCell(self, cell):
cell.isLeaf = False
- for feature in cell.features.all():
+ for feature in cell.features:
self.addFeatureToZoom(feature, cell.zoom + 1)
@transaction.commit_manually
View
8 geocamLayer/views.py
@@ -27,10 +27,12 @@ def main(request):
return HttpResponseRedirect('/static/geojsontest.html')
def quadTree(request, zoom, x, y):
- top_coords = (0,x,y)
+ zoom = float(zoom)
+ x = float(x)
+ y = float(y)
+ top_coords = (zoom,x,y)
top_cell = QuadTreeCell.getCellAtIndex(top_coords)
- features = Feature.objects.all().filter(cell=top_cell)
- print top_cell.features.all()
+ features = QuadTreeCell.getFeaturesFromCells(QuadTreeCell.getLeavesUnderIndex(zoom, x, y))
print "Got %s features (should be %s)" % (len(features), top_cell.count)
return HttpResponse('{}');

0 comments on commit c60605e

Please sign in to comment.
Something went wrong with that request. Please try again.