{"action":"created","comment":{"url":"https://api.github.com/repos/openlayers/ol3/pulls/comments/45101225","id":45101225,"diff_hunk":"@@ -0,0 +1,131 @@\n+---\n+title: Raster Reprojection\n+layout: doc.hbs\n+---\n+\n+# Raster Reprojection\n+\n+OpenLayers 3 has an ability to display raster data from WMS, WMTS, static images and many other sources in a different coordinate system than delivered from the server.\n+Transformation of the map projections of the image happens directly in a web browser.\n+The view in any Proj4js supported coordinate reference system is possible and previously incompatible layers can be now combined and overlaid.\n+\n+# Usage\n+The usage in API is very simple. Just specify proper projection (using [EPSG](http://epsg.io) code) on `ol.View`:\n+``` javascript\n+var map = new ol.Map({\n+  target: 'map',\n+  view: new ol.View({\n+    projection: 'EPSG:3857', //HERE IS THE VIEW PROJECTION\n+    center: [0, 0],\n+    zoom: 2\n+  }),\n+  layers: [\n+    new ol.layer.Tile({\n+      source: new ol.source.TileWMS({\n+        projection: 'EPSG:4326', //HERE IS THE DATA SOURCE PROJECTION\n+        url: 'http://demo.boundlessgeo.com/geoserver/wms',\n+        params: {\n+          'LAYERS': 'ne:NE1_HR_LC_SR_W_DR'\n+        }\n+    })\n+  })]\n+});\n+```\n+If a source (based on `ol.source.TileImage` or `ol.source.Image`) has projection different from the current `ol.View`’s projection then the reprojection happens automatically under the hood.\n+\n+### Examples\n+- [Raster reprojection demo](http://openlayers.org/en/master/examples/reprojection.html)\n+- [OpenStreetMap to WGS84 reprojection](http://openlayers.org/en/master/examples/reprojection-wgs84.html)\n+- [Reprojection with EPSG.io database search](http://openlayers.org/en/master/examples/reprojection-by-code.html)\n+- [Image reprojection](http://openlayers.org/en/master/examples/reprojection-image.html)\n+\n+### Custom projection\n+The easiest way to use a custom projection is to add [Proj4js](http://proj4js.org/) library to your project and then define the projection using proj4 definition string.\n+Following example shows definition of a [British National Grid](http://epsg.io/27700):\n+\n+``` html\n+<script type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.12/proj4.js\"></script>\n+```\n+\n+``` javascript\n+proj4.defs('EPSG:27700', '+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 ' +\n+    '+x_0=400000 +y_0=-100000 +ellps=airy ' +\n+    '+towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 ' +\n+    '+units=m +no_defs');\n+var proj27700 = ol.proj.get('EPSG:27700');\n+proj27700.setExtent([0, 0, 700000, 1300000]);\n+```\n+\n+### Change of the view projection\n+To switch the projection used to display the map you have to set a new `ol.View` with selected projection on the `ol.Map`:\n+``` javascript\n+map.setView(new ol.View({\n+    projection: 'EPSG:27700',\n+    center: [400000, 650000],\n+    zoom: 4\n+  }));\n+```\n+\n+## TileGrid and Extents\n+When reprojection is needed, new tiles (in the target projection) are under the hood created from the original source tiles.\n+The TileGrid of the reprojected tiles is by default internally constructed using `ol.tilegrid.getForProjection(projection)`.\n+The projection should have extent defined (see above) for this to work properly.\n+\n+Alternatively, a custom target TileGrid can be constructed manually and set on the source instance using `ol.source.TileImage#setTileGridForProjection(projection, tilegrid)`.\n+This TileGrid will then be used when reprojecting to the specified projection instead of creating the default one.\n+In certain cases, this can be used to optimize performance (by tweaking tile sizes) or visual quality (by specifying resolutions).\n+\n+# How it works\n+\n+The reprojection process is based on triangles -- the target raster is divided into a limited number of triangles with vertices transformed using `ol.proj` capabilities ([proj4js](http://proj4js.org/) is usually utilized to define custom transformations).\n+The reprojection of pixels inside the triangle is approximated with an affine transformation (with rendering hardware-accelerated by the canvas 2d context):\n+\n+<img src=\"raster-reprojection-resources/how-it-works.jpg\" alt=\"How it works\" width=\"600\" />\n+\n+This way we can support wide range of projections from proj4js (or even custom transformation functions) on almost any hardware (with canvas 2d support) with relatively small number of actual transformation calculations.\n+\n+The precision of the reprojection is then limited by the number of triangles.\n+\n+The reprojection process preserves transparency on the raster data supplied from the source (png or gif) and the gaps and no-data pixels generated by reprojection are automatically transparent.\n+\n+###Dynamic triangulation\n+\n+The above image above shows a noticeable error (especially on the edges) when the original image (left; EPSG:27700) is transformed with only a limited number of triangles (right; EPSG:3857).\n+The error can be minimized by increasing the number of triangles used.\n+\n+Since some transformations require more detail triangulation network, the dynamic triangulation process automatically measures reprojection error and iteratively subdivides to meet a specific error threshold:\n+\n+<img src=\"raster-reprojection-resources/iterative-triangulation.png\" alt=\"Iterative triangulation\" width=\"600\" />\n+\n+For debugging, rendering of the reprojection edges can be enabled by `ol.source.TileImage#setRenderReporojectionEdges(true)`.\n+\n+# Advanced\n+\n+### Disabling reprojection\n+In case you are creating a custom build of OpenLayers and do not need the reprojection code, you can reduce the build size by setting `ol.ENABLE_RASTER_REPROJECTION` to `false`, which completely disables the reprojection support.\n+See [Custom builds](custom-builds.html#defines) tutorial to see how to do this.\n+\n+### Triangulation precision threshold\n+The default [triangulation error threshold](#dynamic-triangulation) in pixels is given by `ol.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD` (0.5 pixel).\n+In case different threshold needs to be defined for different sources, `reprojectionErrorThreshold` option can be passed when constructing tile image source.","path":"doc/tutorials/raster-reprojection.md","position":110,"original_position":110,"commit_id":"5c7b719335635281d6eb2edc053cef513cf90cb5","original_commit_id":"5c7b719335635281d6eb2edc053cef513cf90cb5","user":{"login":"bartvde","id":319678,"avatar_url":"https://avatars.githubusercontent.com/u/319678?v=3","gravatar_id":"","url":"https://api.github.com/users/bartvde","html_url":"https://github.com/bartvde","followers_url":"https://api.github.com/users/bartvde/followers","following_url":"https://api.github.com/users/bartvde/following{/other_user}","gists_url":"https://api.github.com/users/bartvde/gists{/gist_id}","starred_url":"https://api.github.com/users/bartvde/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bartvde/subscriptions","organizations_url":"https://api.github.com/users/bartvde/orgs","repos_url":"https://api.github.com/users/bartvde/repos","events_url":"https://api.github.com/users/bartvde/events{/privacy}","received_events_url":"https://api.github.com/users/bartvde/received_events","type":"User","site_admin":false},"body":"constructing tile image source -> constructing the tile image source","created_at":"2015-11-17T18:46:46Z","updated_at":"2015-11-17T18:46:46Z","html_url":"https://github.com/openlayers/ol3/pull/4440#discussion_r45101225","pull_request_url":"https://api.github.com/repos/openlayers/ol3/pulls/4440","_links":{"self":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/comments/45101225"},"html":{"href":"https://github.com/openlayers/ol3/pull/4440#discussion_r45101225"},"pull_request":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/4440"}}},"pull_request":{"url":"https://api.github.com/repos/openlayers/ol3/pulls/4440","id":50951193,"html_url":"https://github.com/openlayers/ol3/pull/4440","diff_url":"https://github.com/openlayers/ol3/pull/4440.diff","patch_url":"https://github.com/openlayers/ol3/pull/4440.patch","issue_url":"https://api.github.com/repos/openlayers/ol3/issues/4440","number":4440,"state":"open","locked":false,"title":"Raster reprojection tutorial","user":{"login":"petrsloup","id":707817,"avatar_url":"https://avatars.githubusercontent.com/u/707817?v=3","gravatar_id":"","url":"https://api.github.com/users/petrsloup","html_url":"https://github.com/petrsloup","followers_url":"https://api.github.com/users/petrsloup/followers","following_url":"https://api.github.com/users/petrsloup/following{/other_user}","gists_url":"https://api.github.com/users/petrsloup/gists{/gist_id}","starred_url":"https://api.github.com/users/petrsloup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/petrsloup/subscriptions","organizations_url":"https://api.github.com/users/petrsloup/orgs","repos_url":"https://api.github.com/users/petrsloup/repos","events_url":"https://api.github.com/users/petrsloup/events{/privacy}","received_events_url":"https://api.github.com/users/petrsloup/received_events","type":"User","site_admin":false},"body":"We were finally able to find enough time to finish the raster reprojection tutorial (related to #4122).\r\n\r\nThis PR adds raster reprojection tutorial explaining basic usage, inner workings and some advanced features of the raster reprojection. (no functional change)\r\n\r\nUntil now, there were no images (or other resources) for the tutorials.\r\nI created `raster-reprojection-resources` folder for the required 3 images for this tutorial. Anybody has some better idea where to put these?\r\nI'm not very happy with the long folder name, but none of the alternatives I could think of (`resources/raster-reprojection/___.jpg` or `resources/raster-reprojection-___.jpg`) was better.","created_at":"2015-11-17T14:12:43Z","updated_at":"2015-11-17T18:46:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"caf55e8ebb9e12729b4f699558c9d4c4235c49bb","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openlayers/ol3/pulls/4440/commits","review_comments_url":"https://api.github.com/repos/openlayers/ol3/pulls/4440/comments","review_comment_url":"https://api.github.com/repos/openlayers/ol3/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openlayers/ol3/issues/4440/comments","statuses_url":"https://api.github.com/repos/openlayers/ol3/statuses/5c7b719335635281d6eb2edc053cef513cf90cb5","head":{"label":"klokantech:rasterreproj_tutorial","ref":"rasterreproj_tutorial","sha":"5c7b719335635281d6eb2edc053cef513cf90cb5","user":{"login":"klokantech","id":511714,"avatar_url":"https://avatars.githubusercontent.com/u/511714?v=3","gravatar_id":"","url":"https://api.github.com/users/klokantech","html_url":"https://github.com/klokantech","followers_url":"https://api.github.com/users/klokantech/followers","following_url":"https://api.github.com/users/klokantech/following{/other_user}","gists_url":"https://api.github.com/users/klokantech/gists{/gist_id}","starred_url":"https://api.github.com/users/klokantech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klokantech/subscriptions","organizations_url":"https://api.github.com/users/klokantech/orgs","repos_url":"https://api.github.com/users/klokantech/repos","events_url":"https://api.github.com/users/klokantech/events{/privacy}","received_events_url":"https://api.github.com/users/klokantech/received_events","type":"Organization","site_admin":false},"repo":{"id":24091682,"name":"ol3","full_name":"klokantech/ol3","owner":{"login":"klokantech","id":511714,"avatar_url":"https://avatars.githubusercontent.com/u/511714?v=3","gravatar_id":"","url":"https://api.github.com/users/klokantech","html_url":"https://github.com/klokantech","followers_url":"https://api.github.com/users/klokantech/followers","following_url":"https://api.github.com/users/klokantech/following{/other_user}","gists_url":"https://api.github.com/users/klokantech/gists{/gist_id}","starred_url":"https://api.github.com/users/klokantech/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klokantech/subscriptions","organizations_url":"https://api.github.com/users/klokantech/orgs","repos_url":"https://api.github.com/users/klokantech/repos","events_url":"https://api.github.com/users/klokantech/events{/privacy}","received_events_url":"https://api.github.com/users/klokantech/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/klokantech/ol3","description":"OpenLayers 3","fork":true,"url":"https://api.github.com/repos/klokantech/ol3","forks_url":"https://api.github.com/repos/klokantech/ol3/forks","keys_url":"https://api.github.com/repos/klokantech/ol3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/klokantech/ol3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/klokantech/ol3/teams","hooks_url":"https://api.github.com/repos/klokantech/ol3/hooks","issue_events_url":"https://api.github.com/repos/klokantech/ol3/issues/events{/number}","events_url":"https://api.github.com/repos/klokantech/ol3/events","assignees_url":"https://api.github.com/repos/klokantech/ol3/assignees{/user}","branches_url":"https://api.github.com/repos/klokantech/ol3/branches{/branch}","tags_url":"https://api.github.com/repos/klokantech/ol3/tags","blobs_url":"https://api.github.com/repos/klokantech/ol3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/klokantech/ol3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/klokantech/ol3/git/refs{/sha}","trees_url":"https://api.github.com/repos/klokantech/ol3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/klokantech/ol3/statuses/{sha}","languages_url":"https://api.github.com/repos/klokantech/ol3/languages","stargazers_url":"https://api.github.com/repos/klokantech/ol3/stargazers","contributors_url":"https://api.github.com/repos/klokantech/ol3/contributors","subscribers_url":"https://api.github.com/repos/klokantech/ol3/subscribers","subscription_url":"https://api.github.com/repos/klokantech/ol3/subscription","commits_url":"https://api.github.com/repos/klokantech/ol3/commits{/sha}","git_commits_url":"https://api.github.com/repos/klokantech/ol3/git/commits{/sha}","comments_url":"https://api.github.com/repos/klokantech/ol3/comments{/number}","issue_comment_url":"https://api.github.com/repos/klokantech/ol3/issues/comments{/number}","contents_url":"https://api.github.com/repos/klokantech/ol3/contents/{+path}","compare_url":"https://api.github.com/repos/klokantech/ol3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/klokantech/ol3/merges","archive_url":"https://api.github.com/repos/klokantech/ol3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/klokantech/ol3/downloads","issues_url":"https://api.github.com/repos/klokantech/ol3/issues{/number}","pulls_url":"https://api.github.com/repos/klokantech/ol3/pulls{/number}","milestones_url":"https://api.github.com/repos/klokantech/ol3/milestones{/number}","notifications_url":"https://api.github.com/repos/klokantech/ol3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/klokantech/ol3/labels{/name}","releases_url":"https://api.github.com/repos/klokantech/ol3/releases{/id}","created_at":"2014-09-16T08:32:16Z","updated_at":"2015-08-11T13:06:00Z","pushed_at":"2015-11-17T13:52:33Z","git_url":"git://github.com/klokantech/ol3.git","ssh_url":"git@github.com:klokantech/ol3.git","clone_url":"https://github.com/klokantech/ol3.git","svn_url":"https://github.com/klokantech/ol3","homepage":"http://openlayers.org","size":37741,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openlayers:master","ref":"master","sha":"fd44295b1706661a2960496ca524e7b98995599e","user":{"login":"openlayers","id":240579,"avatar_url":"https://avatars.githubusercontent.com/u/240579?v=3","gravatar_id":"","url":"https://api.github.com/users/openlayers","html_url":"https://github.com/openlayers","followers_url":"https://api.github.com/users/openlayers/followers","following_url":"https://api.github.com/users/openlayers/following{/other_user}","gists_url":"https://api.github.com/users/openlayers/gists{/gist_id}","starred_url":"https://api.github.com/users/openlayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openlayers/subscriptions","organizations_url":"https://api.github.com/users/openlayers/orgs","repos_url":"https://api.github.com/users/openlayers/repos","events_url":"https://api.github.com/users/openlayers/events{/privacy}","received_events_url":"https://api.github.com/users/openlayers/received_events","type":"Organization","site_admin":false},"repo":{"id":4723248,"name":"ol3","full_name":"openlayers/ol3","owner":{"login":"openlayers","id":240579,"avatar_url":"https://avatars.githubusercontent.com/u/240579?v=3","gravatar_id":"","url":"https://api.github.com/users/openlayers","html_url":"https://github.com/openlayers","followers_url":"https://api.github.com/users/openlayers/followers","following_url":"https://api.github.com/users/openlayers/following{/other_user}","gists_url":"https://api.github.com/users/openlayers/gists{/gist_id}","starred_url":"https://api.github.com/users/openlayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openlayers/subscriptions","organizations_url":"https://api.github.com/users/openlayers/orgs","repos_url":"https://api.github.com/users/openlayers/repos","events_url":"https://api.github.com/users/openlayers/events{/privacy}","received_events_url":"https://api.github.com/users/openlayers/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openlayers/ol3","description":"OpenLayers 3","fork":false,"url":"https://api.github.com/repos/openlayers/ol3","forks_url":"https://api.github.com/repos/openlayers/ol3/forks","keys_url":"https://api.github.com/repos/openlayers/ol3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openlayers/ol3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openlayers/ol3/teams","hooks_url":"https://api.github.com/repos/openlayers/ol3/hooks","issue_events_url":"https://api.github.com/repos/openlayers/ol3/issues/events{/number}","events_url":"https://api.github.com/repos/openlayers/ol3/events","assignees_url":"https://api.github.com/repos/openlayers/ol3/assignees{/user}","branches_url":"https://api.github.com/repos/openlayers/ol3/branches{/branch}","tags_url":"https://api.github.com/repos/openlayers/ol3/tags","blobs_url":"https://api.github.com/repos/openlayers/ol3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openlayers/ol3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openlayers/ol3/git/refs{/sha}","trees_url":"https://api.github.com/repos/openlayers/ol3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openlayers/ol3/statuses/{sha}","languages_url":"https://api.github.com/repos/openlayers/ol3/languages","stargazers_url":"https://api.github.com/repos/openlayers/ol3/stargazers","contributors_url":"https://api.github.com/repos/openlayers/ol3/contributors","subscribers_url":"https://api.github.com/repos/openlayers/ol3/subscribers","subscription_url":"https://api.github.com/repos/openlayers/ol3/subscription","commits_url":"https://api.github.com/repos/openlayers/ol3/commits{/sha}","git_commits_url":"https://api.github.com/repos/openlayers/ol3/git/commits{/sha}","comments_url":"https://api.github.com/repos/openlayers/ol3/comments{/number}","issue_comment_url":"https://api.github.com/repos/openlayers/ol3/issues/comments{/number}","contents_url":"https://api.github.com/repos/openlayers/ol3/contents/{+path}","compare_url":"https://api.github.com/repos/openlayers/ol3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openlayers/ol3/merges","archive_url":"https://api.github.com/repos/openlayers/ol3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openlayers/ol3/downloads","issues_url":"https://api.github.com/repos/openlayers/ol3/issues{/number}","pulls_url":"https://api.github.com/repos/openlayers/ol3/pulls{/number}","milestones_url":"https://api.github.com/repos/openlayers/ol3/milestones{/number}","notifications_url":"https://api.github.com/repos/openlayers/ol3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openlayers/ol3/labels{/name}","releases_url":"https://api.github.com/repos/openlayers/ol3/releases{/id}","created_at":"2012-06-20T06:53:59Z","updated_at":"2015-11-16T16:51:26Z","pushed_at":"2015-11-17T17:46:14Z","git_url":"git://github.com/openlayers/ol3.git","ssh_url":"git@github.com:openlayers/ol3.git","clone_url":"https://github.com/openlayers/ol3.git","svn_url":"https://github.com/openlayers/ol3","homepage":"http://openlayers.org","size":77588,"stargazers_count":1496,"watchers_count":1496,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":845,"mirror_url":null,"open_issues_count":370,"forks":845,"open_issues":370,"watchers":1496,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/4440"},"html":{"href":"https://github.com/openlayers/ol3/pull/4440"},"issue":{"href":"https://api.github.com/repos/openlayers/ol3/issues/4440"},"comments":{"href":"https://api.github.com/repos/openlayers/ol3/issues/4440/comments"},"review_comments":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/4440/comments"},"review_comment":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/4440/commits"},"statuses":{"href":"https://api.github.com/repos/openlayers/ol3/statuses/5c7b719335635281d6eb2edc053cef513cf90cb5"}}}}