Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the new proj4.js #1228

Merged
merged 19 commits into from Jul 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 2 additions & 23 deletions build.py
Expand Up @@ -128,10 +128,6 @@
if path.endswith('.js')
if path not in SHADER_SRC]

PROJ4JS = 'build/proj4js/lib/proj4js-combined.js'
PROJ4JS_ZIP = 'build/proj4js-1.1.0.zip'
PROJ4JS_ZIP_MD5 = '17caad64cf6ebc6e6fe62f292b134897'


def report_sizes(t):
stringio = StringIO()
Expand Down Expand Up @@ -348,7 +344,7 @@ def action(t):
return Target(name, action=action, dependencies=dependencies)


@target('serve', PROJ4JS, 'examples')
@target('serve', 'examples')
def serve(t):
t.run('node', 'tasks/serve.js')

Expand Down Expand Up @@ -671,24 +667,7 @@ def check_examples(t):
t.run('%(PHANTOMJS)s', 'bin/check-example.js', example)


@target(PROJ4JS, PROJ4JS_ZIP)
def proj4js(t):
from zipfile import ZipFile
zf = ZipFile(PROJ4JS_ZIP)
contents = zf.open('proj4js/lib/proj4js-combined.js').read()
with open(t.name, 'wb') as f:
f.write(contents)


@target(PROJ4JS_ZIP, clean=False)
def proj4js_zip(t):
t.info('downloading %r', t.name)
t.download('http://download.osgeo.org/proj4js/' +
os.path.basename(t.name), md5=PROJ4JS_ZIP_MD5)
t.info('downloaded %r', t.name)


@target('test', PROJ4JS, phony=True)
@target('test', phony=True)
def test(t):
t.run('node', 'tasks/test.js')

Expand Down
9 changes: 3 additions & 6 deletions examples/wms-custom-proj.html
Expand Up @@ -8,7 +8,7 @@
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Tiled WMS with Proj4js projection example</title>
<title>Tiled WMS with custom projection example</title>
</head>
<body>

Expand All @@ -31,21 +31,18 @@
<div class="row-fluid">

<div class="span12">
<h4 id="title">Tiled WMS with Proj4js projection example</h4>
<h4 id="title">Tiled WMS with custom projection example</h4>
<p id="shortdesc">Example of two tiled WMS layers (Pixelmap 1:1'000'000 and national parks) using the projection EPSG:21781.</p>
<div id="docs">
<p>See the <a href="wms-custom-proj.js" target="_blank">wms-custom-proj.js source</a> to see how this is done.</p>
</div>
<div id="tags">wms, tile, tilelayer, proj4js, projection</div>
<div id="tags">wms, tile, tilelayer, projection</div>
</div>

</div>

</div>

<script src="jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/proj4js-compressed.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/defs/EPSG21781.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=wms-custom-proj" type="text/javascript"></script>

Expand Down
186 changes: 183 additions & 3 deletions examples/wms-custom-proj.js
Expand Up @@ -5,13 +5,41 @@ goog.require('ol.control');
goog.require('ol.control.ScaleLine');
goog.require('ol.layer.Tile');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
goog.require('ol.source.TileWMS');


var projection = ol.proj.configureProj4jsProjection({

// By default OpenLayers does not know about the EPSG:21781 (Swiss) projection.
// So we create a projection instance for EPSG:21781 and pass it to
// ol.proj.addProjection to make it available to the library.

var projection = new ol.proj.Projection({
code: 'EPSG:21781',
extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864]
// The extent is used to determine zoom level 0. Recommended values for a
// projection's validity extent can be found at http://epsg.io/.
extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864],
units: 'm'
});
ol.proj.addProjection(projection);

// We also declare EPSG:21781/EPSG:4326 transform functions. These functions
// are necessary for the ScaleLine control and when calling ol.proj.transform
// for setting the view's initial center (see below).

ol.proj.addCoordinateTransforms('EPSG:4326', projection,
function(coordinate) {
return [
WGStoCHy(coordinate[1], coordinate[0]),
WGStoCHx(coordinate[1], coordinate[0])
];
},
function(coordinate) {
return [
CHtoWGSlng(coordinate[0], coordinate[1]),
CHtoWGSlat(coordinate[0], coordinate[1])
];
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you cherry-pick https://github.com/elemoine/ol3/commit/6524124a763a7185e948408f4a5b9cf65d786ff3 for more explanations on the use of a custom projection and custom transforms in this example?


var extent = [420000, 30000, 900000, 350000];
var layers = [
Expand Down Expand Up @@ -61,8 +89,160 @@ var map = new ol.Map({
target: 'map',
view: new ol.View({
projection: projection,
center: [660000, 190000],
center: ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781'),
extent: extent,
zoom: 2
})
});



/*
* Swiss projection transform functions downloaded from
* http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html
*/

// Convert WGS lat/long (° dec) to CH y
function WGStoCHy(lat, lng) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My editor's linter complains that these functions are used before they are defined. We could move them at the beginning of the file but this will make the example's code harder to read and understand. So let's keep them here. My eyes will bleed each time I open this file but I guess it's ok :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, and the reason why I decided to move the swisstopo code to the bottom was readability of the example code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elemoine set the "predef":"nofunc" option on your linter for this project (assuming it's jshint)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already did :-) Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could put this code in a separate file

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the file is not compiled it will externs. We do that already for things that are in resources/example-behaviour.js.

But in this case I find it's good to have these function in the example's js file, because it gives more context to the reader, and thereby makes things easier to understand. So I'd rather keep them here.


// Converts degrees dec to sex
lat = DECtoSEX(lat);
lng = DECtoSEX(lng);

// Converts degrees to seconds (sex)
lat = DEGtoSEC(lat);
lng = DEGtoSEC(lng);

// Axiliary values (% Bern)
var lat_aux = (lat - 169028.66) / 10000;
var lng_aux = (lng - 26782.5) / 10000;

// Process Y
var y = 600072.37 +
211455.93 * lng_aux -
10938.51 * lng_aux * lat_aux -
0.36 * lng_aux * Math.pow(lat_aux, 2) -
44.54 * Math.pow(lng_aux, 3);

return y;
}

// Convert WGS lat/long (° dec) to CH x
function WGStoCHx(lat, lng) {

// Converts degrees dec to sex
lat = DECtoSEX(lat);
lng = DECtoSEX(lng);

// Converts degrees to seconds (sex)
lat = DEGtoSEC(lat);
lng = DEGtoSEC(lng);

// Axiliary values (% Bern)
var lat_aux = (lat - 169028.66) / 10000;
var lng_aux = (lng - 26782.5) / 10000;

// Process X
var x = 200147.07 +
308807.95 * lat_aux +
3745.25 * Math.pow(lng_aux, 2) +
76.63 * Math.pow(lat_aux, 2) -
194.56 * Math.pow(lng_aux, 2) * lat_aux +
119.79 * Math.pow(lat_aux, 3);

return x;

}


// Convert CH y/x to WGS lat
function CHtoWGSlat(y, x) {

// Converts militar to civil and to unit = 1000km
// Axiliary values (% Bern)
var y_aux = (y - 600000) / 1000000;
var x_aux = (x - 200000) / 1000000;

// Process lat
var lat = 16.9023892 +
3.238272 * x_aux -
0.270978 * Math.pow(y_aux, 2) -
0.002528 * Math.pow(x_aux, 2) -
0.0447 * Math.pow(y_aux, 2) * x_aux -
0.0140 * Math.pow(x_aux, 3);

// Unit 10000" to 1 " and converts seconds to degrees (dec)
lat = lat * 100 / 36;

return lat;

}

// Convert CH y/x to WGS long
function CHtoWGSlng(y, x) {

// Converts militar to civil and to unit = 1000km
// Axiliary values (% Bern)
var y_aux = (y - 600000) / 1000000;
var x_aux = (x - 200000) / 1000000;

// Process long
var lng = 2.6779094 +
4.728982 * y_aux +
0.791484 * y_aux * x_aux +
0.1306 * y_aux * Math.pow(x_aux, 2) -
0.0436 * Math.pow(y_aux, 3);

// Unit 10000" to 1 " and converts seconds to degrees (dec)
lng = lng * 100 / 36;

return lng;

}


// Convert SEX DMS angle to DEC
function SEXtoDEC(angle) {

// Extract DMS
var deg = parseInt(angle, 10);
var min = parseInt((angle - deg) * 100, 10);
var sec = (((angle - deg) * 100) - min) * 100;

// Result in degrees sex (dd.mmss)
return deg + (sec / 60 + min) / 60;

}

// Convert DEC angle to SEX DMS
function DECtoSEX(angle) {

// Extract DMS
var deg = parseInt(angle, 10);
var min = parseInt((angle - deg) * 60, 10);
var sec = (((angle - deg) * 60) - min) * 60;

// Result in degrees sex (dd.mmss)
return deg + min / 100 + sec / 10000;

}

// Convert Degrees angle to seconds
function DEGtoSEC(angle) {

// Extract DMS
var deg = parseInt(angle, 10);
var min = parseInt((angle - deg) * 100, 10);
var sec = (((angle - deg) * 100) - min) * 100;

// Avoid rounding problems with seconds=0
var parts = String(angle).split('.');
if (parts.length == 2 && parts[1].length == 2) {
min = Number(parts[1]);
sec = 0;
}

// Result in degrees sex (dd.mmss)
return sec + min * 60 + deg * 3600;

}
10 changes: 5 additions & 5 deletions examples/wms-image-custom-proj.html
Expand Up @@ -8,7 +8,7 @@
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
<title>Single image WMS with custom projection example</title>
<title>Single image WMS with Proj4js projection example</title>
</head>
<body>

Expand All @@ -31,22 +31,22 @@
<div class="row-fluid">

<div class="span12">
<h4 id="title">Single image WMS with custom projection example</h4>
<h4 id="title">Single image WMS with Proj4js projection example</h4>
<p id="shortdesc">Example of two single image WMS layers.</p>
<div id="docs">
<p>Pixelmap 1:1'000'000 with National Parks overlay using the projection EPSG:21781.</p>
<p>See the <a href="wms-image-custom-proj.js" target="_blank">wms-image-custom-proj.js source</a> to see how this is done.</p>
</div>
<div id="tags">wms, single image, projection</div>
<div id="tags">wms, single image, proj4js, projection</div>
</div>

</div>

</div>

<script src="jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/proj4js-compressed.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/1.1.0/defs/EPSG21781.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/proj4js/2.2.1/proj4.js" type="text/javascript"></script>
<script src="http://epsg.io/21781.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=wms-image-custom-proj" type="text/javascript"></script>

Expand Down
19 changes: 14 additions & 5 deletions examples/wms-image-custom-proj.js
@@ -1,15 +1,21 @@
goog.require('ol.Attribution');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.control');
goog.require('ol.control.ScaleLine');
goog.require('ol.layer.Image');
goog.require('ol.proj');
goog.require('ol.source.ImageWMS');


var projection = ol.proj.configureProj4jsProjection({
code: 'EPSG:21781',
extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864]
});
// Transparent Proj4js support: ol.proj.get() creates and returns a projection
// known to Proj4js if it is unknown to OpenLayers, and registers functions to
// transform between all registered projections.
// EPSG:21781 is known to Proj4js because its definition was loaded in the html.
var projection = ol.proj.get('EPSG:21781');
// The extent is used to determine zoom level 0. Recommended values for a
// projection's validity extent can be found at http://epsg.io/.
projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]);

var extent = [420000, 30000, 900000, 350000];
var layers = [
Expand Down Expand Up @@ -49,12 +55,15 @@ var layers = [
];

var map = new ol.Map({
controls: ol.control.defaults().extend([
new ol.control.ScaleLine()
]),
layers: layers,
renderer: exampleNS.getRendererFromQueryString(),
target: 'map',
view: new ol.View({
projection: projection,
center: [660000, 190000],
center: ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781'),
extent: extent,
zoom: 2
})
Expand Down