Compare commits

..

36 Commits

Author SHA1 Message Date
Éric Lemoine
757ccf148b Merge pull request #858 from elemoine/getzoom
Add ol.View2D#getZoom
2013-07-11 00:51:25 -07:00
Éric Lemoine
3e4d39b228 Export ol.View2D#getZoom 2013-07-11 09:50:31 +02:00
Éric Lemoine
d7e838274e Merge pull request #840 from fredj/zoomcontrol
Add ol.control.Zoom#zoomByDelta function
2013-07-09 21:38:41 -07:00
Éric Lemoine
2cc5c7a776 Merge pull request #857 from elemoine/view2d-docs
Better View2D docs
2013-07-09 06:29:12 -07:00
Éric Lemoine
daa03b5ef7 @class doc for View2D 2013-07-09 15:28:31 +02:00
Éric Lemoine
42abdb308a Better docs for View2DOptions 2013-07-09 15:28:31 +02:00
Frederic Junod
17f0d01e9f Add ol.control.Zoom#zoomByDelta function
To replace ol.control.Zoom#handleIn_ and ol.control.Zoom#handleOut_ callbacks.
2013-07-09 14:21:46 +02:00
Éric Lemoine
f72784dc38 Merge pull request #855 from elemoine/zoom-slider-fix
Zoomslider cannot be added to a map with no target
2013-07-09 04:45:50 -07:00
Éric Lemoine
44a9c181aa handleMapPostrender may get a null frameState 2013-07-09 10:06:01 +02:00
Éric Lemoine
ccf6aa10ac Zoomslider cannot be added to a map with no target
The zoom slider control's initSlider_ function requires that the control's element is inserted in the document. So if initSlider_ is called before the map have a target then the slider isn't correctly initialized. This commit fixes that by defering the slider initialization until the first handleMapPostrender call.
2013-07-09 10:05:15 +02:00
Éric Lemoine
a10d142752 Add ol.View2D#getZoom 2013-07-09 09:30:45 +02:00
Tim Schaub
461d85dfc3 Merge pull request #854 from elemoine/remove-gh-pages
Rename build/gh-pages to build/hosted
2013-07-05 17:09:52 -07:00
Tim Schaub
087b4d04a6 Merge pull request #809 from tschaub/clockwise
Consistent winding order for polygon rings.
2013-07-05 17:04:50 -07:00
Éric Lemoine
3af5e530ca Merge pull request #835 from elemoine/setzoom
Add ol.View2D.prototype.setZoom
2013-07-05 12:31:34 -07:00
Éric Lemoine
d9f554e10d Dir build/gh-pages renamed to build/hosted 2013-07-05 20:45:40 +02:00
Tim Schaub
d482b66af3 Doc typo 2013-07-05 11:48:45 -06:00
Éric Lemoine
7efff5c3cf Merge pull request #833 from elemoine/stop-other-interactions
Remove ol.MapBrowserEvent#stopOtherInteractions
2013-07-04 00:48:35 -07:00
Éric Lemoine
d0e198df93 Use constrainResolution function
Use the constrainResolution function when setting the initial view resolution.
2013-07-04 09:16:04 +02:00
Éric Lemoine
e6efa741d2 More type checking for View2D 2013-07-04 09:13:31 +02:00
Éric Lemoine
552853a3b8 Remove unused createContinuous function 2013-07-04 08:58:33 +02:00
Éric Lemoine
0cf4024194 Add ol.View2D.prototype.setZoom 2013-07-04 08:58:32 +02:00
Frédéric Junod
a071c3521c Merge pull request #848 from fredj/geolocation-example
Update geolocation example to display all the properties
2013-07-01 07:28:06 -07:00
Frédéric Junod
6ae4b28db8 Merge pull request #847 from fredj/apidoc
API doc update.
2013-07-01 07:01:35 -07:00
Frederic Junod
e1f8863bd2 Update geolocation example to display all the properties 2013-07-01 15:48:50 +02:00
Frederic Junod
1c3369a3f6 Add className parameter documentation 2013-07-01 15:04:14 +02:00
Tim Schaub
f2ce4db85a Merge pull request #842 from tschaub/examples
Updates to example markup.
2013-06-28 12:15:53 -07:00
Tim Schaub
949edb694e Duplicated id 2013-06-28 10:43:57 -06:00
Tim Schaub
7ebacba720 Use full grid
The example documentation should not be restricted to 1/3 of the row unless there is something else consuming the other 2/3.
2013-06-28 10:42:42 -06:00
Tim Schaub
12338783cc Load scripts in RAW mode by default
On-the-fly compilation is a frustrating default.
2013-06-28 10:07:02 -06:00
Tim Schaub
82c791f9f5 Merge pull request #839 from tschaub/delete-gh-pages-branch
Delete gh-pages branch
2013-06-28 08:26:00 -07:00
Tim Schaub
e1a2c72587 Adjective -> adverb 2013-06-27 16:01:22 -06:00
Tim Schaub
dc246cd45b Correct links to hosted examples (and docs) 2013-06-27 15:59:52 -06:00
Tim Schaub
04bab7e436 The examples and docs are deployed from the openlayers.github.io repo
To deploy the latest docs and examples, see https://github.com/openlayers/openlayers.github.io/blob/build/README.md

tl;dr

    git clone -b build https://github.com/openlayers/openlayers.github.io.git
    cd openlayers.github.io
    npm install
    npm run deploy

Subsequent deploys are simply: `npm run deploy`

This publishes the examples (http://ol3js.org/en/master/examples/) and docs (http://ol3js.org/en/master/apidoc/).

The `build.py gh-pages` target published under different paths (http://ol3js.org/ol3/master/examples/ and http://ol3js.org/ol3/master/apidoc/).  Having two (not always up to date) copies of this content hosted on the same domain is A Bad Idea.
2013-06-27 15:56:11 -06:00
Éric Lemoine
6fc4aa68b6 Remove ol.MapBrowserEvent#stopOtherInteractions
and check for false/true in the return from handleMapBrowserEvent. Refs #791.
2013-06-27 14:43:00 +02:00
Tim Schaub
99ba5a0da8 Store rings so exerior is clockwise and interior is counter-clockwise
KML and WKT don't specify a winding order, so we write those out in CW/CCW order (for exterior/interior).  GML references ISO 19107 that specifies CCW/CW, so we serialize in that winding order.

Having hand generated all this GML data the first time around, I reserve the right to modify it for the tests.
2013-06-24 17:46:36 -06:00
Tim Schaub
e292d8fa12 Add method to determine winding order of linear rings 2013-06-24 17:43:22 -06:00
85 changed files with 524 additions and 349 deletions

View File

@@ -2,8 +2,8 @@
[![Travis CI Status](https://secure.travis-ci.org/openlayers/ol3.png)](http://travis-ci.org/#!/openlayers/ol3) [![Travis CI Status](https://secure.travis-ci.org/openlayers/ol3.png)](http://travis-ci.org/#!/openlayers/ol3)
Welcome to OpenLayers 3! Welcome to [OpenLayers 3](http://ol3js.org/)!
To see OpenLayers 3 in action you can look at the live examples on Check out the [hosted examples](http://ol3js.org/en/master/examples/) or poke around the evolving [API docs](http://ol3js.org/en/master/apidoc/).
http://openlayers.github.io/ol3/master/examples/. If you want to contribute
to OpenLayers 3 please read the [CONTRIBUTING](CONTRIBUTING.md) page. Please see our guide on [contributing](CONTRIBUTING.md) if you're interested in getting involved.

View File

@@ -574,20 +574,6 @@ def plovr_jar(t):
t.info('downloaded %r', t.name) t.info('downloaded %r', t.name)
@target('gh-pages', 'host-examples', 'doc', phony=True)
def gh_pages(t):
with t.tempdir() as tempdir:
t.run('%(GIT)s', 'clone', '--branch', 'gh-pages',
'git@github.com:openlayers/ol3.git', tempdir)
with t.chdir(tempdir):
t.rm_rf('%(BRANCH)s')
t.cp_r('build/gh-pages/%(BRANCH)s', tempdir + '/%(BRANCH)s')
with t.chdir(tempdir):
t.run('%(GIT)s', 'add', '--all', '%(BRANCH)s')
t.run('%(GIT)s', 'commit', '--message', 'Updated')
t.run('%(GIT)s', 'push', 'origin', 'gh-pages')
virtual('doc', 'build/jsdoc-%(BRANCH)s-timestamp' % vars(variables)) virtual('doc', 'build/jsdoc-%(BRANCH)s-timestamp' % vars(variables))
@@ -596,7 +582,7 @@ virtual('doc', 'build/jsdoc-%(BRANCH)s-timestamp' % vars(variables))
SRC, SHADER_SRC, ifind('doc/template')) SRC, SHADER_SRC, ifind('doc/template'))
def jsdoc_BRANCH_timestamp(t): def jsdoc_BRANCH_timestamp(t):
t.run('%(JSDOC)s', '-c', 'doc/conf.json', 'src', 'doc/index.md', t.run('%(JSDOC)s', '-c', 'doc/conf.json', 'src', 'doc/index.md',
'-d', 'build/gh-pages/%(BRANCH)s/apidoc') '-d', 'build/hosted/%(BRANCH)s/apidoc')
t.touch() t.touch()
@@ -634,15 +620,15 @@ def split_example_file(example, dst_dir):
@target('host-resources', phony=True) @target('host-resources', phony=True)
def host_resources(t): def host_resources(t):
resources_dir = 'build/gh-pages/%(BRANCH)s/resources' resources_dir = 'build/hosted/%(BRANCH)s/resources'
t.rm_rf(resources_dir) t.rm_rf(resources_dir)
t.cp_r('resources', resources_dir) t.cp_r('resources', resources_dir)
@target('host-examples', 'build', 'host-resources', 'examples', phony=True) @target('host-examples', 'build', 'host-resources', 'examples', phony=True)
def host_examples(t): def host_examples(t):
examples_dir = 'build/gh-pages/%(BRANCH)s/examples' examples_dir = 'build/hosted/%(BRANCH)s/examples'
build_dir = 'build/gh-pages/%(BRANCH)s/build' build_dir = 'build/hosted/%(BRANCH)s/build'
t.rm_rf(examples_dir) t.rm_rf(examples_dir)
t.makedirs(examples_dir) t.makedirs(examples_dir)
t.rm_rf(build_dir) t.rm_rf(build_dir)
@@ -657,25 +643,25 @@ def host_examples(t):
t.cp('examples/index.html', 'examples/example-list.js', t.cp('examples/index.html', 'examples/example-list.js',
'examples/example-list.xml', 'examples/Jugl.js', 'examples/example-list.xml', 'examples/Jugl.js',
'examples/jquery.min.js', examples_dir) 'examples/jquery.min.js', examples_dir)
t.rm_rf('build/gh-pages/%(BRANCH)s/closure-library') t.rm_rf('build/hosted/%(BRANCH)s/closure-library')
t.makedirs('build/gh-pages/%(BRANCH)s/closure-library') t.makedirs('build/hosted/%(BRANCH)s/closure-library')
with t.chdir('build/gh-pages/%(BRANCH)s/closure-library'): with t.chdir('build/hosted/%(BRANCH)s/closure-library'):
t.run('%(JAR)s', 'xf', '../../../../' + PLOVR_JAR, 'closure') t.run('%(JAR)s', 'xf', '../../../../' + PLOVR_JAR, 'closure')
t.run('%(JAR)s', 'xf', '../../../../' + PLOVR_JAR, 'third_party') t.run('%(JAR)s', 'xf', '../../../../' + PLOVR_JAR, 'third_party')
t.rm_rf('build/gh-pages/%(BRANCH)s/ol') t.rm_rf('build/hosted/%(BRANCH)s/ol')
t.makedirs('build/gh-pages/%(BRANCH)s/ol') t.makedirs('build/hosted/%(BRANCH)s/ol')
t.cp_r('src/ol', 'build/gh-pages/%(BRANCH)s/ol/ol') t.cp_r('src/ol', 'build/hosted/%(BRANCH)s/ol/ol')
t.run('%(PYTHON)s', 'bin/closure/depswriter.py', t.run('%(PYTHON)s', 'bin/closure/depswriter.py',
'--root_with_prefix', 'src ../../../ol', '--root_with_prefix', 'src ../../../ol',
'--root', 'build/gh-pages/%(BRANCH)s/closure-library/closure/goog', '--root', 'build/hosted/%(BRANCH)s/closure-library/closure/goog',
'--root_with_prefix', 'build/gh-pages/%(BRANCH)s/closure-library/' '--root_with_prefix', 'build/hosted/%(BRANCH)s/closure-library/'
'third_party ../../third_party', 'third_party ../../third_party',
'--output_file', 'build/gh-pages/%(BRANCH)s/build/ol-deps.js') '--output_file', 'build/hosted/%(BRANCH)s/build/ol-deps.js')
@target('check-examples', 'host-examples', phony=True) @target('check-examples', 'host-examples', phony=True)
def check_examples(t): def check_examples(t):
examples = ['build/gh-pages/%(BRANCH)s/' + e for e in EXAMPLES] examples = ['build/hosted/%(BRANCH)s/' + e for e in EXAMPLES]
all_examples = \ all_examples = \
[e + '?mode=raw' for e in examples] + \ [e + '?mode=raw' for e in examples] + \
[e + '?mode=whitespace' for e in examples] + \ [e + '?mode=whitespace' for e in examples] + \

View File

@@ -1,5 +1,5 @@
Finding your way round Finding your way around
---------------------- -----------------------
See the class list to the right and especially take a look at {@link ol.Map} and {@link ol.layer.Layer} because those are the central objects. See the class list to the right and especially take a look at {@link ol.Map} and {@link ol.layer.Layer} because those are the central objects.
In general every use of OpenLayers starts by initializing a map, then adding the required layers. Controls and interactions can be added to change the behavior of the map. In general every use of OpenLayers starts by initializing a map, then adding the required layers. Controls and interactions can be added to change the behavior of the map.

View File

@@ -48,7 +48,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Animation example</h4> <h4 id="title">Animation example</h4>
<p id="shortdesc">Demonstrates animated pan, zoom, and rotation.</p> <p id="shortdesc">Demonstrates animated pan, zoom, and rotation.</p>
<div id="docs"> <div id="docs">

View File

@@ -41,7 +41,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Bing Maps example</h4> <h4 id="title">Bing Maps example</h4>
<p id="shortdesc">Example of a Bing Maps layer.</p> <p id="shortdesc">Example of a Bing Maps layer.</p>
<div id="docs"> <div id="docs">

View File

@@ -53,7 +53,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Brightness/contrast example</h4> <h4 id="title">Brightness/contrast example</h4>
<p id="shortdesc">Example of brightness/contrast control on the client (WebGL only).</p> <p id="shortdesc">Example of brightness/contrast control on the client (WebGL only).</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Canvas tiles example</h4> <h4 id="title">Canvas tiles example</h4>
<p id="shortdesc">Renders tiles with coordinates for debugging.</p> <p id="shortdesc">Renders tiles with coordinates for debugging.</p>
<div id="docs"> <div id="docs">

View File

@@ -68,7 +68,7 @@
</div> </div>
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Custom controls</h4> <h4 id="title">Custom controls</h4>
<p id="shortdesc">This example shows how to create custom controls.</p> <p id="shortdesc">This example shows how to create custom controls.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Device orientation example</h4> <h4 id="title">Device orientation example</h4>
<label class="checkbox" for="track"> <label class="checkbox" for="track">
<input id="track" type="checkbox"/>track changes <input id="track" type="checkbox"/>track changes

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Drag rotate and zoom example</h4> <h4 id="title">Drag rotate and zoom example</h4>
<p id="shortdesc">A single interaction to drag, rotate, and zoom.</p> <p id="shortdesc">A single interaction to drag, rotate, and zoom.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">EPSG:4326 example</h4> <h4 id="title">EPSG:4326 example</h4>
<p id="shortdesc">Example of a map in EPSG:4326.</p> <p id="shortdesc">Example of a map in EPSG:4326.</p>
<div id="docs"> <div id="docs">

View File

@@ -37,7 +37,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Export map example</h4> <h4 id="title">Export map example</h4>
<p id="shortdesc">Example of exporting a map as a JPEG or PNG image.</p> <p id="shortdesc">Example of exporting a map as a JPEG or PNG image.</p>
<div id="docs"> <div id="docs">

View File

@@ -46,7 +46,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Full screen drag rotate and zoom example</h4> <h4 id="title">Full screen drag rotate and zoom example</h4>
<p id="shortdesc">Example of drag rotate and zoom control with full screen effect.</p> <p id="shortdesc">Example of drag rotate and zoom control with full screen effect.</p>
<div id="docs"> <div id="docs">

View File

@@ -46,7 +46,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Full screen control example</h4> <h4 id="title">Full screen control example</h4>
<p id="shortdesc">Example of a full screen control.</p> <p id="shortdesc">Example of a full screen control.</p>
<div id="docs"> <div id="docs">

View File

@@ -44,13 +44,21 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Geolocation example</h4> <h4 id="title">Geolocation example</h4>
<label class="checkbox" for="track">
<input id="track" type="checkbox"/>track position
</label>
<p>position accuracy : <code id="accuracy"></code></p>
<p>altitude : <code id="altitude"></code></p>
<p>altitude accuracy : <code id="altitudeAccuracy"></code></p>
<p>heading : <code id="heading"></code></p>
<p>speed : <code id="speed"></code></p>
<p id="shortdesc">Example of a geolocation map.</p> <p id="shortdesc">Example of a geolocation map.</p>
<div id="docs"> <div id="docs">
<p>See the <a href="geolocation.js" target="_blank">geolocation.js source</a> to see how this is done.</p> <p>See the <a href="geolocation.js" target="_blank">geolocation.js source</a> to see how this is done.</p>
</div> </div>
<button id="locate"><i class="icon-screenshot"></i> locate</button>
<div id="tags">geolocation, openstreetmap</div> <div id="tags">geolocation, openstreetmap</div>
</div> </div>
<div class="span4 pull-right"> <div class="span4 pull-right">

View File

@@ -3,6 +3,7 @@ goog.require('ol.Map');
goog.require('ol.Overlay'); goog.require('ol.Overlay');
goog.require('ol.RendererHints'); goog.require('ol.RendererHints');
goog.require('ol.View2D'); goog.require('ol.View2D');
goog.require('ol.dom.Input');
goog.require('ol.layer.TileLayer'); goog.require('ol.layer.TileLayer');
goog.require('ol.source.OSM'); goog.require('ol.source.OSM');
@@ -24,6 +25,17 @@ var map = new ol.Map({
var geolocation = new ol.Geolocation(); var geolocation = new ol.Geolocation();
geolocation.bindTo('projection', map.getView()); geolocation.bindTo('projection', map.getView());
var track = new ol.dom.Input(document.getElementById('track'));
track.bindTo('checked', geolocation, 'tracking');
geolocation.on('change', function() {
$('#accuracy').text(geolocation.getAccuracy() + ' [m]');
$('#altitude').text(geolocation.getAltitude() + ' [m]');
$('#altitudeAccuracy').text(geolocation.getAltitudeAccuracy() + ' [m]');
$('#heading').text(geolocation.getHeading() + ' [rad]');
$('#speed').text(geolocation.getSpeed() + ' [m/s]');
});
var marker = new ol.Overlay({ var marker = new ol.Overlay({
map: map, map: map,
element: /** @type {Element} */ ($('<i/>').addClass('icon-flag').get(0)) element: /** @type {Element} */ ($('<i/>').addClass('icon-flag').get(0))
@@ -41,8 +53,3 @@ geolocation.on('error', function(error) {
info.innerHTML = error.message; info.innerHTML = error.message;
info.style.display = ''; info.style.display = '';
}); });
$('#locate').click(function() {
geolocation.setTracking(true);
});

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">GML example</h4> <h4 id="title">GML example</h4>
<p id="shortdesc">Example of using the GML parser.</p> <p id="shortdesc">Example of using the GML parser.</p>
<div id="docs"> <div id="docs">

View File

@@ -43,7 +43,7 @@
</div> </div>
<div id="tags">GPX</div> <div id="tags">GPX</div>
</div> </div>
<div class="span4 pull-right"> <div class="span4 offset4">
<div id="info" class="alert alert-success"> <div id="info" class="alert alert-success">
&nbsp; &nbsp;
</div> </div>

View File

@@ -53,7 +53,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Hue/saturation example</h4> <h4 id="title">Hue/saturation example</h4>
<p id="shortdesc">Example of hue/saturation control on the client (WebGL only).</p> <p id="shortdesc">Example of hue/saturation control on the client (WebGL only).</p>
<div id="docs"> <div id="docs">

View File

@@ -46,7 +46,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Timezones in KML</h4> <h4 id="title">Timezones in KML</h4>
<p id="shortdesc">Demonstrates rendering timezones from KML.</p> <p id="shortdesc">Demonstrates rendering timezones from KML.</p>
<div id="docs"> <div id="docs">

View File

@@ -43,7 +43,7 @@
</div> </div>
<div id="tags">KML</div> <div id="tags">KML</div>
</div> </div>
<div class="span4 pull-right"> <div class="span4 offset4">
<div id="info" class="alert alert-success"> <div id="info" class="alert alert-success">
&nbsp; &nbsp;
</div> </div>

View File

@@ -8,7 +8,7 @@
* *
* * hostname - the current hostname (window.location.hostname) * * hostname - the current hostname (window.location.hostname)
* * port - 9810 * * port - 9810
* * mode - ADVANCED * * mode - RAW
* * id - id param in loader.js query string; defaults to 'ol' if not set * * id - id param in loader.js query string; defaults to 'ol' if not set
* *
* Usage: * Usage:
@@ -20,7 +20,7 @@
var params = { var params = {
hostname: window.location.hostname, hostname: window.location.hostname,
port: '9810', port: '9810',
mode: 'ADVANCED', mode: 'RAW',
id: 'ol' id: 'ol'
}; };
if (window.location.protocol === 'file:' && !params.hostname) { if (window.location.protocol === 'file:' && !params.hostname) {

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Localized OpenStreetMap example</h4> <h4 id="title">Localized OpenStreetMap example</h4>
<p id="shortdesc">Example of a localized OpenStreetMap map with a custom tile server and a custom attribution.</p> <p id="shortdesc">Example of a localized OpenStreetMap map with a custom tile server and a custom attribution.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">MapQuest example</h4> <h4 id="title">MapQuest example</h4>
<p id="shortdesc">Example of a MapQuest map.</p> <p id="shortdesc">Example of a MapQuest map.</p>
<div id="docs"> <div id="docs">

View File

@@ -34,22 +34,13 @@
</div> </div>
<div class="row-fluid"> <div class="row-fluid">
<div class="span6">
<div class="span4">
<h4 id="title">Mouse position example</h4> <h4 id="title">Mouse position example</h4>
<p id="shortdesc">Example of a mouse position control, outside the map.</p> <p id="shortdesc">Example of a mouse position control, outside the map.</p>
<div id="docs"> <div id="docs">
<p>See the <a href="mouse-position.js" target="_blank">mouse-position.js source</a> to see how this is done.</p> <p>See the <a href="mouse-position.js" target="_blank">mouse-position.js source</a> to see how this is done.</p>
</div> </div>
<div id="tags">mouse-position, openstreetmap</div> <div id="tags">mouse-position, openstreetmap</div>
</div>
<div class="span8 pull-right">
<div id="mouse-position">&nbsp;</div>
</div>
</div>
<div class="row-fluid">
<div class="span8">
<form> <form>
<label>Projection </label> <label>Projection </label>
<select id="projection"> <select id="projection">
@@ -60,6 +51,7 @@
<input id="precision" type="number" min="0" max="12" value="4"/> <input id="precision" type="number" min="0" max="12" value="4"/>
</form> </form>
</div> </div>
<div class="span6" id="mouse-position">&nbsp;</div>
</div> </div>
</div> </div>

View File

@@ -47,7 +47,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Overlay example</h4> <h4 id="title">Overlay example</h4>
<p id="shortdesc">Demonstrates overlays.</p> <p id="shortdesc">Demonstrates overlays.</p>
<div id="docs"> <div id="docs">

View File

@@ -38,11 +38,11 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Preload example</h4> <h4 id="title">Preload example</h4>
<p id="shortdesc">Example of tile preloading.</p> <p id="shortdesc">Example of tile preloading.</p>
<div id="docs"> <div id="docs">
<p>Low resolution tiles for the map are preloaded, the map on the right does not use any preloading. Try zooming out and panning to see the difference.</p> <p>The map on the left preloads low resolution tiles. The map on the right does not use any preloading. Try zooming out and panning to see the difference.</p>
<p>See the <a href="preload.js" target="_blank">preload.js source</a> to see how this is done.</p> <p>See the <a href="preload.js" target="_blank">preload.js source</a> to see how this is done.</p>
</div> </div>
<div id="tags">preload, bing</div> <div id="tags">preload, bing</div>

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Rotation example</h4> <h4 id="title">Rotation example</h4>
<p id="shortdesc">Example of a rotated map.</p> <p id="shortdesc">Example of a rotated map.</p>
<div id="docs"> <div id="docs">

View File

@@ -40,7 +40,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Scale line example</h4> <h4 id="title">Scale line example</h4>
<p id="shortdesc">Example of a scale line.</p> <p id="shortdesc">Example of a scale line.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Semi-transparent layer example</h4> <h4 id="title">Semi-transparent layer example</h4>
<p id="shortdesc">Example of a map with a semi-transparent layer.</p> <p id="shortdesc">Example of a map with a semi-transparent layer.</p>
<div id="docs"> <div id="docs">

View File

@@ -44,7 +44,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Side-by-side example</h4> <h4 id="title">Side-by-side example</h4>
<p id="shortdesc">The three maps, one WebGL, one Canvas, one DOM, share the same center, resolution, rotation and layers.</p> <p id="shortdesc">The three maps, one WebGL, one Canvas, one DOM, share the same center, resolution, rotation and layers.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Simple example</h4> <h4 id="title">Simple example</h4>
<p id="shortdesc">Example of a simple map.</p> <p id="shortdesc">Example of a simple map.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Stamen example</h4> <h4 id="title">Stamen example</h4>
<p id="shortdesc">Example of a Stamen tile source. Two layers are composed: the watercolor base layer with the terrain labels.</p> <p id="shortdesc">Example of a Stamen tile source. Two layers are composed: the watercolor base layer with the terrain labels.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Style with rules example</h4> <h4 id="title">Style with rules example</h4>
<p id="shortdesc">Draws features with rule based styles.</p> <p id="shortdesc">Draws features with rule based styles.</p>
<div id="docs"> <div id="docs">

View File

@@ -44,7 +44,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span6"> <div class="span12">
<h4 id="title">Teleport example</h4> <h4 id="title">Teleport example</h4>
<p id="shortdesc">Example of moving a map from one target to another.</p> <p id="shortdesc">Example of moving a map from one target to another.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Ten thousand points example</h4> <h4 id="title">Ten thousand points example</h4>
<p id="shortdesc">Example of a map with ten thousand points.</p> <p id="shortdesc">Example of a map with ten thousand points.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">TileJSON example</h4> <h4 id="title">TileJSON example</h4>
<p id="shortdesc">Example of a TileJSON layer.</p> <p id="shortdesc">Example of a TileJSON layer.</p>
<div id="docs"> <div id="docs">

View File

@@ -43,7 +43,7 @@
</div> </div>
<div id="tags">vector, geojson, style</div> <div id="tags">vector, geojson, style</div>
</div> </div>
<div class="span4 pull-right"> <div class="span4 offset4">
<div id="info" class="alert alert-success"> <div id="info" class="alert alert-success">
&nbsp; &nbsp;
</div> </div>

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Tiled WMS with Proj4js projection example</h4> <h4 id="title">Tiled WMS with Proj4js 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> <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"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">WMS without client projection example</h4> <h4 id="title">WMS without client projection example</h4>
<p id="shortdesc">Example of two WMS layers using the projection EPSG:21781, which is unknown to the client.</p> <p id="shortdesc">Example of two WMS layers using the projection EPSG:21781, which is unknown to the client.</p>
<div id="docs"> <div id="docs">

View File

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

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Single image WMS example</h4> <h4 id="title">Single image WMS example</h4>
<p id="shortdesc">Example of a single image WMS layer.</p> <p id="shortdesc">Example of a single image WMS layer.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">Tiled WMS example</h4> <h4 id="title">Tiled WMS example</h4>
<p id="shortdesc">Example of a tiled WMS layer.</p> <p id="shortdesc">Example of a tiled WMS layer.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">WMTS from capabilities example</h4> <h4 id="title">WMTS from capabilities example</h4>
<p id="shortdesc">Example of a WMTS source built from a WMTS getCapabilities response.</p> <p id="shortdesc">Example of a WMTS source built from a WMTS getCapabilities response.</p>
<div id="docs"> <div id="docs">

View File

@@ -35,7 +35,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">WMTS example</h4> <h4 id="title">WMTS example</h4>
<p id="shortdesc">Example of a WMTS source.</p> <p id="shortdesc">Example of a WMTS source.</p>
<div id="docs"> <div id="docs">

View File

@@ -96,7 +96,7 @@
<div class="row-fluid"> <div class="row-fluid">
<div class="span4"> <div class="span12">
<h4 id="title">ZoomSlider control</h4> <h4 id="title">ZoomSlider control</h4>
<p id="shortdesc">Example of various ZoomSlider controls.</p> <p id="shortdesc">Example of various ZoomSlider controls.</p>
<div id="docs"> <div id="docs">

View File

@@ -88,21 +88,33 @@
/** /**
* Object literal with config options for the view. * Object literal with config options for the view.
* @typedef {Object} ol.View2DOptions * @typedef {Object} ol.View2DOptions
* @property {ol.Coordinate|undefined} center The view center in map projection. * @property {ol.Coordinate|undefined} center The initial center for the view.
* @property {number|undefined} maxResolution The maximum resolution in map * The coordinate system for the center is specified with the `projection`
* units per pixel. * option.
* @property {number|undefined} maxZoom The maximum zoom level for this view. * @property {number|undefined} maxResolution The maximum resolution used to
* Zoom level 0 uses the `maxResolution`; subsequent zoom levels are * determine the resolution constraint. It is used together with `maxZoom`
* calculated by dividing the previous resolution by `zoomFactor`. * and `zoomFactor`. If unspecified it is calculated in such a way that the
* @property {ol.ProjectionLike} projection The map projection. * projection's validity extent fits in a 256x256 px tile. If the projection
* is Spherical Mercator (the default) then `maxResolution` defaults to
* 40075016.68557849 / 256 = 156543.03392804097.
* @property {number|undefined} maxZoom The maximum zoom level used to determine
* the resolution constraint. It is used together with `maxResolution` and
* `zoomFactor`. Default is 28.
* @property {ol.ProjectionLike} projection The projection. Default is
* `EPSG:3857` (Spherical Mercator).
* @property {number|undefined} resolution The initial resolution for the view. * @property {number|undefined} resolution The initial resolution for the view.
* @property {Array.<number>|undefined} resolutions The resolutions for this * The units are `projection` units per pixel (e.g. meters per pixel).
* view. If configured, this is equivalent to specifying `maxResolution` and * @property {Array.<number>|undefined} resolutions Resolutions to determine the
* `maxZoom`. * resolution constraint. If set the `maxResolution`, `maxZoom` and
* @property {number|undefined} rotation Initial rotation of the view. * `zoomFactor` options are ignored.
* @property {number|undefined} zoom Initial zoom level of the view. * @property {number|undefined} rotation The initial rotation for the view
* @property {number|undefined} zoomFactor Factor to calculate resolutions for * in radians (positive rotation clockwise).
* zoom levels. Default is 2. * @property {number|undefined} zoom Zoom level used to calculate the initial
* resolution for the view. The initial resolution is determined using the
* `ol.View2D#constrainResolution` method.
* @property {number|undefined} zoomFactor The zoom factor used to determine the
* resolution constraint. It is together with `maxResolution` and `maxZoom`.
* Default is 2.
*/ */
/** /**
@@ -139,7 +151,7 @@
/** /**
* @typedef {Object} ol.control.AttributionOptions * @typedef {Object} ol.control.AttributionOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS class name. Default is 'ol-attribution'.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {Element|undefined} target Target. * @property {Element|undefined} target Target.
*/ */
@@ -164,7 +176,7 @@
/** /**
* @typedef {Object} ol.control.FullScreenOptions * @typedef {Object} ol.control.FullScreenOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS class name. Default is 'ol-full-screen'.
* @property {boolean|undefined} keys Full keyboard access. * @property {boolean|undefined} keys Full keyboard access.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {Element|undefined} target Target. * @property {Element|undefined} target Target.
@@ -172,25 +184,26 @@
/** /**
* @typedef {Object} ol.control.LogoOptions * @typedef {Object} ol.control.LogoOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS class name. Default is 'ol-logo'.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {Element|undefined} target Target. * @property {Element|undefined} target Target.
*/ */
/** /**
* @typedef {Object} ol.control.MousePositionOptions * @typedef {Object} ol.control.MousePositionOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS class name. Default is 'ol-mouse-position'.
* @property {ol.CoordinateFormatType|undefined} coordinateFormat Coordinate * @property {ol.CoordinateFormatType|undefined} coordinateFormat Coordinate
* format. * format.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {ol.ProjectionLike} projection Projection. * @property {ol.ProjectionLike} projection Projection.
* @property {Element|undefined} target Target. * @property {Element|undefined} target Target.
* @property {string|undefined} undefinedHTML Markup for undefined coordinates. * @property {string|undefined} undefinedHTML Markup for undefined coordinates.
* Default is '' (empty string).
*/ */
/** /**
* @typedef {Object} ol.control.ScaleLineOptions * @typedef {Object} ol.control.ScaleLineOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS Class name. Default is 'ol-scale-line'.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {number|undefined} minWidth Minimum width in pixels. * @property {number|undefined} minWidth Minimum width in pixels.
* @property {Element|undefined} target Target. * @property {Element|undefined} target Target.
@@ -199,15 +212,15 @@
/** /**
* @typedef {Object} ol.control.ZoomOptions * @typedef {Object} ol.control.ZoomOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS class name. Default is 'ol-zoom'.
* @property {number|undefined} delta Delta. * @property {number|undefined} delta The zoom delta applied on each click.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {Element|undefined} target Target. * @property {Element|undefined} target Target.
*/ */
/** /**
* @typedef {Object} ol.control.ZoomSliderOptions * @typedef {Object} ol.control.ZoomSliderOptions
* @property {string|undefined} className Class name. * @property {string|undefined} className CSS class name.
* @property {ol.Map|undefined} map Map. * @property {ol.Map|undefined} map Map.
* @property {number|undefined} maxResolution Maximum resolution. * @property {number|undefined} maxResolution Maximum resolution.
* @property {number|undefined} minResolution Minimum resolution. * @property {number|undefined} minResolution Minimum resolution.

View File

@@ -33,6 +33,8 @@ ol.control.Zoom = function(opt_options) {
var className = goog.isDef(options.className) ? options.className : 'ol-zoom'; var className = goog.isDef(options.className) ? options.className : 'ol-zoom';
var delta = goog.isDef(options.delta) ? options.delta : 1;
var inElement = goog.dom.createDom(goog.dom.TagName.A, { var inElement = goog.dom.createDom(goog.dom.TagName.A, {
'href': '#zoomIn', 'href': '#zoomIn',
'class': className + '-in' 'class': className + '-in'
@@ -40,7 +42,7 @@ ol.control.Zoom = function(opt_options) {
goog.events.listen(inElement, [ goog.events.listen(inElement, [
goog.events.EventType.TOUCHEND, goog.events.EventType.TOUCHEND,
goog.events.EventType.CLICK goog.events.EventType.CLICK
], this.handleIn_, false, this); ], goog.partial(ol.control.Zoom.prototype.zoomByDelta_, delta), false, this);
var outElement = goog.dom.createDom(goog.dom.TagName.A, { var outElement = goog.dom.createDom(goog.dom.TagName.A, {
'href': '#zoomOut', 'href': '#zoomOut',
@@ -49,7 +51,7 @@ ol.control.Zoom = function(opt_options) {
goog.events.listen(outElement, [ goog.events.listen(outElement, [
goog.events.EventType.TOUCHEND, goog.events.EventType.TOUCHEND,
goog.events.EventType.CLICK goog.events.EventType.CLICK
], this.handleOut_, false, this); ], goog.partial(ol.control.Zoom.prototype.zoomByDelta_, -delta), false, this);
var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE; var cssClasses = className + ' ' + ol.css.CLASS_UNSELECTABLE;
var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, inElement, var element = goog.dom.createDom(goog.dom.TagName.DIV, cssClasses, inElement,
@@ -61,46 +63,17 @@ ol.control.Zoom = function(opt_options) {
target: options.target target: options.target
}); });
/**
* @type {number}
* @private
*/
this.delta_ = goog.isDef(options.delta) ? options.delta : 1;
}; };
goog.inherits(ol.control.Zoom, ol.control.Control); goog.inherits(ol.control.Zoom, ol.control.Control);
/** /**
* @param {number} delta Zoom delta.
* @param {goog.events.BrowserEvent} browserEvent The browser event to handle. * @param {goog.events.BrowserEvent} browserEvent The browser event to handle.
* @private * @private
*/ */
ol.control.Zoom.prototype.handleIn_ = function(browserEvent) { ol.control.Zoom.prototype.zoomByDelta_ = function(delta, browserEvent) {
// prevent #zoomIn anchor from getting appended to the url // prevent the anchor from getting appended to the url
browserEvent.preventDefault();
var map = this.getMap();
map.requestRenderFrame();
// FIXME works for View2D only
var view = map.getView().getView2D();
var currentResolution = view.getResolution();
if (goog.isDef(currentResolution)) {
map.addPreRenderFunction(ol.animation.zoom({
resolution: currentResolution,
duration: ol.control.ZOOM_DURATION,
easing: ol.easing.easeOut
}));
}
var resolution = view.constrainResolution(currentResolution, this.delta_);
view.setResolution(resolution);
};
/**
* @param {goog.events.BrowserEvent} browserEvent The browser event to handle.
* @private
*/
ol.control.Zoom.prototype.handleOut_ = function(browserEvent) {
// prevent #zoomOut anchor from getting appended to the url
browserEvent.preventDefault(); browserEvent.preventDefault();
var map = this.getMap(); var map = this.getMap();
// FIXME works for View2D only // FIXME works for View2D only
@@ -112,7 +85,7 @@ ol.control.Zoom.prototype.handleOut_ = function(browserEvent) {
duration: ol.control.ZOOM_DURATION, duration: ol.control.ZOOM_DURATION,
easing: ol.easing.easeOut easing: ol.easing.easeOut
})); }));
var newResolution = view.constrainResolution(currentResolution, delta);
view.setResolution(newResolution);
} }
var resolution = view.constrainResolution(currentResolution, -this.delta_);
view.setResolution(resolution);
}; };

View File

@@ -62,6 +62,13 @@ ol.control.ZoomSlider = function(opt_options) {
*/ */
this.direction_ = ol.control.ZoomSlider.direction.VERTICAL; this.direction_ = ol.control.ZoomSlider.direction.VERTICAL;
/**
* Whether the slider is initialized.
* @type {boolean}
* @private
*/
this.sliderInitialized_ = false;
/** /**
* @private * @private
* @type {Array.<?number>} * @type {Array.<?number>}
@@ -107,11 +114,8 @@ ol.control.ZoomSlider.direction = {
*/ */
ol.control.ZoomSlider.prototype.setMap = function(map) { ol.control.ZoomSlider.prototype.setMap = function(map) {
goog.base(this, 'setMap', map); goog.base(this, 'setMap', map);
this.initSlider_(); if (!goog.isNull(map)) {
var resolution = map.getView().getView2D().getResolution(); map.render();
if (goog.isDef(resolution)) {
this.currentResolution_ = resolution;
this.positionThumbForResolution_(resolution);
} }
}; };
@@ -147,6 +151,7 @@ ol.control.ZoomSlider.prototype.initSlider_ = function() {
limits = new goog.math.Rect(0, 0, 0, h); limits = new goog.math.Rect(0, 0, 0, h);
} }
this.dragger_.setLimits(limits); this.dragger_.setLimits(limits);
this.sliderInitialized_ = true;
}; };
@@ -154,6 +159,14 @@ ol.control.ZoomSlider.prototype.initSlider_ = function() {
* @inheritDoc * @inheritDoc
*/ */
ol.control.ZoomSlider.prototype.handleMapPostrender = function(mapEvent) { ol.control.ZoomSlider.prototype.handleMapPostrender = function(mapEvent) {
if (goog.isNull(mapEvent.frameState)) {
return;
}
goog.asserts.assert(
goog.isDefAndNotNull(mapEvent.frameState.view2DState));
if (!this.sliderInitialized_) {
this.initSlider_();
}
var res = mapEvent.frameState.view2DState.resolution; var res = mapEvent.frameState.view2DState.resolution;
if (res !== this.currentResolution_) { if (res !== this.currentResolution_) {
this.currentResolution_ = res; this.currentResolution_ = res;

View File

@@ -27,6 +27,42 @@ ol.geom.LinearRing = function(coordinates, opt_shared) {
goog.inherits(ol.geom.LinearRing, ol.geom.LineString); goog.inherits(ol.geom.LinearRing, ol.geom.LineString);
/**
* Determine if a vertex array representing a linear ring is in clockwise
* order.
*
* This method comes from Green's Theorem and was mentioned in an answer to a
* a Stack Overflow question (http://tinyurl.com/clockwise-method).
*
* Note that calculating the cross product for each pair of edges could be
* avoided by first finding the lowest, rightmost vertex. See OGR's
* implementation for an example of this.
* https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp
*
* @param {ol.geom.VertexArray} coordinates Linear ring coordinates.
* @return {boolean} The coordinates are in clockwise order.
*/
ol.geom.LinearRing.isClockwise = function(coordinates) {
var length = coordinates.length;
var edge = 0;
var last = coordinates[length - 1];
var x1 = last[0];
var y1 = last[1];
var x2, y2, coord;
for (var i = 0; i < length; ++i) {
coord = coordinates[i];
x2 = coord[0];
y2 = coord[1];
edge += (x2 - x1) * (y2 + y1);
x1 = x2;
y1 = y2;
}
return edge > 0;
};
/** /**
* @inheritDoc * @inheritDoc
*/ */

View File

@@ -10,6 +10,12 @@ goog.require('ol.geom.VertexArray');
/** /**
* Create a polygon from an array of vertex arrays. Coordinates for the
* exterior ring will be forced to clockwise order. Coordinates for any
* interior rings will be forced to counter-clockwise order. In cases where
* the opposite winding order occurs in the passed vertex arrays, they will
* be modified in place.
*
* @constructor * @constructor
* @extends {ol.geom.Geometry} * @extends {ol.geom.Geometry}
* @param {Array.<ol.geom.VertexArray>} coordinates Array of rings. First * @param {Array.<ol.geom.VertexArray>} coordinates Array of rings. First
@@ -40,8 +46,21 @@ ol.geom.Polygon = function(coordinates, opt_shared) {
* @type {Array.<ol.geom.LinearRing>} * @type {Array.<ol.geom.LinearRing>}
*/ */
this.rings = new Array(numRings); this.rings = new Array(numRings);
var ringCoords;
for (var i = 0; i < numRings; ++i) { for (var i = 0; i < numRings; ++i) {
this.rings[i] = new ol.geom.LinearRing(coordinates[i], vertices); ringCoords = coordinates[i];
if (i === 0) {
// force exterior ring to be clockwise
if (!ol.geom.LinearRing.isClockwise(ringCoords)) {
ringCoords.reverse();
}
} else {
// force interior rings to be counter-clockwise
if (ol.geom.LinearRing.isClockwise(ringCoords)) {
ringCoords.reverse();
}
}
this.rings[i] = new ol.geom.LinearRing(ringCoords, vertices);
} }
/** /**

View File

@@ -41,6 +41,7 @@ goog.inherits(ol.interaction.DoubleClickZoom, ol.interaction.Interaction);
*/ */
ol.interaction.DoubleClickZoom.prototype.handleMapBrowserEvent = ol.interaction.DoubleClickZoom.prototype.handleMapBrowserEvent =
function(mapBrowserEvent) { function(mapBrowserEvent) {
var stopEvent = false;
var browserEvent = mapBrowserEvent.browserEvent; var browserEvent = mapBrowserEvent.browserEvent;
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK && if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DBLCLICK &&
mapBrowserEvent.isMouseActionButton()) { mapBrowserEvent.isMouseActionButton()) {
@@ -52,6 +53,7 @@ ol.interaction.DoubleClickZoom.prototype.handleMapBrowserEvent =
ol.interaction.Interaction.zoomByDelta(map, view, delta, anchor, ol.interaction.Interaction.zoomByDelta(map, view, delta, anchor,
ol.interaction.DOUBLECLICKZOOM_ANIMATION_DURATION); ol.interaction.DOUBLECLICKZOOM_ANIMATION_DURATION);
mapBrowserEvent.preventDefault(); mapBrowserEvent.preventDefault();
mapBrowserEvent.stopOtherInteractions(); stopEvent = true;
} }
return !stopEvent;
}; };

View File

@@ -95,8 +95,9 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent =
function(mapBrowserEvent) { function(mapBrowserEvent) {
var map = mapBrowserEvent.map; var map = mapBrowserEvent.map;
if (!map.isDef()) { if (!map.isDef()) {
return; return true;
} }
var stopEvent = false;
var view = map.getView(); var view = map.getView();
var browserEvent = mapBrowserEvent.browserEvent; var browserEvent = mapBrowserEvent.browserEvent;
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DOWN) { if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.DOWN) {
@@ -132,7 +133,8 @@ ol.interaction.Drag.prototype.handleMapBrowserEvent =
view.setHint(ol.ViewHint.INTERACTING, 1); view.setHint(ol.ViewHint.INTERACTING, 1);
this.dragging_ = true; this.dragging_ = true;
mapBrowserEvent.preventDefault(); mapBrowserEvent.preventDefault();
mapBrowserEvent.stopOtherInteractions(); stopEvent = true;
} }
} }
return !stopEvent;
}; };

View File

@@ -17,6 +17,9 @@ ol.interaction.Interaction = function() {
/** /**
* @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event. * @param {ol.MapBrowserEvent} mapBrowserEvent Map browser event.
* @return {boolean} Whether the map browser event should continue
* through the chain of interactions. false means stop, true
* means continue.
*/ */
ol.interaction.Interaction.prototype.handleMapBrowserEvent = ol.interaction.Interaction.prototype.handleMapBrowserEvent =
goog.abstractMethod; goog.abstractMethod;

View File

@@ -52,6 +52,7 @@ goog.inherits(ol.interaction.KeyboardPan, ol.interaction.Interaction);
*/ */
ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent = ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent =
function(mapBrowserEvent) { function(mapBrowserEvent) {
var stopEvent = false;
if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
var keyEvent = /** @type {goog.events.KeyEvent} */ var keyEvent = /** @type {goog.events.KeyEvent} */
(mapBrowserEvent.browserEvent); (mapBrowserEvent.browserEvent);
@@ -81,7 +82,8 @@ ol.interaction.KeyboardPan.prototype.handleMapBrowserEvent =
ol.interaction.Interaction.pan( ol.interaction.Interaction.pan(
map, view, delta, ol.interaction.KEYBOARD_PAN_DURATION); map, view, delta, ol.interaction.KEYBOARD_PAN_DURATION);
mapBrowserEvent.preventDefault(); mapBrowserEvent.preventDefault();
mapBrowserEvent.stopOtherInteractions(); stopEvent = true;
} }
} }
return !stopEvent;
}; };

View File

@@ -49,6 +49,7 @@ goog.inherits(ol.interaction.KeyboardZoom, ol.interaction.Interaction);
*/ */
ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent = ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent =
function(mapBrowserEvent) { function(mapBrowserEvent) {
var stopEvent = false;
if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) { if (mapBrowserEvent.type == goog.events.KeyHandler.EventType.KEY) {
var keyEvent = /** @type {goog.events.KeyEvent} */ var keyEvent = /** @type {goog.events.KeyEvent} */
(mapBrowserEvent.browserEvent); (mapBrowserEvent.browserEvent);
@@ -63,7 +64,8 @@ ol.interaction.KeyboardZoom.prototype.handleMapBrowserEvent =
ol.interaction.Interaction.zoomByDelta(map, view, delta, undefined, ol.interaction.Interaction.zoomByDelta(map, view, delta, undefined,
ol.interaction.KEYBOARD_ZOOM_DURATION); ol.interaction.KEYBOARD_ZOOM_DURATION);
mapBrowserEvent.preventDefault(); mapBrowserEvent.preventDefault();
mapBrowserEvent.stopOtherInteractions(); stopEvent = true;
} }
} }
return !stopEvent;
}; };

View File

@@ -70,7 +70,7 @@ goog.inherits(ol.interaction.MouseWheelZoom, ol.interaction.Interaction);
*/ */
ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent = ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent =
function(mapBrowserEvent) { function(mapBrowserEvent) {
var stopEvent = false;
if (mapBrowserEvent.type == if (mapBrowserEvent.type ==
goog.events.MouseWheelHandler.EventType.MOUSEWHEEL) { goog.events.MouseWheelHandler.EventType.MOUSEWHEEL) {
var map = mapBrowserEvent.map; var map = mapBrowserEvent.map;
@@ -93,8 +93,9 @@ ol.interaction.MouseWheelZoom.prototype.handleMapBrowserEvent =
goog.bind(this.doZoom_, this, map), timeLeft); goog.bind(this.doZoom_, this, map), timeLeft);
mapBrowserEvent.preventDefault(); mapBrowserEvent.preventDefault();
mapBrowserEvent.stopOtherInteractions(); stopEvent = true;
} }
return !stopEvent;
}; };

View File

@@ -126,4 +126,5 @@ ol.interaction.Touch.prototype.handleMapBrowserEvent =
} }
this.handled_ = handled; this.handled_ = handled;
} }
return true;
}; };

View File

@@ -672,8 +672,8 @@ ol.Map.prototype.handleMapBrowserEvent = function(mapBrowserEvent) {
if (this.dispatchEvent(mapBrowserEvent) !== false) { if (this.dispatchEvent(mapBrowserEvent) !== false) {
for (i = interactionsArray.length - 1; i >= 0; i--) { for (i = interactionsArray.length - 1; i >= 0; i--) {
var interaction = interactionsArray[i]; var interaction = interactionsArray[i];
interaction.handleMapBrowserEvent(mapBrowserEvent); var cont = interaction.handleMapBrowserEvent(mapBrowserEvent);
if (mapBrowserEvent.otherInteractionsStopped) { if (!cont) {
break; break;
} }
} }

View File

@@ -39,11 +39,6 @@ ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) {
*/ */
this.coordinate_ = null; this.coordinate_ = null;
/**
* @type {boolean}
*/
this.otherInteractionsStopped = false;
/** /**
* @private * @private
* @type {ol.Pixel} * @type {ol.Pixel}
@@ -114,14 +109,6 @@ ol.MapBrowserEvent.prototype.preventDefault = function() {
}; };
/**
* Stop the interaction chain.
*/
ol.MapBrowserEvent.prototype.stopOtherInteractions = function() {
this.otherInteractionsStopped = true;
};
/** /**
* Prevents further propagation of the current event. * Prevents further propagation of the current event.
* @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation * @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation

View File

@@ -763,6 +763,10 @@ ol.parser.KML = function(opt_options) {
return node; return node;
}, },
'Polygon': function(geometry) { 'Polygon': function(geometry) {
/**
* KML doesn't specify the winding order of coordinates in linear
* rings. So we keep them as they are in the geometries.
*/
var node = this.createElementNS('Polygon'); var node = this.createElementNS('Polygon');
var coordinates = geometry.getCoordinates(); var coordinates = geometry.getCoordinates();
this.writeNode('outerBoundaryIs', coordinates[0], null, node); this.writeNode('outerBoundaryIs', coordinates[0], null, node);

View File

@@ -67,9 +67,17 @@ ol.parser.ogc.GML_v2 = function(opt_options) {
'Polygon': function(geometry) { 'Polygon': function(geometry) {
var node = this.createElementNS('gml:Polygon'); var node = this.createElementNS('gml:Polygon');
var coordinates = geometry.getCoordinates(); var coordinates = geometry.getCoordinates();
this.writeNode('outerBoundaryIs', coordinates[0], null, node); /**
* Though there continues to be ambiguity around this, GML references
* ISO 19107, which says polygons have counter-clockwise exterior rings
* and clockwise interior rings. The ambiguity comes because the
* the Simple Feature Access - SQL spec (ISO 19125-2) says that no
* winding order is enforced. Anyway, we write out counter-clockwise
* exterior and clockwise interior here but accept either when reading.
*/
this.writeNode('outerBoundaryIs', coordinates[0].reverse(), null, node);
for (var i = 1; i < coordinates.length; ++i) { for (var i = 1; i < coordinates.length; ++i) {
this.writeNode('innerBoundaryIs', coordinates[i], null, node); this.writeNode('innerBoundaryIs', coordinates[i].reverse(), null, node);
} }
return node; return node;
}, },

View File

@@ -298,18 +298,26 @@ ol.parser.ogc.GML_v3 = function(opt_options) {
var node = this.createElementNS('gml:PolygonPatch'); var node = this.createElementNS('gml:PolygonPatch');
node.setAttribute('interpolation', 'planar'); node.setAttribute('interpolation', 'planar');
var coordinates = geometry.getCoordinates(); var coordinates = geometry.getCoordinates();
this.writeNode('exterior', coordinates[0], null, node); this.writeNode('exterior', coordinates[0].reverse(), null, node);
for (var i = 1, len = coordinates.length; i < len; ++i) { for (var i = 1, len = coordinates.length; i < len; ++i) {
this.writeNode('interior', coordinates[i], null, node); this.writeNode('interior', coordinates[i].reverse(), null, node);
} }
return node; return node;
}, },
'Polygon': function(geometry) { 'Polygon': function(geometry) {
var node = this.createElementNS('gml:Polygon'); var node = this.createElementNS('gml:Polygon');
var coordinates = geometry.getCoordinates(); var coordinates = geometry.getCoordinates();
this.writeNode('exterior', coordinates[0], null, node); /**
* Though there continues to be ambiguity around this, GML references
* ISO 19107, which says polygons have counter-clockwise exterior rings
* and clockwise interior rings. The ambiguity comes because the
* the Simple Feature Access - SQL spec (ISO 19125-2) says that no
* winding order is enforced. Anyway, we write out counter-clockwise
* exterior and clockwise interior here but accept either when reading.
*/
this.writeNode('exterior', coordinates[0].reverse(), null, node);
for (var i = 1, len = coordinates.length; i < len; ++i) { for (var i = 1, len = coordinates.length; i < len; ++i) {
this.writeNode('interior', coordinates[i], null, node); this.writeNode('interior', coordinates[i].reverse(), null, node);
} }
return node; return node;
}, },

View File

@@ -11,33 +11,6 @@ goog.require('ol.array');
ol.ResolutionConstraintType; ol.ResolutionConstraintType;
/**
* @param {number} power Power.
* @param {number} maxResolution Maximum resolution.
* @param {number=} opt_minResolution Minimum resolution.
* @return {ol.ResolutionConstraintType} Zoom function.
*/
ol.ResolutionConstraint.createContinuous =
function(power, maxResolution, opt_minResolution) {
var minResolution = opt_minResolution || 0;
return (
/**
* @param {number|undefined} resolution Resolution.
* @param {number} delta Delta.
* @param {number} direction Direction.
* @return {number|undefined} Resolution.
*/
function(resolution, delta, direction) {
if (goog.isDef(resolution)) {
resolution /= Math.pow(power, delta);
return goog.math.clamp(resolution, minResolution, maxResolution);
} else {
return undefined;
}
});
};
/** /**
* @param {Array.<number>} resolutions Resolutions. * @param {Array.<number>} resolutions Resolutions.
* @return {ol.ResolutionConstraintType} Zoom function. * @return {ol.ResolutionConstraintType} Zoom function.

View File

@@ -4,3 +4,5 @@
@exportProperty ol.View2D.prototype.constrainRotation @exportProperty ol.View2D.prototype.constrainRotation
@exportProperty ol.View2D.prototype.fitExtent @exportProperty ol.View2D.prototype.fitExtent
@exportProperty ol.View2D.prototype.getView2D @exportProperty ol.View2D.prototype.getView2D
@exportProperty ol.View2D.prototype.getZoom
@exportProperty ol.View2D.prototype.setZoom

View File

@@ -32,13 +32,51 @@ ol.View2DProperty = {
/** /**
* Create a new View2D, a View2D manages properties such as center, * @class
* projection, resolution and rotation. * An ol.View2D object represents a simple 2D view of the map.
* *
* Example: * This is the object to act upon to change the center, resolution,
* and rotation of the map.
* *
* // to get the current extent * ### The view states
* map.getView().getView2D().calculateExtent(map.getSize()) *
* An `ol.View2D` is determined by three states: `center`, `resolution`,
* and `rotation`. To each state corresponds a getter and a setter. E.g.
* `getCenter` and `setCenter` for the `center` state.
*
* An `ol.View2D` has a `projection`. The projection determines the
* coordinate system of the center, and its units determine the units of the
* resolution (projection units per pixel). The default projection is
* Spherical Mercator (EPSG:3857).
*
* ### The constraints
*
* `setCenter`, `setResolution` and `setRotation` can be used to change the
* states of the view. Any value can be passed to the setters. And the value
* that is passed to a setter will effectively be the value set in the view,
* and returned by the corresponding getter.
*
* But an `ol.View2D` object also has a *resolution constraint* and a
* *rotation constraint*. There's currently no *center constraint*, but
* this may change in the future.
*
* As said above no constraints are applied when the setters are used to set
* new states for the view. Applying constraints is done explicitly through
* the use of the `constrain*` functions (`constrainResolution` and
* `constrainRotation`).
*
* The main users of the constraints are the interactions and the
* controls. For example, double-clicking on the map changes the view to
* the "next" resolution. And releasing the fingers after pinch-zooming
* snaps to the closest resolution (with an animation).
*
* So the *resolution constraint* snaps to specific resolutions. It is
* determined by the following options: `resolutions`, `maxResolution`,
* `maxZoom`, and `zoomFactor`. If `resolutions` is set, the other three
* options are ignored. See {@link ol.View2DOptions} for more information.
*
* The *rotation constaint* is currently not configurable. It snaps the
* rotation value to zero when approaching the horizontal.
* *
* @constructor * @constructor
* @implements {ol.IView2D} * @implements {ol.IView2D}
@@ -59,21 +97,22 @@ ol.View2D = function(opt_options) {
values[ol.View2DProperty.PROJECTION] = ol.proj.createProjection( values[ol.View2DProperty.PROJECTION] = ol.proj.createProjection(
options.projection, 'EPSG:3857'); options.projection, 'EPSG:3857');
var parts = ol.View2D.createResolutionConstraint_(options); var resolutionConstraintInfo = ol.View2D.createResolutionConstraint_(
options);
/** /**
* @private * @private
* @type {number} * @type {number}
*/ */
this.maxResolution_ = parts[1]; this.maxResolution_ = resolutionConstraintInfo.maxResolution;
/** /**
* @private * @private
* @type {number} * @type {number}
*/ */
this.minResolution_ = parts[2]; this.minResolution_ = resolutionConstraintInfo.minResolution;
var resolutionConstraint = parts[0]; var resolutionConstraint = resolutionConstraintInfo.constraint;
var rotationConstraint = ol.View2D.createRotationConstraint_(options); var rotationConstraint = ol.View2D.createRotationConstraint_(options);
/** /**
@@ -86,7 +125,7 @@ ol.View2D = function(opt_options) {
if (goog.isDef(options.resolution)) { if (goog.isDef(options.resolution)) {
values[ol.View2DProperty.RESOLUTION] = options.resolution; values[ol.View2DProperty.RESOLUTION] = options.resolution;
} else if (goog.isDef(options.zoom)) { } else if (goog.isDef(options.zoom)) {
values[ol.View2DProperty.RESOLUTION] = resolutionConstraint( values[ol.View2DProperty.RESOLUTION] = this.constrainResolution(
this.maxResolution_, options.zoom); this.maxResolution_, options.zoom);
} }
values[ol.View2DProperty.ROTATION] = values[ol.View2DProperty.ROTATION] =
@@ -324,6 +363,31 @@ ol.View2D.prototype.getView3D = function() {
}; };
/**
* Get the current zoom level. Return undefined if the current
* resolution is undefined or not a "constrained resolution".
* @return {number|undefined} Zoom.
*/
ol.View2D.prototype.getZoom = function() {
var zoom;
var resolution = this.getResolution();
if (goog.isDef(resolution)) {
var res, z = 0;
do {
res = this.constrainResolution(this.maxResolution_, z);
if (res == resolution) {
zoom = z;
break;
}
++z;
} while (res > this.minResolution_);
}
return zoom;
};
/** /**
* Fit the given extent based on the given map size. * Fit the given extent based on the given map size.
* @param {ol.Extent} extent Extent. * @param {ol.Extent} extent Extent.
@@ -398,11 +462,21 @@ goog.exportProperty(
ol.View2D.prototype.setRotation); ol.View2D.prototype.setRotation);
/**
* Zoom to a specific zoom level.
* @param {number} zoom Zoom level.
*/
ol.View2D.prototype.setZoom = function(zoom) {
var resolution = this.constrainResolution(this.maxResolution_, zoom, 0);
this.setResolution(resolution);
};
/** /**
* @private * @private
* @param {ol.View2DOptions} options View2D options. * @param {ol.View2DOptions} options View2D options.
* @return {Array} Array of three elements: the resolution constraint, * @return {{constraint: ol.ResolutionConstraintType, maxResolution: number,
* maxResolution, and minResolution. * minResolution: number}}
*/ */
ol.View2D.createResolutionConstraint_ = function(options) { ol.View2D.createResolutionConstraint_ = function(options) {
var resolutionConstraint; var resolutionConstraint;
@@ -440,7 +514,8 @@ ol.View2D.createResolutionConstraint_ = function(options) {
resolutionConstraint = ol.ResolutionConstraint.createSnapToPower( resolutionConstraint = ol.ResolutionConstraint.createSnapToPower(
zoomFactor, maxResolution, maxZoom); zoomFactor, maxResolution, maxZoom);
} }
return [resolutionConstraint, maxResolution, minResolution]; return {constraint: resolutionConstraint, maxResolution: maxResolution,
minResolution: minResolution};
}; };

View File

@@ -68,6 +68,7 @@ describe('ol.control.ZoomSlider', function() {
control.element.style.width = '1000px'; control.element.style.width = '1000px';
control.element.style.height = '10px'; control.element.style.height = '10px';
control.setMap(map); control.setMap(map);
control.initSlider_();
var horizontal = ol.control.ZoomSlider.direction.HORIZONTAL; var horizontal = ol.control.ZoomSlider.direction.HORIZONTAL;
expect(control.direction_).to.be(horizontal); expect(control.direction_).to.be(horizontal);

View File

@@ -108,4 +108,39 @@ describe('ol.geom.LinearRing', function() {
}); });
describe('ol.geom.LinearRing.isClockwise()', function() {
var isClockwise = ol.geom.LinearRing.isClockwise;
it('returns true for clockwise coordinates', function() {
var coordinates = [
[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]
];
expect(isClockwise(coordinates)).to.be(true);
});
it('returns false for counter-clockwise coordinates', function() {
var coordinates = [
[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]
];
expect(isClockwise(coordinates)).to.be(false);
});
it('returns true for mostly clockwise, self-intersecting ring', function() {
var coordinates = [
[0, 0], [0, 1], [1.5, 1], [1.5, 1.5], [1, 1.5], [1, 0], [0, 0]
];
expect(isClockwise(coordinates)).to.be(true);
});
it('returns false for mostly counter-clockwise, intersecting', function() {
var coordinates = [
[0, 0], [1, 0], [1, 1.5], [1.5, 1.5], [1.5, 1], [0, 1], [0, 0]
];
expect(isClockwise(coordinates)).to.be(false);
});
});
goog.require('ol.geom.LinearRing'); goog.require('ol.geom.LinearRing');

View File

@@ -44,6 +44,28 @@ describe('ol.geom.Polygon', function() {
expect(poly.rings[2]).to.be.a(ol.geom.LinearRing); expect(poly.rings[2]).to.be.a(ol.geom.LinearRing);
}); });
var isClockwise = ol.geom.LinearRing.isClockwise;
it('forces exterior ring to be clockwise', function() {
var outer = [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]];
expect(isClockwise(outer)).to.be(false);
var poly = new ol.geom.Polygon([outer]);
var ring = poly.rings[0];
expect(isClockwise(ring.getCoordinates())).to.be(true);
});
it('forces interior ring to be counter-clockwise', function() {
var outer = [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]];
var inner = [[2, 2], [2, 8], [8, 8], [8, 2], [2, 2]];
expect(isClockwise(inner)).to.be(true);
var poly = new ol.geom.Polygon([outer, inner]);
var ring = poly.rings[1];
expect(isClockwise(ring.getCoordinates())).to.be(false);
});
}); });
describe('#dimension', function() { describe('#dimension', function() {

View File

@@ -1,34 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd"> <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd">
<Document> <Document>
<name>Polygon.kml</name> <name>Polygon.kml</name>
<open>0</open> <open>0</open>
<Placemark id="KML.Polygon"> <Placemark id="KML.Polygon">
<name>hollow box</name> <name>hollow box</name>
<Polygon> <Polygon>
<outerBoundaryIs> <outerBoundaryIs>
<LinearRing> <LinearRing>
<coordinates> <coordinates>-30,-20,0 -30,20,0 30,20,0 30,-20,0 -30,-20,0</coordinates>
-122.366278,37.818844,30 </LinearRing>
-122.365248,37.819267,30 </outerBoundaryIs>
-122.36564,37.819861,30 <innerBoundaryIs>
-122.366669,37.819429,30 <LinearRing>
-122.366278,37.818844,30 <coordinates>-15,-10,0 15,-10,0 15,10,0 -15,10,0 -15,-10,0</coordinates>
</coordinates> </LinearRing>
</LinearRing> </innerBoundaryIs>
</outerBoundaryIs> </Polygon>
<innerBoundaryIs> </Placemark>
<LinearRing> </Document>
<coordinates> </kml>
-122.366212,37.818977,30
-122.365424,37.819294,30
-122.365704,37.819731,30
-122.366488,37.819402,30
-122.366212,37.818977,30
</coordinates>
</LinearRing>
</innerBoundaryIs>
</Polygon>
</Placemark>
</Document>
</kml>

View File

@@ -145,14 +145,6 @@ describe('ol.parser.gml_v2', function() {
delete parser.srsName; delete parser.srsName;
expect(obj.geometry.type).to.eql('polygon'); expect(obj.geometry.type).to.eql('polygon');
done(); done();
expect(obj.geometry.coordinates.length).to.eql(3);
expect(obj.geometry.coordinates[0].length).to.eql(4);
expect(obj.geometry.coordinates[0]).to.eql([[1, 2], [3, 4],
[5, 6], [1, 2]]);
expect(obj.geometry.coordinates[1]).to.eql([[2, 3], [4, 5],
[6, 7], [2, 3]]);
expect(obj.geometry.coordinates[2]).to.eql([[3, 4], [5, 6],
[7, 8], [3, 4]]);
}); });
}); });
it('MultiPolygon read correctly from coord', function(done) { it('MultiPolygon read correctly from coord', function(done) {

View File

@@ -247,14 +247,6 @@ describe('ol.parser.gml_v3', function() {
delete parser.srsName; delete parser.srsName;
expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(parser.serialize(node))).to.xmleql(xml);
expect(obj.geometry.type).to.eql('polygon'); expect(obj.geometry.type).to.eql('polygon');
expect(obj.geometry.coordinates.length).to.eql(3);
expect(obj.geometry.coordinates[0].length).to.eql(4);
expect(obj.geometry.coordinates[0]).to.eql([[1, 2], [3, 4],
[5, 6], [1, 2]]);
expect(obj.geometry.coordinates[1]).to.eql([[2, 3], [4, 5],
[6, 7], [2, 3]]);
expect(obj.geometry.coordinates[2]).to.eql([[3, 4], [5, 6],
[7, 8], [3, 4]]);
done(); done();
}); });
}); });
@@ -268,14 +260,6 @@ describe('ol.parser.gml_v3', function() {
[geom]).firstChild; [geom]).firstChild;
expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml); expect(goog.dom.xml.loadXml(p.serialize(node))).to.xmleql(xml);
expect(obj.geometry.type).to.eql('polygon'); expect(obj.geometry.type).to.eql('polygon');
expect(obj.geometry.coordinates.length).to.eql(3);
expect(obj.geometry.coordinates[0].length).to.eql(4);
expect(obj.geometry.coordinates[0]).to.eql([[1, 2], [3, 4],
[5, 6], [1, 2]]);
expect(obj.geometry.coordinates[1]).to.eql([[2, 3], [4, 5],
[6, 7], [2, 3]]);
expect(obj.geometry.coordinates[2]).to.eql([[3, 4], [5, 6],
[7, 8], [3, 4]]);
done(); done();
}); });
}); });

View File

@@ -13,17 +13,17 @@
<gml:Polygon srsName="foo"> <gml:Polygon srsName="foo">
<gml:outerBoundaryIs> <gml:outerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">1,2 3,4 5,6 1,2</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">1,2 3,2 3,4 1,2</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:outerBoundaryIs> </gml:outerBoundaryIs>
<gml:innerBoundaryIs> <gml:innerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">2,3 4,5 6,7 2,3</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">2,3 2,5 4,5 2,3</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:innerBoundaryIs> </gml:innerBoundaryIs>
<gml:innerBoundaryIs> <gml:innerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">3,4 5,6 7,8 3,4</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">3,4 3,6 5,6 3,4</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:innerBoundaryIs> </gml:innerBoundaryIs>
</gml:Polygon> </gml:Polygon>

View File

@@ -9,11 +9,11 @@
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>3</gml:X> <gml:X>3</gml:X>
<gml:Y>4</gml:Y> <gml:Y>2</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>5</gml:X> <gml:X>3</gml:X>
<gml:Y>6</gml:Y> <gml:Y>4</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>1</gml:X> <gml:X>1</gml:X>
@@ -28,12 +28,12 @@
<gml:Y>3</gml:Y> <gml:Y>3</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>4</gml:X> <gml:X>2</gml:X>
<gml:Y>5</gml:Y> <gml:Y>5</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>6</gml:X> <gml:X>4</gml:X>
<gml:Y>7</gml:Y> <gml:Y>5</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>2</gml:X> <gml:X>2</gml:X>
@@ -48,12 +48,12 @@
<gml:Y>4</gml:Y> <gml:Y>4</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>5</gml:X> <gml:X>3</gml:X>
<gml:Y>6</gml:Y> <gml:Y>6</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>7</gml:X> <gml:X>5</gml:X>
<gml:Y>8</gml:Y> <gml:Y>6</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>3</gml:X> <gml:X>3</gml:X>
@@ -73,11 +73,11 @@
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>3</gml:X> <gml:X>3</gml:X>
<gml:Y>4</gml:Y> <gml:Y>2</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>5</gml:X> <gml:X>3</gml:X>
<gml:Y>6</gml:Y> <gml:Y>4</gml:Y>
</gml:coord> </gml:coord>
<gml:coord> <gml:coord>
<gml:X>1</gml:X> <gml:X>1</gml:X>

View File

@@ -3,17 +3,17 @@
<gml:Polygon> <gml:Polygon>
<gml:outerBoundaryIs> <gml:outerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">1,2 3,4 5,6 1,2</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">1,2 3,2 3,4 1,2</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:outerBoundaryIs> </gml:outerBoundaryIs>
<gml:innerBoundaryIs> <gml:innerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">2,3 4,5 6,7 2,3</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">2,3 2,5 4,5 2,3</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:innerBoundaryIs> </gml:innerBoundaryIs>
<gml:innerBoundaryIs> <gml:innerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">3,4 5,6 7,8 3,4</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">3,4 3,6 5,6 3,4</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:innerBoundaryIs> </gml:innerBoundaryIs>
</gml:Polygon> </gml:Polygon>
@@ -22,7 +22,7 @@
<gml:Polygon> <gml:Polygon>
<gml:outerBoundaryIs> <gml:outerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">1,2 3,4 5,6 1,2</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">1,2 3,2 3,4 1,2</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:outerBoundaryIs> </gml:outerBoundaryIs>
</gml:Polygon> </gml:Polygon>

View File

@@ -1,17 +1,17 @@
<gml:Polygon xmlns:gml="http://www.opengis.net/gml" srsName="foo"> <gml:Polygon xmlns:gml="http://www.opengis.net/gml" srsName="foo">
<gml:outerBoundaryIs> <gml:outerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">1,2 3,4 5,6 1,2</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">1,2 5,2 5,6 1,2</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:outerBoundaryIs> </gml:outerBoundaryIs>
<gml:innerBoundaryIs> <gml:innerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">2,3 4,5 6,7 2,3</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">2,3 2,5 4,5 2,3</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:innerBoundaryIs> </gml:innerBoundaryIs>
<gml:innerBoundaryIs> <gml:innerBoundaryIs>
<gml:LinearRing> <gml:LinearRing>
<gml:coordinates decimal="." cs="," ts=" ">3,4 5,6 7,8 3,4</gml:coordinates> <gml:coordinates decimal="." cs="," ts=" ">3,4 3,6 5,6 3,4</gml:coordinates>
</gml:LinearRing> </gml:LinearRing>
</gml:innerBoundaryIs> </gml:innerBoundaryIs>
</gml:Polygon> </gml:Polygon>

View File

@@ -3,24 +3,24 @@
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:Polygon> </gml:Polygon>
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
</gml:Polygon> </gml:Polygon>

View File

@@ -3,17 +3,17 @@
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:Polygon> </gml:Polygon>
@@ -22,7 +22,7 @@
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
</gml:Polygon> </gml:Polygon>

View File

@@ -3,24 +3,24 @@
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:Polygon> </gml:Polygon>
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
</gml:Polygon> </gml:Polygon>

View File

@@ -3,17 +3,17 @@
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:Polygon> </gml:Polygon>
@@ -22,7 +22,7 @@
<gml:Polygon> <gml:Polygon>
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
</gml:Polygon> </gml:Polygon>

View File

@@ -5,17 +5,17 @@
<gml:PolygonPatch interpolation="planar"> <gml:PolygonPatch interpolation="planar">
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:PolygonPatch> </gml:PolygonPatch>
@@ -28,7 +28,7 @@
<gml:PolygonPatch interpolation="planar"> <gml:PolygonPatch interpolation="planar">
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
</gml:PolygonPatch> </gml:PolygonPatch>

View File

@@ -1,17 +1,17 @@
<gml:Polygon xmlns:gml="http://www.opengis.net/gml" srsName="foo"> <gml:Polygon xmlns:gml="http://www.opengis.net/gml" srsName="foo">
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:Polygon> </gml:Polygon>

View File

@@ -3,17 +3,17 @@
<gml:PolygonPatch interpolation="planar"> <gml:PolygonPatch interpolation="planar">
<gml:exterior> <gml:exterior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>1 2 3 4 5 6 1 2</gml:posList> <gml:posList>1 2 3 2 3 4 1 2</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:exterior> </gml:exterior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>2 3 4 5 6 7 2 3</gml:posList> <gml:posList>2 3 2 5 4 5 2 3</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
<gml:interior> <gml:interior>
<gml:LinearRing> <gml:LinearRing>
<gml:posList>3 4 5 6 7 8 3 4</gml:posList> <gml:posList>3 4 3 6 5 6 3 4</gml:posList>
</gml:LinearRing> </gml:LinearRing>
</gml:interior> </gml:interior>
</gml:PolygonPatch> </gml:PolygonPatch>

View File

@@ -80,7 +80,9 @@ describe('ol.parser.WKT', function() {
expect(geom.rings[0].getCoordinates()).to.eql( expect(geom.rings[0].getCoordinates()).to.eql(
[[30, 10], [10, 20], [20, 40], [40, 40], [30, 10]]); [[30, 10], [10, 20], [20, 40], [40, 40], [30, 10]]);
expect(parser.write(geom)).to.eql(wkt); expect(parser.write(geom)).to.eql(wkt);
wkt = 'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,35 35,30 20,20 30))';
// note that WKT doesn't care about winding order, we do
wkt = 'POLYGON((35 10,10 20,15 40,45 45,35 10),(20 30,30 20,35 35,20 30))';
geom = parser.read(wkt); geom = parser.read(wkt);
expect(geom.getType()).to.eql(ol.geom.GeometryType.POLYGON); expect(geom.getType()).to.eql(ol.geom.GeometryType.POLYGON);
expect(geom.rings.length).to.eql(2); expect(geom.rings.length).to.eql(2);
@@ -89,8 +91,9 @@ describe('ol.parser.WKT', function() {
expect(geom.rings[0].getCoordinates()).to.eql( expect(geom.rings[0].getCoordinates()).to.eql(
[[35, 10], [10, 20], [15, 40], [45, 45], [35, 10]]); [[35, 10], [10, 20], [15, 40], [45, 45], [35, 10]]);
expect(geom.rings[1].getCoordinates()).to.eql( expect(geom.rings[1].getCoordinates()).to.eql(
[[20, 30], [35, 35], [30, 20], [20, 30]]); [[20, 30], [30, 20], [35, 35], [20, 30]]);
expect(parser.write(geom)).to.eql(wkt); expect(parser.write(geom)).to.eql(wkt);
// test whitespace when reading // test whitespace when reading
wkt = 'POLYGON ( (30 10, 10 20, 20 40, 40 40, 30 10) )'; wkt = 'POLYGON ( (30 10, 10 20, 20 40, 40 40, 30 10) )';
geom = parser.read(wkt); geom = parser.read(wkt);
@@ -102,7 +105,8 @@ describe('ol.parser.WKT', function() {
}); });
it('MultiPolygon read / written correctly', function() { it('MultiPolygon read / written correctly', function() {
var wkt = 'MULTIPOLYGON(((40 40,20 45,45 30,40 40)),' + // note that WKT doesn't care about winding order, we do
var wkt = 'MULTIPOLYGON(((40 40,45 30,20 45,40 40)),' +
'((20 35,45 20,30 5,10 10,10 30,20 35),(30 20,20 25,20 15,30 20)))'; '((20 35,45 20,30 5,10 10,10 30,20 35),(30 20,20 25,20 15,30 20)))';
var geom = parser.read(wkt); var geom = parser.read(wkt);
expect(geom.getType()).to.eql(ol.geom.GeometryType.MULTIPOLYGON); expect(geom.getType()).to.eql(ol.geom.GeometryType.MULTIPOLYGON);
@@ -112,16 +116,17 @@ describe('ol.parser.WKT', function() {
expect(geom.components[0].rings.length).to.eql(1); expect(geom.components[0].rings.length).to.eql(1);
expect(geom.components[1].rings.length).to.eql(2); expect(geom.components[1].rings.length).to.eql(2);
expect(geom.components[0].rings[0].getCoordinates()).to.eql( expect(geom.components[0].rings[0].getCoordinates()).to.eql(
[[40, 40], [20, 45], [45, 30], [40, 40]]); [[40, 40], [45, 30], [20, 45], [40, 40]]);
expect(geom.components[1].rings[0].getCoordinates()).to.eql( expect(geom.components[1].rings[0].getCoordinates()).to.eql(
[[20, 35], [45, 20], [30, 5], [10, 10], [10, 30], [20, 35]]); [[20, 35], [45, 20], [30, 5], [10, 10], [10, 30], [20, 35]]);
expect(geom.components[1].rings[1].getCoordinates()).to.eql( expect(geom.components[1].rings[1].getCoordinates()).to.eql(
[[30, 20], [20, 25], [20, 15], [30, 20]]); [[30, 20], [20, 25], [20, 15], [30, 20]]);
expect(parser.write(geom)).to.eql(wkt); expect(parser.write(geom)).to.eql(wkt);
// test whitespace when reading // test whitespace when reading
wkt = 'MULTIPOLYGON( ( (40 40, 20 45, 45 30, 40 40) ), ' + wkt = 'MULTIPOLYGON( ( ( 40 40,45 30, 20 45 ,40 40 )) ,' +
'( (20 35, 45 20, 30 5, 10 10, 10 30, 20 35 ), ( 30 20, 20 25, ' + '( (20 35, 45 20,30 5,10 10,10 30,20 35), ' +
'20 15, 30 20 ) ) )'; '( 30 20, 20 25,20 15 ,30 20 ) ))';
geom = parser.read(wkt); geom = parser.read(wkt);
expect(geom.getType()).to.eql(ol.geom.GeometryType.MULTIPOLYGON); expect(geom.getType()).to.eql(ol.geom.GeometryType.MULTIPOLYGON);
expect(geom.components.length).to.eql(2); expect(geom.components.length).to.eql(2);
@@ -130,7 +135,7 @@ describe('ol.parser.WKT', function() {
expect(geom.components[0].rings.length).to.eql(1); expect(geom.components[0].rings.length).to.eql(1);
expect(geom.components[1].rings.length).to.eql(2); expect(geom.components[1].rings.length).to.eql(2);
expect(geom.components[0].rings[0].getCoordinates()).to.eql( expect(geom.components[0].rings[0].getCoordinates()).to.eql(
[[40, 40], [20, 45], [45, 30], [40, 40]]); [[40, 40], [45, 30], [20, 45], [40, 40]]);
expect(geom.components[1].rings[0].getCoordinates()).to.eql( expect(geom.components[1].rings[0].getCoordinates()).to.eql(
[[20, 35], [45, 20], [30, 5], [10, 10], [10, 30], [20, 35]]); [[20, 35], [45, 20], [30, 5], [10, 10], [10, 30], [20, 35]]);
expect(geom.components[1].rings[1].getCoordinates()).to.eql( expect(geom.components[1].rings[1].getCoordinates()).to.eql(

View File

@@ -8,7 +8,7 @@ describe('ol.View2D', function() {
describe('with no options', function() { describe('with no options', function() {
it('gives a correct resolution constraint function', function() { it('gives a correct resolution constraint function', function() {
var options = {}; var options = {};
var fn = ol.View2D.createResolutionConstraint_(options)[0]; var fn = ol.View2D.createResolutionConstraint_(options).constraint;
expect(fn(156543.03392804097, 0, 0)) expect(fn(156543.03392804097, 0, 0))
.to.roughlyEqual(156543.03392804097, 1e-9); .to.roughlyEqual(156543.03392804097, 1e-9);
expect(fn(78271.51696402048, 0, 0)) expect(fn(78271.51696402048, 0, 0))
@@ -24,12 +24,12 @@ describe('ol.View2D', function() {
maxZoom: 3, maxZoom: 3,
zoomFactor: 3 zoomFactor: 3
}; };
var parts = ol.View2D.createResolutionConstraint_(options); var info = ol.View2D.createResolutionConstraint_(options);
var maxResolution = parts[1]; var maxResolution = info.maxResolution;
expect(maxResolution).to.eql(81); expect(maxResolution).to.eql(81);
var minResolution = parts[2]; var minResolution = info.minResolution;
expect(minResolution).to.eql(3); expect(minResolution).to.eql(3);
var fn = parts[0]; var fn = info.constraint;
expect(fn(82, 0, 0)).to.eql(81); expect(fn(82, 0, 0)).to.eql(81);
expect(fn(81, 0, 0)).to.eql(81); expect(fn(81, 0, 0)).to.eql(81);
expect(fn(27, 0, 0)).to.eql(27); expect(fn(27, 0, 0)).to.eql(27);
@@ -44,12 +44,12 @@ describe('ol.View2D', function() {
var options = { var options = {
resolutions: [97, 76, 65, 54, 0.45] resolutions: [97, 76, 65, 54, 0.45]
}; };
var parts = ol.View2D.createResolutionConstraint_(options); var info = ol.View2D.createResolutionConstraint_(options);
var maxResolution = parts[1]; var maxResolution = info.maxResolution;
expect(maxResolution).to.eql(97); expect(maxResolution).to.eql(97);
var minResolution = parts[2]; var minResolution = info.minResolution;
expect(minResolution).to.eql(0.45); expect(minResolution).to.eql(0.45);
var fn = parts[0]; var fn = info.constraint;
expect(fn(97, 0, 0)).to.eql(97); expect(fn(97, 0, 0)).to.eql(97);
expect(fn(76, 0, 0)).to.eql(76); expect(fn(76, 0, 0)).to.eql(76);
expect(fn(65, 0, 0)).to.eql(65); expect(fn(65, 0, 0)).to.eql(65);
@@ -70,6 +70,38 @@ describe('ol.View2D', function() {
}); });
}); });
describe('#getZoom', function() {
var view;
beforeEach(function() {
view = new ol.View2D({
resolutions: [512, 256, 128, 64, 32, 16]
});
});
it('returns correct zoom levels', function() {
view.setResolution(undefined);
expect(view.getZoom()).to.be(undefined);
view.setResolution(511);
expect(view.getZoom()).to.be(undefined);
view.setResolution(512);
expect(view.getZoom()).to.be(0);
view.setResolution(64);
expect(view.getZoom()).to.be(3);
view.setResolution(65);
expect(view.getZoom()).to.be(undefined);
view.setResolution(16);
expect(view.getZoom()).to.be(5);
view.setResolution(15);
expect(view.getZoom()).to.be(undefined);
});
});
}); });
goog.require('ol.View2D'); goog.require('ol.View2D');