This is pretty cool, but you're right that it may lead to exploding
indexes, something that someone pointed out was a weakness in the
strategy I built, so I modified it to save only the saved point's own
grid square, but then on the query, I search all the neighboring grid
squares.  Since you shared, so will I:

class SaveLocation(webapp.RequestHandler):
  def get(self):

    from math import floor

    address = cgi.escape(self.request.get('address'))
    lattitude,longitude =
cgi.escape(self.request.get('point')).split(',')

    mLat = int(floor(float(lattitude)*10))
    mLon = int(floor(float(longitude)*10))
    token = str(mLon)+','+str(mLat)

    save = SaveLocation(longitude = float(longitude),
                        lattitude = float(lattitude),
                        address = address,
                        region = token).put()

    self.response.headers['Content-Type'] = 'text/xml'
    self.response.out.write('<response><note>Location Saved</note></
response>')

class GetLocations(webapp.RequestHandler):

  def get(self):
    from math import floor

    lattitude,longitude =
cgi.escape(self.request.get('point')).split(',')
    mLon = int(floor(float(longitude)*10))
    mLat = int(floor(float(lattitude)*10))
    offsets = [(-1,-1), (-1,0), (-1,1),
                   (0, -1), (0,0), (0,1),
                   (1,-1), (1,0), (1,1)]

    locList = '<response>'

    for (i, j) in offsets:
      token = str(mLon+i)+','+str(mLat+j)


      now = date.today()
      yesterday = date(now.year, now.month, now.day-1)

      lat = db.GqlQuery("SELECT * FROM SaveLocation " +
                        "WHERE region=:1 ORDER BY date",
                        token)
      lats = lat.fetch(100)

      for location in lats:
       if location.date >= yesterday:
        if location.longitude < float(longitude) + 0.14 and
location.longitude > \
           float(longitude) - 0.14:
          locList = locList + '<sale><lattitude>' +
str(location.lattitude) + \
          '</lattitude><longitude>' + str(location.longitude) + \
          '</longitude><address>' + str(location.address) + '</
address></sale>'
    locList = locList + '</response>'

    self.response.headers['Content-Type'] = 'text/xml'
    self.response.out.write(locList)

As you can see, the GAE app outputs XML that's used by JS on the page
to display the contact as appropriate.

-B



On Sep 10, 12:47 pm, Nevin Freeman <[EMAIL PROTECTED]> wrote:
> Since starting this thread, I've come up with something slightly
> similar to what you are suggesting here. Rather than store metadata
> about both lat and lng, I store a ListProperty of lngs to differing
> degrees of accuracy, and still use inequalities for latitude. So if
> you have a point with Lat, Lng = 12.12345678, 40.12345678, my stored
> "lng-list" property would look like: [40, 40.1, 40.12, 40.123]. This
> way, based on zoom level (well, actually just based on the size of the
> viewport, calculated when the query is run), I can query for all of
> the strips of longitude within my viewport, and then still include a
> minLat < lat < minLng. This results in a single query up front, but
> multiple queries behind the scenes, since the viewport will have many
> longitude strips and thus I will be comparing the lng-list to an array
> of values. I decide how to divide up the viewport based on the
> difference in longitude between either edge, and limit the number of
> strips to 10 (using the larger strips in order to decrease the
> number). Here is the code for "encoding" and generating the array for
> the query:
>
> import decimal
> from decimal import Decimal as d
> import logging
>
> def LngList(lng):
>   """returns array of truncated lng strings"""
>   lnglist = []
>   lnglist.append(__truncate(lng, 0))
>   lnglist.append(__truncate(lng, 1))
>   lnglist.append(__truncate(lng, 2))
>   lnglist.append(__truncate(lng, 3))
>   return lnglist
>
> def ViewportLngs(minLng, maxLng):
>   """returns array of lngs that exist in the viewport, with the right
> degree of precision"""
>   vislngs = []
>   dif = abs(maxLng - minLng)
>   if minLng > maxLng:
>     logging.info("minLng: %s maxLng: %s" %(minLng, maxLng))
>     dif = (180 - minLng) + abs(-180 - maxLng)
>     if dif < .01:
>       vislngs = __makelist(3, minLng, 180) + __makelist(3, -180,
> maxLng)
>     elif dif < .1:
>       vislngs = __makelist(2, minLng, 180) + __makelist(2, -180,
> maxLng)
>     elif dif < 1:
>       vislngs = __makelist(1, minLng, 180) + __makelist(1, -180,
> maxLng)
>     else:
>       logging.error("Viewing both sides of the dateline, zoomed out.")
>   elif dif < .01:
>     vislngs = __makelist(3, minLng, maxLng)
>   elif dif < .1:
>     vislngs = __makelist(2, minLng, maxLng)
>   elif dif < 1:
>     vislngs = __makelist(1, minLng, maxLng)
>   else:
>     # zoomed out case
>     logging.error("The LngList method is being used on a viewport with
> a range larger than 1 degree.")
>   return vislngs
>
> def __makelist(level, minLng, maxLng):
>   """actually populates the list of longs, based on conditions passed
> in, and accounts for extreme near-zero cases."""
>   inc = 10**-level
>   lng = __truncate(minLng, level)
>   maxL = __truncate(maxLng, level)
>   vislngs = [lng]
>   while lng != maxL:
>     if lng == 0:
>       return __makelist(level + 1, minLng, maxLng)
>     lng = __truncate(float(lng)+inc, level)
>     vislngs.append(lng)
>   return vislngs
>
> def __truncate(num, prec):
>   """truncates the float passed in to _prec_ places after the decimal,
> and returns it as a string"""
>   result = unicode(d(str(num)).quantize(d("1e%d" % (-prec)),
> decimal.ROUND_DOWN))
>   if result == u'-0.0':
>     result = u'0.0'
>   if result == u'-0.00':
>     result == u'0.00'
>   return result
>
> This method seems to preform pretty well, though I don't yet have gobs
> of data. I am able to run a query that returns 3-400 markers and load
> them all up in less than a second. Unfortunately, this doesn't account
> for Polylines and Polygons. We're still working on an elegant solution
> for those, probably similar to your method of storing the grid-boxes
> each one overlaps. Exploding indexes, here I come.
>
> Nevin
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to