{"action":"created","comment":{"url":"https://api.github.com/repos/mapzen/TileStache/pulls/comments/42898555","id":42898555,"diff_hunk":"@@ -1240,42 +1312,86 @@ def exterior_boundaries(feature_layers, zoom,\n \n     features = layer['features']\n \n+    # this exists to enable a dirty hack to try and work\n+    # around duplicate geometries in the database. this\n+    # happens when a multipolygon relation can't\n+    # supersede a member way because the way contains tags\n+    # which aren't present on the relation. working around\n+    # this by calling \"union\" on geometries proved to be\n+    # too expensive (~3x current), so this hack looks at\n+    # the way_area of each object, and uses that as a\n+    # proxy for identity. it's not perfect, but the chance\n+    # that there are two overlapping polygons of exactly\n+    # the same size must be pretty small. however, the\n+    # STRTree we're using as a spatial index doesn't\n+    # directly support setting attributes on the indexed\n+    # geometries, so this class exists to carry the area\n+    # attribute through the index to the point where we\n+    # want to use it.\n+    class geom_with_area:\n+        def __init__(self, geom, area):\n+            self.geom = geom\n+            self.area = area\n+            self._geom = geom._geom","path":"TileStache/Goodies/VecTiles/transform.py","position":138,"original_position":138,"commit_id":"f35a65195e198eac350b0206ba32bec8cabad82c","original_commit_id":"f35a65195e198eac350b0206ba32bec8cabad82c","user":{"login":"zerebubuth","id":271360,"avatar_url":"https://avatars.githubusercontent.com/u/271360?v=3","gravatar_id":"","url":"https://api.github.com/users/zerebubuth","html_url":"https://github.com/zerebubuth","followers_url":"https://api.github.com/users/zerebubuth/followers","following_url":"https://api.github.com/users/zerebubuth/following{/other_user}","gists_url":"https://api.github.com/users/zerebubuth/gists{/gist_id}","starred_url":"https://api.github.com/users/zerebubuth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zerebubuth/subscriptions","organizations_url":"https://api.github.com/users/zerebubuth/orgs","repos_url":"https://api.github.com/users/zerebubuth/repos","events_url":"https://api.github.com/users/zerebubuth/events{/privacy}","received_events_url":"https://api.github.com/users/zerebubuth/received_events","type":"User","site_admin":false},"body":"The `STRTree` is looking to access `_geom`, and we need `geom` and `area`, so would you do that as `NamedTuple('class_with_area', ['geom','_geom','area'])` and set them explicitly?","created_at":"2015-10-23T18:32:17Z","updated_at":"2015-10-23T18:32:17Z","html_url":"https://github.com/mapzen/TileStache/pull/76#discussion_r42898555","pull_request_url":"https://api.github.com/repos/mapzen/TileStache/pulls/76","_links":{"self":{"href":"https://api.github.com/repos/mapzen/TileStache/pulls/comments/42898555"},"html":{"href":"https://github.com/mapzen/TileStache/pull/76#discussion_r42898555"},"pull_request":{"href":"https://api.github.com/repos/mapzen/TileStache/pulls/76"}}},"pull_request":{"url":"https://api.github.com/repos/mapzen/TileStache/pulls/76","id":48600158,"html_url":"https://github.com/mapzen/TileStache/pull/76","diff_url":"https://github.com/mapzen/TileStache/pull/76.diff","patch_url":"https://github.com/mapzen/TileStache/pull/76.patch","issue_url":"https://api.github.com/repos/mapzen/TileStache/issues/76","number":76,"state":"open","locked":false,"title":"Fix water boundaries","user":{"login":"zerebubuth","id":271360,"avatar_url":"https://avatars.githubusercontent.com/u/271360?v=3","gravatar_id":"","url":"https://api.github.com/users/zerebubuth","html_url":"https://github.com/zerebubuth","followers_url":"https://api.github.com/users/zerebubuth/followers","following_url":"https://api.github.com/users/zerebubuth/following{/other_user}","gists_url":"https://api.github.com/users/zerebubuth/gists{/gist_id}","starred_url":"https://api.github.com/users/zerebubuth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zerebubuth/subscriptions","organizations_url":"https://api.github.com/users/zerebubuth/orgs","repos_url":"https://api.github.com/users/zerebubuth/repos","events_url":"https://api.github.com/users/zerebubuth/events{/privacy}","received_events_url":"https://api.github.com/users/zerebubuth/received_events","type":"User","site_admin":false},"body":"Fix a couple of water boundaries issues. Well, one fix, one dirty hack-around.\r\n\r\n## Snapping to grid\r\n\r\nWe get our water / river polygons through osm2pgsql, but our ocean polygons via the osmcoastline shapefile download. The different processing done by each pipeline means that the numeric precision of the coordinates can be very, very slightly off (by about 1cm in this case). There's nothing we can really do about this - that level of precision is pretty good, given how the data is being processed and projected in the different pipelines.\r\n\r\nThe fix for this is to snap to grid before doing anything with the polygons. PostGIS has a `ST_SnapToGrid` function, but this isn't coming from GEOS, it's implemented by PostGIS. Likewise, Shapely doesn't have a snapping function, so this PR adds one.\r\n\r\n## Dirty hack around duplicate polygons\r\n\r\nWhen a way is a member of a multipolygon relation, the relation usually \"supersedes\" the way and suppresses its output. This _doesn't_ happen when the way has tags which aren't present on the relation for the very good reason that those tags might be important (e.g: for inner courtyards tagged as a different type of object).\r\n\r\nSince performing a union on all the polygons is a _very_ expensive operation, instead this PR introduces a method which appears to be effective and cheap: it compares the area of the geometry and any intersecting geometry and if they match _exactly_ then it treats that as a proxy for the object's identity and doesn't intersect with it. This appears to fix the Lake Merced case.","created_at":"2015-10-23T16:20:58Z","updated_at":"2015-10-23T18:32:18Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a2cfc147b498957645421bda479ca8094621edf9","assignee":{"login":"rmarianski","id":53770,"avatar_url":"https://avatars.githubusercontent.com/u/53770?v=3","gravatar_id":"","url":"https://api.github.com/users/rmarianski","html_url":"https://github.com/rmarianski","followers_url":"https://api.github.com/users/rmarianski/followers","following_url":"https://api.github.com/users/rmarianski/following{/other_user}","gists_url":"https://api.github.com/users/rmarianski/gists{/gist_id}","starred_url":"https://api.github.com/users/rmarianski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rmarianski/subscriptions","organizations_url":"https://api.github.com/users/rmarianski/orgs","repos_url":"https://api.github.com/users/rmarianski/repos","events_url":"https://api.github.com/users/rmarianski/events{/privacy}","received_events_url":"https://api.github.com/users/rmarianski/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/mapzen/TileStache/pulls/76/commits","review_comments_url":"https://api.github.com/repos/mapzen/TileStache/pulls/76/comments","review_comment_url":"https://api.github.com/repos/mapzen/TileStache/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mapzen/TileStache/issues/76/comments","statuses_url":"https://api.github.com/repos/mapzen/TileStache/statuses/f35a65195e198eac350b0206ba32bec8cabad82c","head":{"label":"mapzen:303-fix-water-boundaries","ref":"303-fix-water-boundaries","sha":"f35a65195e198eac350b0206ba32bec8cabad82c","user":{"login":"mapzen","id":5435747,"avatar_url":"https://avatars.githubusercontent.com/u/5435747?v=3","gravatar_id":"","url":"https://api.github.com/users/mapzen","html_url":"https://github.com/mapzen","followers_url":"https://api.github.com/users/mapzen/followers","following_url":"https://api.github.com/users/mapzen/following{/other_user}","gists_url":"https://api.github.com/users/mapzen/gists{/gist_id}","starred_url":"https://api.github.com/users/mapzen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapzen/subscriptions","organizations_url":"https://api.github.com/users/mapzen/orgs","repos_url":"https://api.github.com/users/mapzen/repos","events_url":"https://api.github.com/users/mapzen/events{/privacy}","received_events_url":"https://api.github.com/users/mapzen/received_events","type":"Organization","site_admin":false},"repo":{"id":16214517,"name":"TileStache","full_name":"mapzen/TileStache","owner":{"login":"mapzen","id":5435747,"avatar_url":"https://avatars.githubusercontent.com/u/5435747?v=3","gravatar_id":"","url":"https://api.github.com/users/mapzen","html_url":"https://github.com/mapzen","followers_url":"https://api.github.com/users/mapzen/followers","following_url":"https://api.github.com/users/mapzen/following{/other_user}","gists_url":"https://api.github.com/users/mapzen/gists{/gist_id}","starred_url":"https://api.github.com/users/mapzen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapzen/subscriptions","organizations_url":"https://api.github.com/users/mapzen/orgs","repos_url":"https://api.github.com/users/mapzen/repos","events_url":"https://api.github.com/users/mapzen/events{/privacy}","received_events_url":"https://api.github.com/users/mapzen/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mapzen/TileStache","description":"A stylish alternative for caching your map tiles.","fork":true,"url":"https://api.github.com/repos/mapzen/TileStache","forks_url":"https://api.github.com/repos/mapzen/TileStache/forks","keys_url":"https://api.github.com/repos/mapzen/TileStache/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mapzen/TileStache/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mapzen/TileStache/teams","hooks_url":"https://api.github.com/repos/mapzen/TileStache/hooks","issue_events_url":"https://api.github.com/repos/mapzen/TileStache/issues/events{/number}","events_url":"https://api.github.com/repos/mapzen/TileStache/events","assignees_url":"https://api.github.com/repos/mapzen/TileStache/assignees{/user}","branches_url":"https://api.github.com/repos/mapzen/TileStache/branches{/branch}","tags_url":"https://api.github.com/repos/mapzen/TileStache/tags","blobs_url":"https://api.github.com/repos/mapzen/TileStache/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mapzen/TileStache/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mapzen/TileStache/git/refs{/sha}","trees_url":"https://api.github.com/repos/mapzen/TileStache/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mapzen/TileStache/statuses/{sha}","languages_url":"https://api.github.com/repos/mapzen/TileStache/languages","stargazers_url":"https://api.github.com/repos/mapzen/TileStache/stargazers","contributors_url":"https://api.github.com/repos/mapzen/TileStache/contributors","subscribers_url":"https://api.github.com/repos/mapzen/TileStache/subscribers","subscription_url":"https://api.github.com/repos/mapzen/TileStache/subscription","commits_url":"https://api.github.com/repos/mapzen/TileStache/commits{/sha}","git_commits_url":"https://api.github.com/repos/mapzen/TileStache/git/commits{/sha}","comments_url":"https://api.github.com/repos/mapzen/TileStache/comments{/number}","issue_comment_url":"https://api.github.com/repos/mapzen/TileStache/issues/comments{/number}","contents_url":"https://api.github.com/repos/mapzen/TileStache/contents/{+path}","compare_url":"https://api.github.com/repos/mapzen/TileStache/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mapzen/TileStache/merges","archive_url":"https://api.github.com/repos/mapzen/TileStache/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mapzen/TileStache/downloads","issues_url":"https://api.github.com/repos/mapzen/TileStache/issues{/number}","pulls_url":"https://api.github.com/repos/mapzen/TileStache/pulls{/number}","milestones_url":"https://api.github.com/repos/mapzen/TileStache/milestones{/number}","notifications_url":"https://api.github.com/repos/mapzen/TileStache/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mapzen/TileStache/labels{/name}","releases_url":"https://api.github.com/repos/mapzen/TileStache/releases{/id}","created_at":"2014-01-24T19:28:51Z","updated_at":"2015-10-05T10:32:25Z","pushed_at":"2015-10-23T16:21:44Z","git_url":"git://github.com/mapzen/TileStache.git","ssh_url":"git@github.com:mapzen/TileStache.git","clone_url":"https://github.com/mapzen/TileStache.git","svn_url":"https://github.com/mapzen/TileStache","homepage":"http://tilestache.org","size":7032,"stargazers_count":14,"watchers_count":14,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":3,"forks":7,"open_issues":3,"watchers":14,"default_branch":"integration-1"}},"base":{"label":"mapzen:integration-1","ref":"integration-1","sha":"28b965f09c44f0dbc15f52c11d35363705f7f419","user":{"login":"mapzen","id":5435747,"avatar_url":"https://avatars.githubusercontent.com/u/5435747?v=3","gravatar_id":"","url":"https://api.github.com/users/mapzen","html_url":"https://github.com/mapzen","followers_url":"https://api.github.com/users/mapzen/followers","following_url":"https://api.github.com/users/mapzen/following{/other_user}","gists_url":"https://api.github.com/users/mapzen/gists{/gist_id}","starred_url":"https://api.github.com/users/mapzen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapzen/subscriptions","organizations_url":"https://api.github.com/users/mapzen/orgs","repos_url":"https://api.github.com/users/mapzen/repos","events_url":"https://api.github.com/users/mapzen/events{/privacy}","received_events_url":"https://api.github.com/users/mapzen/received_events","type":"Organization","site_admin":false},"repo":{"id":16214517,"name":"TileStache","full_name":"mapzen/TileStache","owner":{"login":"mapzen","id":5435747,"avatar_url":"https://avatars.githubusercontent.com/u/5435747?v=3","gravatar_id":"","url":"https://api.github.com/users/mapzen","html_url":"https://github.com/mapzen","followers_url":"https://api.github.com/users/mapzen/followers","following_url":"https://api.github.com/users/mapzen/following{/other_user}","gists_url":"https://api.github.com/users/mapzen/gists{/gist_id}","starred_url":"https://api.github.com/users/mapzen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapzen/subscriptions","organizations_url":"https://api.github.com/users/mapzen/orgs","repos_url":"https://api.github.com/users/mapzen/repos","events_url":"https://api.github.com/users/mapzen/events{/privacy}","received_events_url":"https://api.github.com/users/mapzen/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mapzen/TileStache","description":"A stylish alternative for caching your map tiles.","fork":true,"url":"https://api.github.com/repos/mapzen/TileStache","forks_url":"https://api.github.com/repos/mapzen/TileStache/forks","keys_url":"https://api.github.com/repos/mapzen/TileStache/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mapzen/TileStache/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mapzen/TileStache/teams","hooks_url":"https://api.github.com/repos/mapzen/TileStache/hooks","issue_events_url":"https://api.github.com/repos/mapzen/TileStache/issues/events{/number}","events_url":"https://api.github.com/repos/mapzen/TileStache/events","assignees_url":"https://api.github.com/repos/mapzen/TileStache/assignees{/user}","branches_url":"https://api.github.com/repos/mapzen/TileStache/branches{/branch}","tags_url":"https://api.github.com/repos/mapzen/TileStache/tags","blobs_url":"https://api.github.com/repos/mapzen/TileStache/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mapzen/TileStache/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mapzen/TileStache/git/refs{/sha}","trees_url":"https://api.github.com/repos/mapzen/TileStache/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mapzen/TileStache/statuses/{sha}","languages_url":"https://api.github.com/repos/mapzen/TileStache/languages","stargazers_url":"https://api.github.com/repos/mapzen/TileStache/stargazers","contributors_url":"https://api.github.com/repos/mapzen/TileStache/contributors","subscribers_url":"https://api.github.com/repos/mapzen/TileStache/subscribers","subscription_url":"https://api.github.com/repos/mapzen/TileStache/subscription","commits_url":"https://api.github.com/repos/mapzen/TileStache/commits{/sha}","git_commits_url":"https://api.github.com/repos/mapzen/TileStache/git/commits{/sha}","comments_url":"https://api.github.com/repos/mapzen/TileStache/comments{/number}","issue_comment_url":"https://api.github.com/repos/mapzen/TileStache/issues/comments{/number}","contents_url":"https://api.github.com/repos/mapzen/TileStache/contents/{+path}","compare_url":"https://api.github.com/repos/mapzen/TileStache/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mapzen/TileStache/merges","archive_url":"https://api.github.com/repos/mapzen/TileStache/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mapzen/TileStache/downloads","issues_url":"https://api.github.com/repos/mapzen/TileStache/issues{/number}","pulls_url":"https://api.github.com/repos/mapzen/TileStache/pulls{/number}","milestones_url":"https://api.github.com/repos/mapzen/TileStache/milestones{/number}","notifications_url":"https://api.github.com/repos/mapzen/TileStache/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mapzen/TileStache/labels{/name}","releases_url":"https://api.github.com/repos/mapzen/TileStache/releases{/id}","created_at":"2014-01-24T19:28:51Z","updated_at":"2015-10-05T10:32:25Z","pushed_at":"2015-10-23T16:21:44Z","git_url":"git://github.com/mapzen/TileStache.git","ssh_url":"git@github.com:mapzen/TileStache.git","clone_url":"https://github.com/mapzen/TileStache.git","svn_url":"https://github.com/mapzen/TileStache","homepage":"http://tilestache.org","size":7032,"stargazers_count":14,"watchers_count":14,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":3,"forks":7,"open_issues":3,"watchers":14,"default_branch":"integration-1"}},"_links":{"self":{"href":"https://api.github.com/repos/mapzen/TileStache/pulls/76"},"html":{"href":"https://github.com/mapzen/TileStache/pull/76"},"issue":{"href":"https://api.github.com/repos/mapzen/TileStache/issues/76"},"comments":{"href":"https://api.github.com/repos/mapzen/TileStache/issues/76/comments"},"review_comments":{"href":"https://api.github.com/repos/mapzen/TileStache/pulls/76/comments"},"review_comment":{"href":"https://api.github.com/repos/mapzen/TileStache/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mapzen/TileStache/pulls/76/commits"},"statuses":{"href":"https://api.github.com/repos/mapzen/TileStache/statuses/f35a65195e198eac350b0206ba32bec8cabad82c"}}}}