{"url":"https://api.github.com/gists/550849","forks_url":"https://api.github.com/gists/550849/forks","commits_url":"https://api.github.com/gists/550849/commits","id":"550849","node_id":"MDQ6R2lzdDU1MDg0OQ==","git_pull_url":"https://gist.github.com/550849.git","git_push_url":"https://gist.github.com/550849.git","html_url":"https://gist.github.com/mbostock/550849","files":{"app.yaml":{"filename":"app.yaml","type":"text/x-yaml","language":"YAML","raw_url":"https://gist.githubusercontent.com/mbostock/550849/raw/1bc78de069f307f0a4e37f3fb31415001787d5fa/app.yaml","size":175,"truncated":false,"content":"application: polymaps\nversion: 1\nruntime: python\napi_version: 1\n\nhandlers:\n- url: /state/.*\n  script: main.py\n\n- url: /county/.*\n  script: main.py\n\n- url: /\n  script: main.py\n","encoding":"utf-8"},"main.py":{"filename":"main.py","type":"application/x-python","language":"Python","raw_url":"https://gist.githubusercontent.com/mbostock/550849/raw/7e6d49449f6b86c8891c5f1987b1df2ac7fe525d/main.py","size":1457,"truncated":false,"content":"#!/usr/bin/env python\n#\n# Copyright 2007 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nimport wsgiref.handlers\nimport os\nfrom google.appengine.ext import webapp\nfrom google.appengine.ext.webapp import util\n\nclass MainHandler(webapp.RequestHandler):\n  def get(self):\n    self.response.out.write('Hello world!')\n\nclass JsonHandler(webapp.RequestHandler):\n  def get(self):\n    path = os.path.join(os.path.dirname(__file__), self.request.path[1:])\n    self.response.headers.add_header(\"Access-Control-Allow-Origin\", \"*\")\n    if os.path.exists(path):\n      self.response.out.write(open(path, 'r').read())\n    else:\n      self.response.out.write('{\"type\":\"FeatureCollection\",\"features\":[]}')\n\ndef main():\n  application = webapp.WSGIApplication([\n      ('/', MainHandler),\n      ('/state/.*', JsonHandler),\n      ('/county/.*', JsonHandler),\n      ], debug=False)\n  wsgiref.handlers.CGIHandler().run(application)\n\nif __name__ == '__main__':\n  main()","encoding":"utf-8"},"scraper.py":{"filename":"scraper.py","type":"application/x-python","language":"Python","raw_url":"https://gist.githubusercontent.com/mbostock/550849/raw/392e110194e108c23ba12bdf29b86351a6183d38/scraper.py","size":2454,"truncated":false,"content":"import os\nimport errno\nimport re\nfrom urllib import urlopen\nfrom json import JSONEncoder\n\nimport ModestMaps\nimport geojson\nimport simplejson\nfrom shapely.geometry import asShape\nfrom shapely.geometry import asPolygon\n\nif __name__ == '__main__':\n\n    provider = ModestMaps.builtinProviders['OPENSTREETMAP']()\n    float_pat = re.compile(r'^-?\\d+\\.\\d+$')\n\n    def mkdir_p(path):\n        try:\n            os.makedirs(path)\n        except OSError as exc: # Python >2.5\n            if exc.errno == errno.EEXIST:\n                pass\n            else: raise\n\n    def scrape(row, col, zoom):\n        nw = provider.coordinateLocation(ModestMaps.Core.Coordinate(row, col, zoom))\n        se = provider.coordinateLocation(ModestMaps.Core.Coordinate(row + 1, col + 1, zoom))\n        url = 'http://localhost/pushpin?area=county&where=bbox:{nw.lat:f},{se.lon:f},{se.lat:f},{nw.lon:f}&zoom={Z}'.format(nw=nw, se=se, Z=zoom)\n        print url\n        fcb = geojson.loads(urlopen(url).read())\n\n        if not len(fcb['features']):\n            return\n\n        nwc = provider.coordinateLocation(ModestMaps.Core.Coordinate(row - .01, col - .01, zoom))\n        sec = provider.coordinateLocation(ModestMaps.Core.Coordinate(row + 1.01, col + 1.01, zoom))\n        clip = asPolygon([[nwc.lon, nwc.lat], [sec.lon, nwc.lat],  [sec.lon, sec.lat], [nwc.lon, sec.lat]])\n        match = 0\n\n        for f in fcb['features']:\n            g = f['geometry']\n            shape = asShape(f['geometry'])\n            if shape.intersects(clip):\n                match = 1\n                f['geometry'] = geojson.loads(geojson.dumps(shape.intersection(clip)))\n            else:\n                f['geometry'] = geojson.loads('{}')\n\n        if not match:\n            return\n\n        dir = 'scrape/{Z}/{X}'.format(X=col, Y=row, Z=zoom)\n        mkdir_p(dir)\n        file = 'scrape/{Z}/{X}/{Y}.json'.format(X=col, Y=row, Z=zoom)\n        print file\n        open(file, 'w').write(''.join([(float_pat.match(x) and ('%.6f' % float(x)) or x) for x in JSONEncoder(separators=(',', ':')).iterencode(fcb)]))\n\n        if zoom < maxZoom:\n            zoom += 1\n            row <<= 1\n            col <<= 1\n            scrape(row, col, zoom)\n            scrape(row, col + 1, zoom)\n            scrape(row + 1, col, zoom)\n            scrape(row + 1, col + 1, zoom)\n\n    minZoom = 3\n    maxZoom = 7\n    for row in range(0, 1 << minZoom):\n        for col in range(0, 1 << minZoom):\n            scrape(row, col, minZoom)","encoding":"utf-8"}},"public":true,"created_at":"2010-08-26T05:05:54Z","updated_at":"2015-09-05T21:15:09Z","description":"polymaps.appspot.com","comments":1,"user":null,"comments_enabled":true,"comments_url":"https://api.github.com/gists/550849/comments","owner":{"login":"mbostock","id":230541,"node_id":"MDQ6VXNlcjIzMDU0MQ==","avatar_url":"https://avatars.githubusercontent.com/u/230541?v=4","gravatar_id":"","url":"https://api.github.com/users/mbostock","html_url":"https://github.com/mbostock","followers_url":"https://api.github.com/users/mbostock/followers","following_url":"https://api.github.com/users/mbostock/following{/other_user}","gists_url":"https://api.github.com/users/mbostock/gists{/gist_id}","starred_url":"https://api.github.com/users/mbostock/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mbostock/subscriptions","organizations_url":"https://api.github.com/users/mbostock/orgs","repos_url":"https://api.github.com/users/mbostock/repos","events_url":"https://api.github.com/users/mbostock/events{/privacy}","received_events_url":"https://api.github.com/users/mbostock/received_events","type":"User","user_view_type":"public","site_admin":false},"forks":[{"url":"https://api.github.com/gists/863544","user":{"login":"JasonSanford","id":220341,"node_id":"MDQ6VXNlcjIyMDM0MQ==","avatar_url":"https://avatars.githubusercontent.com/u/220341?v=4","gravatar_id":"","url":"https://api.github.com/users/JasonSanford","html_url":"https://github.com/JasonSanford","followers_url":"https://api.github.com/users/JasonSanford/followers","following_url":"https://api.github.com/users/JasonSanford/following{/other_user}","gists_url":"https://api.github.com/users/JasonSanford/gists{/gist_id}","starred_url":"https://api.github.com/users/JasonSanford/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JasonSanford/subscriptions","organizations_url":"https://api.github.com/users/JasonSanford/orgs","repos_url":"https://api.github.com/users/JasonSanford/repos","events_url":"https://api.github.com/users/JasonSanford/events{/privacy}","received_events_url":"https://api.github.com/users/JasonSanford/received_events","type":"User","user_view_type":"public","site_admin":false,"name":"Jason Sanford","company":null,"blog":"https://jsanford.dev","location":"Mooresville, NC","email":"jasonsanford@gmail.com","hireable":null,"bio":null,"twitter_username":"JCSanford","public_repos":88,"public_gists":31,"followers":207,"following":8,"created_at":"2010-03-11T04:01:12Z","updated_at":"2026-05-12T19:34:02Z"},"id":"863544","created_at":"2011-03-10T03:47:29Z","updated_at":"2015-09-25T04:28:00Z"}],"history":[{"user":null,"version":"b97b150a1b142fb0f888333f7f0c78c103e00faf","committed_at":"2010-08-26T05:08:14Z","change_status":{"total":59,"additions":59,"deletions":0},"url":"https://api.github.com/gists/550849/b97b150a1b142fb0f888333f7f0c78c103e00faf"},{"user":null,"version":"2a79562a3b494382bf3f11600f9d51f19ee2d406","committed_at":"2010-08-26T05:05:54Z","change_status":{"total":72,"additions":72,"deletions":0},"url":"https://api.github.com/gists/550849/2a79562a3b494382bf3f11600f9d51f19ee2d406"}],"truncated":false}