Compare commits

...

114 Commits

Author SHA1 Message Date
Bart van den Eijnden
626d1da0e7 Merge pull request #3406 from bartvde/release-v3.4.0
Release v3.4.0
2015-03-27 10:22:38 +01:00
Bart van den Eijnden
96c670cebf Update package version to 3.4.0 2015-03-27 10:08:50 +01:00
Bart van den Eijnden
42366c3d00 Changelog for v3.4.0 2015-03-27 10:08:30 +01:00
Bart van den Eijnden
d698e2fcee Merge pull request #3383 from bartvde/xmleql-performance
GML3 tests time out in unit tests
2015-03-26 17:10:25 +01:00
Bart van den Eijnden
7d5ede6728 Restore the previous error messages 2015-03-26 16:48:22 +01:00
Bart van den Eijnden
616a0b161e Speed up xmleql performance 2015-03-26 16:03:28 +01:00
Tim Schaub
6e878468ae Merge pull request #3401 from tschaub/geojson-orientation
Allow GeoJSON to be serialized according to the right-hand rule.
2015-03-26 08:44:57 -06:00
Frédéric Junod
9b23572d4e Merge pull request #3403 from fredj/unused-require
Remove unused goog.require
2015-03-26 14:08:24 +01:00
Frederic Junod
c0c3057498 Remove unused goog.require 2015-03-26 11:54:37 +01:00
Andreas Hocevar
34851d8ecb Merge pull request #3362 from ahocevar/constructor-proj4js
Configure proj4 options and transforms upon construction
2015-03-26 11:21:52 +01:00
Andreas Hocevar
362c9b6851 Clarification of the purpose of ol.proj.addProjection 2015-03-26 10:52:19 +01:00
Andreas Hocevar
a920cd94d9 Create ol.proj.Projection instances with additional properties 2015-03-26 10:50:52 +01:00
Andreas Hocevar
338901774b Configure proj4 options and transforms upon construction 2015-03-26 10:39:26 +01:00
Frédéric Junod
2c04e4c071 Merge pull request #3394 from fredj/fullscreen-css-name
Fix fullscreen pseudo CSS class name
2015-03-26 09:00:57 +01:00
Tim Schaub
be0c9f3c8a Allow orienting coordinates when serializing GeoJSON 2015-03-25 18:32:31 -06:00
Tim Schaub
5d590bcf95 Allow access to right-hand oriented multi-polygon coordinates 2015-03-25 16:57:29 -06:00
Tim Schaub
7572f27cf9 Allow access to right-hand oriented polygon coordinates 2015-03-25 16:57:29 -06:00
Tim Schaub
ce36947bdb Allow orienting with the right-hand rule 2015-03-25 16:57:25 -06:00
Tim Schaub
5f6ceff3a7 Use ol.geom.flat.orient namespace 2015-03-25 16:33:17 -06:00
Andreas Hocevar
7d20e2a317 Merge pull request #3399 from ahocevar/tilegrid-widths-docs
Clarify when widths need to be configured on a tile grid
2015-03-25 17:18:27 +01:00
Andreas Hocevar
0d507dcbb0 Clarify when widths need to be configured on a tile grid 2015-03-25 16:52:45 +01:00
Andreas Hocevar
c600a92516 Merge pull request #3398 from ahocevar/safe-wrapx
Make sure that the return value of wrapX() is stable
2015-03-25 16:21:53 +01:00
Andreas Hocevar
1df8cba753 Make sure that the return value of wrapX() is stable 2015-03-25 15:59:59 +01:00
Frédéric Junod
bb87b8e7ce Merge pull request #3396 from fredj/sort-compareFn
Move the compare function out of ol.interaction.Modify.handleDownEvent_
2015-03-25 14:57:50 +01:00
Frederic Junod
6a770f03b8 Move the compare function out of ol.interaction.Modify.handleDownEvent_ 2015-03-25 14:41:40 +01:00
Andreas Hocevar
683097d62a Merge pull request #3395 from fperucic/inteaction.modify-fix
ol.Interaction.Modify fixes
2015-03-25 14:16:37 +01:00
Andreas Hocevar
e58a470e69 Merge pull request #3387 from ahocevar/wmts-wrapx
Add wrapX option for ol.source.WMTS
2015-03-25 14:01:04 +01:00
Fran Peručić
56067d1cda Prevent unnecessary function calls
handlePointerMove_ doesn't need to be called when dragging.
handleDragEvent_ takes care of the event in that case.

in handleDragEvent_, createOrUpdateVertexFeature_ doesn't need to be called for each dragged segment. it can be called only once with current vertex.

fixes made to pass the build
2015-03-25 11:19:24 +01:00
Frederic Junod
40f4d5256b Fix fullscreen pseudo CSS class name
Change from `:full-screen` to `:fullscreen`.
See https://fullscreen.spec.whatwg.org/#:fullscreen-pseudo-class
2015-03-25 11:14:52 +01:00
Fran Peručić
279d1829bb fix: ol.interaction.Select conflict
Prevent vertexFeature_ from ol.interaction.Modify from being selected by ol.interaction.Select.
The bug occurs when an delete attempt fails. ex: clicikng on the first or last node of LineString,
or clicking a line segment between two nodes.
2015-03-25 10:52:29 +01:00
Fran Peručić
eb6d61e6d1 fix: modifying the closed LineString
This commit fixes the bug that occurs when trying to modify
a closed LineString by clicking on the starting/ending node.

Such a closed line is added to the modify-test example.
2015-03-25 10:44:35 +01:00
Fran Peručić
7dff739bce Deleting a duplicate node
Fix a bug in ol.interaction.Modify when trying to delete nodes
on a geometry that has duplicate nodes. A bug occurs when
clicking on the duplicate node.
2015-03-25 10:34:36 +01:00
Frédéric Junod
8beeee8a95 Merge pull request #3393 from fredj/cleanup
Remove unused define
2015-03-25 08:54:27 +01:00
Andreas Hocevar
ebb40c8046 Clean up docs and consistently work with resolutions 2015-03-24 19:03:33 +01:00
Andreas Hocevar
4822ca273f Give tile grids a width 2015-03-24 19:03:09 +01:00
Tobias Sauerwein
563d51b389 Merge pull request #3392 from tsauerwein/fullscreen-class
Fix switching class name of full-screen control
2015-03-24 18:26:20 +01:00
Andreas Hocevar
57d9b87fb3 Add wrapX option for ol.source.WMTS 2015-03-24 17:13:07 +01:00
Frederic Junod
4c36e05f27 Remove unused define
Should have been removed in #40
2015-03-24 17:10:27 +01:00
tsauerwein
eb7dde6d0f Fix class name of full-screen control 2015-03-24 17:07:55 +01:00
Frédéric Junod
1d04eabeda Merge pull request #3391 from fredj/cleanup
Minor code cleanup
2015-03-24 14:57:51 +01:00
Frédéric Junod
5c6c45fc92 Merge pull request #3388 from fredj/polyline-layout
Add new geometry layout option for polyline format
2015-03-24 14:44:06 +01:00
Frederic Junod
b7c4e4f297 Remove console.debug from selectinteraction tests 2015-03-24 14:42:30 +01:00
Frederic Junod
6a8b236d82 Remove unnecessary newlines 2015-03-24 14:41:40 +01:00
Frederic Junod
e669b20ed5 Add new geometry layout option for polyline format
To be able to choose the geometry layout of the feature geometries created by
the format reader.

Default is `ol.geom.GeometryLayout.XY`
2015-03-24 11:39:18 +01:00
Éric Lemoine
ae2c9144e1 Merge pull request #3385 from elemoine/getzforresolution
Fix ol.tilegrid.TileGrid#getZForResolution
2015-03-23 18:31:42 +01:00
Andreas Hocevar
45e9695239 Merge pull request #3377 from ahocevar/attribution-wrapx
Support wrapX for attributions
2015-03-23 18:05:13 +01:00
Éric Lemoine
79748c6f0c Fix ol.tilegrid.TileGrid#getZForResolution
This fixes a bug in ol.tilegrid.TileGrid#getZForResolution where this function doesn't take minZoom and maxZoom into account when selecting a zoom level for a resolution.

Fixes #2780.
2015-03-23 18:04:13 +01:00
Andreas Hocevar
d9c04cd925 Support wrapX for attributions 2015-03-23 16:55:50 +01:00
Andreas Hocevar
7df00242f0 Merge pull request #3382 from ahocevar/github-source-links
Create github source links
2015-03-23 16:47:47 +01:00
Andreas Hocevar
4862a8c897 Create github source links 2015-03-23 16:08:36 +01:00
Andreas Hocevar
8813eb0112 Merge pull request #3376 from ahocevar/wms-tile-wrapx
Add ol.source.Tile support for wrapping around the x-axis
2015-03-23 14:37:12 +01:00
Andreas Hocevar
b75f7f9e3b Merge pull request #3378 from ahocevar/questions
Clarify where to ask questions
2015-03-23 14:24:14 +01:00
Andreas Hocevar
9b4cb96502 Clarify where to ask questions 2015-03-23 14:14:34 +01:00
Frédéric Junod
c71db17c1d Merge pull request #3380 from fredj/more-geojson-tests
Test the GeoJSON layout
2015-03-23 13:29:13 +01:00
Frederic Junod
bfd9ec1ef1 Test the GeoJSON layout 2015-03-23 12:47:34 +01:00
Andreas Hocevar
3e18b85206 Add ol.source.Tile support for wrapping around the x-axis 2015-03-22 14:27:19 +01:00
Frédéric Junod
c707c5e9db Merge pull request #3360 from fredj/dispose-imagetile
Don't unlisten image twice when disposing an ol.ImageTile
2015-03-18 11:46:09 +01:00
Frederic Junod
f474e7ccd9 Don't unlisten image twice when disposing an ol.ImageTile
Fixes #3325
2015-03-18 10:33:41 +01:00
Andreas Hocevar
752cf78e50 Merge pull request #3361 from ahocevar/test-listen-localhost
Listen on localhost to avoid phantomjs browsing 0.0.0.0
2015-03-18 09:54:08 +01:00
Andreas Hocevar
52ee1b1630 Merge pull request #3365 from ahocevar/pointresolution-docs
Better docs for #getPointResolution
2015-03-18 09:53:29 +01:00
Andreas Hocevar
d8f624bf44 Better docs for #getPointResolution 2015-03-18 09:26:02 +01:00
Andreas Hocevar
7916f36f7a Merge pull request #3363 from bill-chadwick/master
New ol.proj features
2015-03-18 00:22:34 +01:00
bill-chadwick
3efea3ddfc Update to ol.proj
Add support for custom getPointResolution
and setting the 'global' boolean
2015-03-17 23:08:11 +00:00
Andreas Hocevar
9462c2148d Listen on localhost to avoid phantomjs browsing 0.0.0.0 2015-03-17 14:39:00 +01:00
Bart van den Eijnden
8061b69495 Merge pull request #3305 from bartvde/image-load-events
Add image loading events to image sources (r=@ahocevar,@elemoine)
2015-03-17 13:07:37 +01:00
Bart van den Eijnden
4569858882 Add image loading events to image sources 2015-03-17 12:56:39 +01:00
Frédéric Junod
3a7b9751d7 Merge pull request #3343 from fredj/line-arrows
Line arrows example
2015-03-16 14:30:08 +01:00
Frédéric Junod
d3f246518b Merge pull request #3354 from fredj/geojson-write-options
Mark ol.format.GeoJSON#writeFeature(s) option param optional
2015-03-16 11:31:59 +01:00
Frederic Junod
b9aba8babd Add optional this param to the callback function 2015-03-16 11:25:51 +01:00
Frederic Junod
023816f43b Add new line-arrows example 2015-03-16 10:43:33 +01:00
Frederic Junod
4b13627fd7 Add new ol.geom.LineString#forEachSegment function 2015-03-16 10:43:33 +01:00
Frédéric Junod
dd23403315 Merge pull request #3346 from fredj/geojson-feature-properties
Set the 'properties' member to null if the feature has not properties
2015-03-16 10:21:05 +01:00
Frederic Junod
3a7d1ebd16 Mark ol.format.GeoJSON#writeGeometry option param optional 2015-03-16 09:25:50 +01:00
Frederic Junod
180a75d714 Mark ol.format.GeoJSON#writeFeature option param optional 2015-03-16 09:20:57 +01:00
Frederic Junod
0997a171a0 Mark ol.format.GeoJSON#writeFeatures option param optional 2015-03-16 09:18:52 +01:00
Frederic Junod
96883e0b69 Set the 'properties' member to null if the feature has not properties 2015-03-12 15:58:16 +01:00
Frédéric Junod
da94ee5754 Merge pull request #3344 from fredj/cleanup
Minor code cleanup
2015-03-12 13:24:02 +01:00
Frederic Junod
5a350fb978 Remove unused goog.require 2015-03-12 12:25:38 +01:00
Frederic Junod
d87da4b3c8 Better 'rotation' option documentation 2015-03-12 12:17:25 +01:00
Éric Lemoine
80fa7e5ba1 Merge pull request #3237 from Morgul/ccase-circle-drawing
Add circles to Draw interaction.
2015-03-11 17:08:10 +01:00
Christopher S. Case
1fb932f7bb Removed lurking console.log 2015-03-11 10:09:58 -05:00
Frédéric Junod
b26bea8e88 Merge pull request #2691 from fredj/will-change
Add will-change CSS properties
2015-03-11 12:15:44 +01:00
Frederic Junod
1a80c0ef01 Add will-change CSS property to ol-overlay-container elements 2015-03-11 11:08:14 +01:00
Frederic Junod
dcba9f2ff4 Add a 'ol-overlay-container' CSS class to the overlay element 2015-03-11 11:08:14 +01:00
Frederic Junod
064cd5695a Add will-change CSS property to scale line and rotate controls 2015-03-11 11:08:14 +01:00
Frédéric Junod
b6adeea4f4 Merge pull request #3336 from fredj/getTargetElement
Use ol.Map#getTargetElement function
2015-03-09 17:15:20 +01:00
Frédéric Junod
49a807fa56 Merge pull request #3335 from fredj/rbush
Update rbush to version 1.3.5
2015-03-09 17:14:51 +01:00
Frederic Junod
7dcef882c2 Use ol.Map#getTargetElement function 2015-03-09 16:21:03 +01:00
Frederic Junod
b6b8ae265c Update rbush to version 1.3.5 2015-03-09 16:03:09 +01:00
Frédéric Junod
9951c88343 Merge pull request #3322 from fredj/drawinteraction-map.isDef
Remove unneeded map.isDef call
2015-03-09 09:01:05 +01:00
Andreas Hocevar
c9715d32b0 Merge pull request #3327 from ahocevar/dist-css
Add css to dist directory
2015-03-07 21:55:25 +01:00
Andreas Hocevar
47f32a30b8 Merge pull request #3324 from ahocevar/select-event-interface
Add interface definition for ol.SelectEvent
2015-03-06 12:41:05 +01:00
Andreas Hocevar
d8150c5155 Add interface definition for ol.SelectEvent 2015-03-06 11:31:30 +01:00
Andreas Hocevar
1b640870b1 Add css to dist directory 2015-03-06 11:20:01 +01:00
Frederic Junod
0d979e37b8 Remove unneeded map.isDef call 2015-03-05 18:12:23 +01:00
Frederic Junod
daf81b9c26 Remove unused goog.require 2015-03-05 18:11:19 +01:00
Frédéric Junod
4b1accb149 Merge pull request #3315 from fredj/tissot-desc
Fix Tissot indicatrix example description
2015-03-05 13:55:06 +01:00
Frederic Junod
b79174d6a3 Fix Tissot indicatrix example description
Fixes #3314
2015-03-05 12:36:37 +01:00
Andreas Hocevar
41fe72fab5 Merge pull request #3312 from ahocevar/arcgis-hidpi
Fix HiDPI support for ArcGIS REST
2015-03-04 22:33:21 +01:00
Andreas Hocevar
8f1726ae39 Fix HiDPI support for ArcGIS REST 2015-03-04 22:11:16 +01:00
Bart van den Eijnden
3867c0e45a Merge pull request #2910 from bartvde/issue-2910
Support multiple featureTpes in GML parser
2015-03-04 18:59:05 +01:00
Bart van den Eijnden
15ab515ceb Add docs to explain how to use featureNS in the case of multiple feature namespaces 2015-03-04 18:33:56 +01:00
Éric Lemoine
aad727ad14 Merge pull request #3309 from bjornharrtell/select-multi-fix
Fix select event always reporting as multi select
2015-03-04 18:04:15 +01:00
Bart van den Eijnden
b698fe9968 Support multiple featureTypes with a different featureNS 2015-03-04 15:27:05 +01:00
Andreas Hocevar
b782e0be98 Merge pull request #3307 from ahocevar/scaleline-units
Handle all non-degree units in ol.control.ScaleLine
2015-03-04 11:20:05 +01:00
Bart van den Eijnden
b05ead4056 Allow multiple featureTypes through ol.format.WFS as well 2015-03-04 10:24:42 +01:00
Bart van den Eijnden
d0180f35e0 Support multiple featureTypes as well in autoconfigure mode 2015-03-04 10:20:36 +01:00
Bart van den Eijnden
3a7905f2fd Support multiple feature types in GML format 2015-03-04 10:16:25 +01:00
Björn Harrtell
49c2af165a Fix select event always reporting as multi select 2015-03-04 08:48:08 +01:00
Andreas Hocevar
2e3d0d57d5 Handle all non-degree units in ol.control.ScaleLine 2015-03-03 21:06:12 +01:00
Christopher S. Case
15a4b7f4a6 Changed default radius to 0, instead of 1000.
(This was debugging code.)
2015-02-18 09:50:10 -06:00
Christopher S. Case
b2ce4c19e1 added unit tests. 2015-02-18 09:50:10 -06:00
Christopher S. Case
1074c9d44a Updated example for circle drawing. 2015-02-18 09:50:10 -06:00
Christopher S. Case
ae8321ab30 Added circle drawing to draw interaction. 2015-02-18 09:50:02 -06:00
89 changed files with 2229 additions and 379 deletions

View File

@@ -2,6 +2,18 @@
Thanks for your interest in contributing to OpenLayers 3.
## Asking Questions
Please ask questions about using the library on [stackoverflow using the tag 'openlayers-3'](http://stackoverflow.com/questions/tagged/openlayers-3).
When you want to get involved and discuss new features or changes, please use [the mailing list](https://groups.google.com/forum/#!forum/ol3-dev).
## Submitting Bug Reports
Please use the [GitHub issue tracker](https://github.com/openlayers/ol3/issues). Before creating a new issue, do a quick search to see if the problem has been reported already.
## Contributing Code
Our preferred means of receiving contributions is through [pull requests](https://help.github.com/articles/using-pull-requests). Make sure
@@ -25,7 +37,7 @@ You will obviously start by
### Travis CI
The Travis CI hook is enabled on the Github repository. This means every pull request
The Travis CI hook is enabled on the Github repository. This means every pull request
is run through a full test suite to ensure it compiles and passes the tests. Failing
pull requests will not be merged.
@@ -78,7 +90,7 @@ The `build.py` script is equivalent to a Makefile. It is actually based on
The usage of the script is:
$ ./build.py <target>
where `<target>` is the name of the build target you want to execute. For
example:

View File

@@ -7,8 +7,5 @@ Welcome to [OpenLayers 3](http://openlayers.org/)!
## Examples
Check out the [hosted examples](http://openlayers.org/en/master/examples/), the [workshop](http://openlayers.org/ol3-workshop/) or poke around the evolving [API docs](http://openlayers.org/en/master/apidoc/).
## Questions
Please don't ask questions in the github issue tracker but use [stackoverflow with tag openlayers](http://stackoverflow.com/questions/tagged/openlayers) or [the mailing list](https://groups.google.com/forum/#!forum/ol3-dev) instead.
## Contributing
Please see our guide on [contributing](CONTRIBUTING.md) if you're interested in getting involved.

43
changelog/v3.4.0.md Normal file
View File

@@ -0,0 +1,43 @@
## Overview of all changes
* [#3383](https://github.com/openlayers/ol3/pull/3383) - GML3 tests time out in unit tests ([@bartvde](https://github.com/bartvde))
* [#3401](https://github.com/openlayers/ol3/pull/3401) - Allow GeoJSON to be serialized according to the right-hand rule. ([@tschaub](https://github.com/tschaub))
* [#3403](https://github.com/openlayers/ol3/pull/3403) - Remove unused goog.require ([@fredj](https://github.com/fredj))
* [#3362](https://github.com/openlayers/ol3/pull/3362) - Configure proj4 options and transforms upon construction ([@ahocevar](https://github.com/ahocevar))
* [#3394](https://github.com/openlayers/ol3/pull/3394) - Fix fullscreen pseudo CSS class name ([@fredj](https://github.com/fredj))
* [#3399](https://github.com/openlayers/ol3/pull/3399) - Clarify when widths need to be configured on a tile grid ([@ahocevar](https://github.com/ahocevar))
* [#3398](https://github.com/openlayers/ol3/pull/3398) - Make sure that the return value of wrapX() is stable ([@ahocevar](https://github.com/ahocevar))
* [#3396](https://github.com/openlayers/ol3/pull/3396) - Move the compare function out of ol.interaction.Modify.handleDownEvent_ ([@fredj](https://github.com/fredj))
* [#3395](https://github.com/openlayers/ol3/pull/3395) - ol.Interaction.Modify fixes ([@fperucic](https://github.com/fperucic))
* [#3387](https://github.com/openlayers/ol3/pull/3387) - Add wrapX option for ol.source.WMTS ([@ahocevar](https://github.com/ahocevar))
* [#3393](https://github.com/openlayers/ol3/pull/3393) - Remove unused define ([@fredj](https://github.com/fredj))
* [#3392](https://github.com/openlayers/ol3/pull/3392) - Fix switching class name of full-screen control ([@tsauerwein](https://github.com/tsauerwein))
* [#3391](https://github.com/openlayers/ol3/pull/3391) - Minor code cleanup ([@fredj](https://github.com/fredj))
* [#3388](https://github.com/openlayers/ol3/pull/3388) - Add new geometry layout option for polyline format ([@fredj](https://github.com/fredj))
* [#3385](https://github.com/openlayers/ol3/pull/3385) - Fix ol.tilegrid.TileGrid#getZForResolution ([@elemoine](https://github.com/elemoine))
* [#3377](https://github.com/openlayers/ol3/pull/3377) - Support wrapX for attributions ([@ahocevar](https://github.com/ahocevar))
* [#3382](https://github.com/openlayers/ol3/pull/3382) - Create github source links ([@ahocevar](https://github.com/ahocevar))
* [#3376](https://github.com/openlayers/ol3/pull/3376) - Add ol.source.Tile support for wrapping around the x-axis ([@ahocevar](https://github.com/ahocevar))
* [#3378](https://github.com/openlayers/ol3/pull/3378) - Clarify where to ask questions ([@ahocevar](https://github.com/ahocevar))
* [#3380](https://github.com/openlayers/ol3/pull/3380) - Test the GeoJSON layout ([@fredj](https://github.com/fredj))
* [#3360](https://github.com/openlayers/ol3/pull/3360) - Don't unlisten image twice when disposing an ol.ImageTile ([@fredj](https://github.com/fredj))
* [#3361](https://github.com/openlayers/ol3/pull/3361) - Listen on localhost to avoid phantomjs browsing 0.0.0.0 ([@ahocevar](https://github.com/ahocevar))
* [#3365](https://github.com/openlayers/ol3/pull/3365) - Better docs for #getPointResolution ([@ahocevar](https://github.com/ahocevar))
* [#3363](https://github.com/openlayers/ol3/pull/3363) - New ol.proj features ([@bill-chadwick](https://github.com/bill-chadwick))
* [#3305](https://github.com/openlayers/ol3/pull/3305) - Add image loading events to image sources (r=@ahocevar,@elemoine) ([@bartvde](https://github.com/bartvde))
* [#3343](https://github.com/openlayers/ol3/pull/3343) - Line arrows example ([@fredj](https://github.com/fredj))
* [#3354](https://github.com/openlayers/ol3/pull/3354) - Mark ol.format.GeoJSON#writeFeature(s) option param optional ([@fredj](https://github.com/fredj))
* [#3346](https://github.com/openlayers/ol3/pull/3346) - Set the 'properties' member to null if the feature has not properties ([@fredj](https://github.com/fredj))
* [#3344](https://github.com/openlayers/ol3/pull/3344) - Minor code cleanup ([@fredj](https://github.com/fredj))
* [#3237](https://github.com/openlayers/ol3/pull/3237) - Add circles to Draw interaction. ([@Morgul](https://github.com/Morgul))
* [#2691](https://github.com/openlayers/ol3/pull/2691) - Add will-change CSS properties ([@fredj](https://github.com/fredj))
* [#3336](https://github.com/openlayers/ol3/pull/3336) - Use ol.Map#getTargetElement function ([@fredj](https://github.com/fredj))
* [#3335](https://github.com/openlayers/ol3/pull/3335) - Update rbush to version 1.3.5 ([@fredj](https://github.com/fredj))
* [#3322](https://github.com/openlayers/ol3/pull/3322) - Remove unneeded map.isDef call ([@fredj](https://github.com/fredj))
* [#3327](https://github.com/openlayers/ol3/pull/3327) - Add css to dist directory ([@ahocevar](https://github.com/ahocevar))
* [#3324](https://github.com/openlayers/ol3/pull/3324) - Add interface definition for ol.SelectEvent ([@ahocevar](https://github.com/ahocevar))
* [#3315](https://github.com/openlayers/ol3/pull/3315) - Fix Tissot indicatrix example description ([@fredj](https://github.com/fredj))
* [#3312](https://github.com/openlayers/ol3/pull/3312) - Fix HiDPI support for ArcGIS REST ([@ahocevar](https://github.com/ahocevar))
* [#2910](https://github.com/openlayers/ol3/pull/2910) - Support multiple featureTpes in GML parser ([@bartvde](https://github.com/bartvde))
* [#3309](https://github.com/openlayers/ol3/pull/3309) - Fix select event always reporting as multi select ([@bjornharrtell](https://github.com/bjornharrtell))
* [#3307](https://github.com/openlayers/ol3/pull/3307) - Handle all non-degree units in ol.control.ScaleLine ([@ahocevar](https://github.com/ahocevar))

View File

@@ -53,6 +53,21 @@ $(function () {
$(window).on('resize', _onResize);
_onResize();
// create source code links to github
var srcLinks = $('div.tag-source');
var masterSearch = window.location.href.match(/\/([^\/]*\/)apidoc\//);
if (masterSearch && masterSearch.length) {
var branch = masterSearch[1];
srcLinks.each(function(i, el) {
var textParts = el.innerHTML.trim().split(', ');
var link = 'https://github.com/openlayers/ol3/blob/' + branch +
textParts[0];
el.innerHTML = '<a href="' + link + '">' + textParts[0] + '</a>, ' +
'<a href="' + link + textParts[1].replace('line ', '#l') + '">' +
textParts[1] + '</a>';
});
}
// show/hide unstable items
var links = $('a[href^="ol."]');
var unstable = $('.unstable');

View File

@@ -21,7 +21,12 @@
font-size: 10px;
text-align: center;
margin: 1px;
will-change: contents, width;
}
.ol-overlay-container {
will-change: left,right,top,bottom;
}
.ol-unsupported {
display: none;
}
@@ -101,6 +106,7 @@
display: block;
font-weight: normal;
font-size: 1.2em;
will-change: transform;
}
.ol-touch .ol-control button {
font-size: 1.5em;

View File

@@ -12,3 +12,7 @@ For a more in-depth overview of OpenLayers 3 core concepts, check out the [tutor
Make sure to also check out the [OpenLayers 3 workshop](../../../ol3-workshop/).
Find additional reference material in the [API docs](../apidoc).
# Questions
If you cannot find an answer in the documentation, you can ask your question on [stackoverflow using the tag 'openlayers-3'](http://stackoverflow.com/questions/tagged/openlayers-3).

View File

@@ -1,7 +1,6 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.events.condition');
goog.require('ol.interaction');
goog.require('ol.interaction.DragBox');
goog.require('ol.interaction.Select');
goog.require('ol.layer.Tile');

BIN
examples/data/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

View File

@@ -2,7 +2,6 @@ goog.require('ol.FeatureOverlay');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.events.condition');
goog.require('ol.interaction');
goog.require('ol.interaction.Draw');
goog.require('ol.interaction.Modify');
goog.require('ol.layer.Tile');

View File

@@ -40,6 +40,7 @@
<option value="Point">Point</option>
<option value="LineString">LineString</option>
<option value="Polygon">Polygon</option>
<option value="Circle">Circle</option>
</select>
</form>

View File

@@ -1,6 +1,5 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.interaction');
goog.require('ol.interaction.Draw');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');

View File

@@ -15,7 +15,7 @@
.map:-webkit-full-screen {
height: 100%;
}
.map:full-screen {
.map:fullscreen {
height: 100%;
}
</style>

View File

@@ -18,7 +18,7 @@
.map:-ms-fullscreen {
height: 100%;
}
.map:full-screen {
.map:fullscreen {
height: 100%;
}
.ol-rotate {

View File

@@ -0,0 +1,79 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<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>Image load events example</title>
<style>
.map {
background: #E0ECED;
}
.wrapper {
position: relative;
}
#progress {
position: absolute;
bottom: 0;
left: 0;
height: 2px;
background: rgba(0, 60, 136, 0.4);
width: 0;
transition: width 250ms;
}
</style>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12 wrapper">
<div id="map" class="map"></div>
<div id="progress"></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<h4 id="title">Image load events example</h4>
<p id="shortdesc">Example using image load events.</p>
<div id="docs">
<p>
Image sources fire events related to image loading. You can
listen for <code>imageloadstart</code>, <code>imageloadend</code>,
and <code>imageloaderror</code> type events to monitor image loading
progress. This example registers listeners for these events and
renders an image loading progress bar at the bottom of the map.
</p>
<p>
See the <a href="image-load-events.js" target="_blank">image-load-events.js source</a>
for more detail on how this is done.
</p>
</div>
<div id="tags">image, events, loading</div>
</div>
</div>
</div>
<script src="../resources/jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=image-load-events" type="text/javascript"></script>
</body>
</html>

View File

@@ -0,0 +1,105 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Image');
goog.require('ol.source.ImageWMS');
/**
* Renders a progress bar.
* @param {Element} el The target element.
* @constructor
*/
function Progress(el) {
this.el = el;
this.loading = 0;
this.loaded = 0;
}
/**
* Increment the count of loading tiles.
*/
Progress.prototype.addLoading = function() {
if (this.loading === 0) {
this.show();
}
++this.loading;
this.update();
};
/**
* Increment the count of loaded tiles.
*/
Progress.prototype.addLoaded = function() {
setTimeout(function() {
++this.loaded;
this.update();
}.bind(this), 100);
};
/**
* Update the progress bar.
*/
Progress.prototype.update = function() {
var width = (this.loaded / this.loading * 100).toFixed(1) + '%';
this.el.style.width = width;
if (this.loading === this.loaded) {
this.loading = 0;
this.loaded = 0;
setTimeout(this.hide.bind(this), 500);
}
};
/**
* Show the progress bar.
*/
Progress.prototype.show = function() {
this.el.style.visibility = 'visible';
};
/**
* Hide the progress bar.
*/
Progress.prototype.hide = function() {
if (this.loading === this.loaded) {
this.el.style.visibility = 'hidden';
this.el.style.width = 0;
}
};
var progress = new Progress(document.getElementById('progress'));
var source = new ol.source.ImageWMS({
url: 'http://demo.boundlessgeo.com/geoserver/wms',
params: {'LAYERS': 'topp:states'},
serverType: 'geoserver'
});
source.on('imageloadstart', function(event) {
progress.addLoading();
});
source.on('imageloadend', function(event) {
progress.addLoaded();
});
source.on('imageloaderror', function(event) {
progress.addLoaded();
});
var map = new ol.Map({
logo: false,
layers: [
new ol.layer.Image({source: source})
],
renderer: exampleNS.getRendererFromQueryString(),
target: 'map',
view: new ol.View({
center: [-10997148, 4569099],
zoom: 4
})
});

51
examples/line-arrows.html Normal file
View File

@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<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>LineString arrows example</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<h4 id="title">LineString arrows example</h4>
<p id="shortdesc">Example of drawing arrows for each line string segment.</p>
<div id="docs">
<p>See the <a href="line-arrows.js" target="_blank">line-arrows.js source</a> to see how this is done.</p>
</div>
<div id="tags">draw, vector, arrow</div>
</div>
</div>
</div>
<script src="../resources/jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=line-arrows" type="text/javascript"></script>
</body>
</html>

67
examples/line-arrows.js Normal file
View File

@@ -0,0 +1,67 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.geom.Point');
goog.require('ol.interaction.Draw');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.MapQuest');
goog.require('ol.source.Vector');
goog.require('ol.style.Icon');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');
var raster = new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
var source = new ol.source.Vector();
var styleFunction = function(feature, resolution) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
})
})
];
geometry.forEachSegment(function(start, end) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
// arrows
styles.push(new ol.style.Style({
geometry: new ol.geom.Point(end),
image: new ol.style.Icon({
src: 'data/arrow.png',
anchor: [0.75, 0.5],
rotateWithView: false,
rotation: -rotation
})
}));
});
return styles;
};
var vector = new ol.layer.Vector({
source: source,
style: styleFunction
});
var map = new ol.Map({
layers: [raster, vector],
renderer: exampleNS.getRendererFromQueryString(),
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4
})
});
map.addInteraction(new ol.interaction.Draw({
source: source,
type: /** @type {ol.geom.GeometryType} */ ('LineString')
}));

View File

@@ -4,7 +4,6 @@ goog.require('ol.Sphere');
goog.require('ol.View');
goog.require('ol.geom.LineString');
goog.require('ol.geom.Polygon');
goog.require('ol.interaction');
goog.require('ol.interaction.Draw');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');

View File

@@ -114,7 +114,8 @@ var source = new ol.source.GeoJSON(
'type': 'MultiLineString',
'coordinates': [
[[-1e6, -7.5e5], [-1e6, 7.5e5]],
[[1e6, -7.5e5], [1e6, 7.5e5]],
[[-1e6, -7.5e5], [-1e6, 7.5e5], [-5e5, 0], [-1e6, -7.5e5]],
[[1e6, -7.5e5], [15e5, 0], [15e5, 0], [1e6, 7.5e5]],
[[-7.5e5, -1e6], [7.5e5, -1e6]],
[[-7.5e5, 1e6], [7.5e5, 1e6]]
]
@@ -127,8 +128,8 @@ var source = new ol.source.GeoJSON(
'coordinates': [
[[[-5e6, 6e6], [-5e6, 8e6], [-3e6, 8e6],
[-3e6, 6e6], [-5e6, 6e6]]],
[[[-2e6, 6e6], [-2e6, 8e6], [0, 8e6],
[0, 6e6], [-2e6, 6e6]]],
[[[-3e6, 6e6], [-2e6, 8e6], [0, 8e6],
[0, 6e6], [-3e6, 6e6]]],
[[[1e6, 6e6], [1e6, 8e6], [3e6, 8e6],
[3e6, 6e6], [1e6, 6e6]]]
]

View File

@@ -1,7 +1,6 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.events.condition');
goog.require('ol.interaction');
goog.require('ol.interaction.Select');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');

View File

@@ -2,7 +2,7 @@ goog.require('ol.Graticule');
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Vector');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
goog.require('ol.source.GeoJSON');
@@ -11,11 +11,12 @@ proj4.defs('ESRI:53009', '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +a=6371000 ' +
// Configure the Sphere Mollweide projection object with an extent,
// and a world extent. These are required for the Graticule.
var sphereMollweideProjection = ol.proj.get('ESRI:53009');
sphereMollweideProjection.setExtent([
-9009954.605703328, -9009954.605703328,
9009954.605703328, 9009954.605703328]);
sphereMollweideProjection.setWorldExtent([-179, -90, 179, 90]);
var sphereMollweideProjection = new ol.proj.Projection({
code: 'ESRI:53009',
extent: [-9009954.605703328, -9009954.605703328,
9009954.605703328, 9009954.605703328],
worldExtent: [-179, -90, 179, 90]
});
var map = new ol.Map({
keyboardEventTarget: document,

View File

@@ -37,7 +37,7 @@
<div class="span12">
<h4 id="title">Tissot indicatrix example</h4>
<p id="shortdesc">Example of <a href="http://en.wikipedia.org/wiki/Tissot's_indicatrix">Tissot indicatrix</a> maps. The map on the left is an EPSG:4326 map. The one on the left is EPSG:3857.</p>
<p id="shortdesc">Example of <a href="http://en.wikipedia.org/wiki/Tissot's_indicatrix">Tissot indicatrix</a> maps. The map on the left is an EPSG:4326 map. The one on the right is EPSG:3857.</p>
<div id="docs">
<p>See the <a href="tissot.js" target="_blank">tissot.js source</a> to see how this is done.</p>
</div>

View File

@@ -12,7 +12,8 @@ goog.require('ol.source.TileWMS');
// 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.
// ol.proj.addProjection to make it available to the library for lookup by its
// code.
var projection = new ol.proj.Projection({
code: 'EPSG:21781',

View File

@@ -5,21 +5,29 @@ goog.require('ol.control');
goog.require('ol.control.ScaleLine');
goog.require('ol.layer.Image');
goog.require('ol.proj');
goog.require('ol.proj.Projection');
goog.require('ol.source.ImageWMS');
// 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.
// Transparent Proj4js support:
//
// EPSG:21781 is known to Proj4js because its definition was loaded in the html.
// Note that we are getting the projection object here to set the extent. If
// you do not need this, you do not have to use ol.proj.get(); simply use the
// string code in the view projection below and the transforms will be
// registered transparently.
var projection = ol.proj.get('EPSG:21781');
// The extent is used to determine zoom level 0. Recommended values for a
// Now when we create an ol.proj.Projection instance with the 'EPSG:21781' code,
// OpenLayers will pick up parameters like units and transform functions from
// Proj4js.
//
// Note that we are setting the projection's extent here, which is used to
// determine the view resolution for 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]);
//
// If you use Proj4js only to transform coordinates, you don't even need to
// create an ol.proj.Projection instance. ol.proj.get() will take care of it
// internally.
var projection = new ol.proj.Projection({
code: 'EPSG:21781',
extent: [485869.5728, 76443.1884, 837076.5648, 299941.7864]
});
var extent = [420000, 30000, 900000, 350000];
var layers = [
@@ -67,7 +75,7 @@ var map = new ol.Map({
target: 'map',
view: new ol.View({
projection: projection,
center: ol.proj.transform([8.23, 46.86], 'EPSG:4326', 'EPSG:21781'),
center: ol.proj.transform([8.23, 46.86], 'EPSG:4326', projection),
extent: extent,
zoom: 2
})

View File

@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<link rel="stylesheet" href="../css/ol.css" type="text/css">
<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 wrap 180° meridian example</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="./"><img src="../resources/logo.png"> OpenLayers 3 Examples</a>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<h4 id="title">Tiled WMS wrap 180° meridian example</h4>
<p id="shortdesc">Example of a tiled WMS layer that wraps across the 180° meridian.</p>
<div id="docs">
<p>See the <a href="wms-tiled-wrap-180.js" target="_blank">wms-tiled-wrap-180.js source</a> to see how this is done.</p>
</div>
<div id="tags">wms, tile, dateline, wrap, 180</div>
</div>
</div>
</div>
<script src="../resources/jquery.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=wms-tiled-wrap-180" type="text/javascript"></script>
</body>
</html>

View File

@@ -0,0 +1,28 @@
goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.layer.Tile');
goog.require('ol.source.MapQuest');
goog.require('ol.source.TileWMS');
var layers = [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
}),
new ol.layer.Tile({
source: new ol.source.TileWMS(/** @type {olx.source.TileWMSOptions} */ ({
url: 'http://demo.boundlessgeo.com/geoserver/ne/wms',
params: {'LAYERS': 'ne:ne_10m_admin_0_countries', 'TILED': true},
serverType: 'geoserver',
wrapX: true
}))
})
];
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 1
})
});

View File

@@ -2,7 +2,6 @@ goog.require('ol.Map');
goog.require('ol.View');
goog.require('ol.format.WMTSCapabilities');
goog.require('ol.layer.Tile');
goog.require('ol.proj');
goog.require('ol.source.OSM');
goog.require('ol.source.WMTS');
@@ -14,8 +13,6 @@ $.ajax('data/WMTSCapabilities.xml').then(function(response) {
var options = ol.source.WMTS.optionsFromCapabilities(result,
{layer: 'layer-7328', matrixSet: 'EPSG:3857'});
var projection = ol.proj.get('EPSG:3857');
var projectionExtent = projection.getExtent();
map = new ol.Map({
layers: [
new ol.layer.Tile({
@@ -24,7 +21,6 @@ $.ajax('data/WMTSCapabilities.xml').then(function(response) {
}),
new ol.layer.Tile({
opacity: 1,
extent: projectionExtent,
source: new ol.source.WMTS(options)
})
],

View File

@@ -35,7 +35,6 @@ var map = new ol.Map({
}),
new ol.layer.Tile({
opacity: 0.7,
extent: projectionExtent,
source: new ol.source.WMTS({
attributions: [attribution],
url: 'http://services.arcgisonline.com/arcgis/rest/' +
@@ -49,7 +48,8 @@ var map = new ol.Map({
resolutions: resolutions,
matrixIds: matrixIds
}),
style: 'default'
style: 'default',
wrapX: true
})
})
],

View File

@@ -117,6 +117,25 @@ oli.MapEvent.prototype.map;
oli.MapEvent.prototype.frameState;
/**
* @interface
*/
oli.SelectEvent = function() {};
/**
* @type {Array.<ol.Feature>}
*/
oli.SelectEvent.prototype.deselected;
/**
* @type {Array.<ol.Feature>}
*/
oli.SelectEvent.prototype.selected;
/**
* @type {Object}
*/
@@ -210,6 +229,18 @@ oli.render.Event.prototype.vectorContext;
oli.source;
/**
* @interface
*/
oli.source.ImageEvent = function() {};
/**
* @type {ol.Image}
*/
oli.source.ImageEvent.prototype.image;
/**
* @interface
*/

View File

@@ -411,11 +411,12 @@ olx.OverlayOptions.prototype.autoPanMargin;
/**
* Object literal with config options for the projection.
* @typedef {{code: string,
* units: (ol.proj.Units|string),
* units: (ol.proj.Units|string|undefined),
* extent: (ol.Extent|undefined),
* axisOrientation: (string|undefined),
* global: (boolean|undefined),
* worldExtent: (ol.Extent|undefined)}}
* worldExtent: (ol.Extent|undefined),
* getPointResolution: (function(number, ol.Coordinate):number|undefined) }}
* @api
*/
olx.ProjectionOptions;
@@ -430,8 +431,8 @@ olx.ProjectionOptions.prototype.code;
/**
* Units.
* @type {ol.proj.Units|string}
* Units. Required unless a proj4 projection is defined for `code`.
* @type {ol.proj.Units|string|undefined}
* @api stable
*/
olx.ProjectionOptions.prototype.units;
@@ -468,6 +469,15 @@ olx.ProjectionOptions.prototype.global;
*/
olx.ProjectionOptions.prototype.worldExtent;
/**
* Function to determine resolution at a point. The function is called with a
* `{number}` view resolution and an `{ol.Coordinate}` as arguments, and returns
* the `{number}` resolution at the passed coordinate.
* @type {(function(number, ol.Coordinate):number|undefined)}
* @api
*/
olx.ProjectionOptions.prototype.getPointResolution;
/**
* Object literal with config options for the view.
@@ -1528,7 +1538,8 @@ olx.format;
/**
* @typedef {{dataProjection: ol.proj.ProjectionLike,
* featureProjection: ol.proj.ProjectionLike}}
* featureProjection: ol.proj.ProjectionLike,
* rightHanded: (boolean|undefined)}}
* @api
*/
olx.format.ReadOptions;
@@ -1557,7 +1568,8 @@ olx.format.ReadOptions.prototype.featureProjection;
/**
* @typedef {{dataProjection: ol.proj.ProjectionLike,
* featureProjection: ol.proj.ProjectionLike}}
* featureProjection: ol.proj.ProjectionLike,
* rightHanded: (boolean|undefined)}}
* @api
*/
olx.format.WriteOptions;
@@ -1583,6 +1595,22 @@ olx.format.WriteOptions.prototype.dataProjection;
olx.format.WriteOptions.prototype.featureProjection;
/**
* When writing geometries, follow the right-hand rule for linear ring
* orientation. This means that polygons will have counter-clockwise exterior
* rings and clockwise interior rings. By default, coordinates are serialized
* as they are provided at construction. If `true`, the right-hand rule will
* be applied. If `false`, the left-hand rule will be applied (clockwise for
* exterior and counter-clockwise for interior rings). Note that not all
* formats support this. The GeoJSON format does use this property when writing
* geometries.
*
* @type {boolean|undefined}
* @api
*/
olx.format.WriteOptions.prototype.rightHanded;
/**
* @typedef {{defaultDataProjection: ol.proj.ProjectionLike,
* geometryName: (string|undefined)}}
@@ -1608,7 +1636,8 @@ olx.format.GeoJSONOptions.prototype.geometryName;
/**
* @typedef {{factor: (number|undefined)}}
* @typedef {{factor: (number|undefined),
* geometryLayout: (ol.geom.GeometryLayout|undefined)}}
* @api
*/
olx.format.PolylineOptions;
@@ -1623,6 +1652,15 @@ olx.format.PolylineOptions;
olx.format.PolylineOptions.prototype.factor;
/**
* Layout of the feature geometries created by the format reader.
* Default is `ol.geom.GeometryLayout.XY`.
* @type {ol.geom.GeometryLayout|undefined}
* @api
*/
olx.format.PolylineOptions.prototype.geometryLayout;
/**
* @typedef {{defaultDataProjection: ol.proj.ProjectionLike}}
* @api
@@ -1679,8 +1717,8 @@ olx.format.KMLOptions.prototype.defaultStyle;
/**
* @typedef {{featureNS: string,
* featureType: string,
* @typedef {{featureNS: (Object.<string, string>|string|undefined),
* featureType: (Array.<string>|string|undefined),
* srsName: string,
* surface: (boolean|undefined),
* curve: (boolean|undefined),
@@ -1693,16 +1731,28 @@ olx.format.GMLOptions;
/**
* Feature namespace.
* @type {string}
* Feature namespace. If not defined will be derived from GML. If multiple
* feature types have been configured which come from different feature
* namespaces, this will be an object with the keys being the prefixes used
* in the entries of featureType array. The values of the object will be the
* feature namespaces themselves. So for instance there might be a featureType
* item `topp:states` in the `featureType` array and then there will be a key
* `topp` in the featureNS object with value `http://www.openplans.org/topp`.
* @type {Object.<string, string>|string|undefined}
* @api stable
*/
olx.format.GMLOptions.prototype.featureNS;
/**
* Feature type to parse.
* @type {string}
* Feature type(s) to parse. If multiple feature types need to be configured
* which come from different feature namespaces, `featureNS` will be an object
* with the keys being the prefixes used in the entries of featureType array.
* The values of the object will be the feature namespaces themselves.
* So for instance there might be a featureType item `topp:states` and then
* there will be a key named `topp` in the featureNS object with value
* `http://www.openplans.org/topp`.
* @type {Array.<string>|string|undefined}
* @api stable
*/
olx.format.GMLOptions.prototype.featureType;
@@ -1782,8 +1832,8 @@ olx.format.GPXOptions.prototype.readExtensions;
/**
* @typedef {{featureNS: string,
* featureType: string,
* @typedef {{featureNS: (Object.<string, string>|string|undefined),
* featureType: (Array.<string>|string|undefined),
* gmlFormat: (ol.format.GMLBase|undefined),
* schemaLocation: (string|undefined)}}
* @api
@@ -1793,7 +1843,7 @@ olx.format.WFSOptions;
/**
* The namespace URI used for features.
* @type {string}
* @type {Object.<string, string>|string|undefined}
* @api stable
*/
olx.format.WFSOptions.prototype.featureNS;
@@ -1801,7 +1851,7 @@ olx.format.WFSOptions.prototype.featureNS;
/**
* The feature type to parse. Only used for read operations.
* @type {string}
* @type {Array.<string>|string|undefined}
* @api stable
*/
olx.format.WFSOptions.prototype.featureType;
@@ -3839,7 +3889,8 @@ olx.source.TileUTFGridOptions.prototype.url;
* tileGrid: (ol.tilegrid.TileGrid|undefined),
* tileLoadFunction: (ol.TileLoadFunctionType|undefined),
* tilePixelRatio: (number|undefined),
* tileUrlFunction: (ol.TileUrlFunctionType|undefined)}}
* tileUrlFunction: (ol.TileUrlFunctionType|undefined),
* wrapX: (boolean|undefined)}}
* @api
*/
olx.source.TileImageOptions;
@@ -3942,6 +3993,17 @@ olx.source.TileImageOptions.prototype.tilePixelRatio;
olx.source.TileImageOptions.prototype.tileUrlFunction;
/**
* Whether to wrap the world horizontally. The default, `undefined`, is to
* request out-of-bounds tiles from the server. When set to `false`, only one
* world will be rendered. When set to `true`, tiles will be requested for one
* world only, but they will be wrapped horizontally to render multiple worlds.
* @type {boolean|undefined}
* @api
*/
olx.source.TileImageOptions.prototype.wrapX;
/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* format: ol.format.Feature,
@@ -5018,7 +5080,8 @@ olx.source.ServerVectorOptions.prototype.projection;
* projection: ol.proj.ProjectionLike,
* tileLoadFunction: (ol.TileLoadFunctionType|undefined),
* url: (string|undefined),
* urls: (Array.<string>|undefined)}}
* urls: (Array.<string>|undefined),
* wrapX: (boolean|undefined)}}
* @api
*/
olx.source.TileArcGISRestOptions;
@@ -5034,9 +5097,9 @@ olx.source.TileArcGISRestOptions.prototype.attributions;
/**
* ArcGIS Rest parameters. This field is optional. Service defaults will be
* used for any fields not specified. `FORMAT` is `PNG32` by default. `F` is `IMAGE` by
* default. `TRANSPARENT` is `true` by default. `BBOX, `SIZE`, `BBOXSR`,
* default. `TRANSPARENT` is `true` by default. `BBOX, `SIZE`, `BBOXSR`,
* and `IMAGESR` will be set dynamically. Set `LAYERS` to
* override the default service layer visibility. See
* override the default service layer visibility. See
* {@link http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Export_Map/02r3000000v7000000/}
* for further reference.
* @type {Object.<string,*>|undefined}
@@ -5089,6 +5152,14 @@ olx.source.TileArcGISRestOptions.prototype.tileLoadFunction;
olx.source.TileArcGISRestOptions.prototype.url;
/**
* Whether to wrap the world horizontally. Default is `true`.
* @type {boolean|undefined}
* @api
*/
olx.source.TileArcGISRestOptions.prototype.wrapX;
/**
* ArcGIS Rest service urls. Use this instead of `url` when the ArcGIS Service supports multiple
* urls for export requests.
@@ -5168,7 +5239,8 @@ olx.source.TileJSONOptions.prototype.wrapX;
* serverType: (ol.source.wms.ServerType|string|undefined),
* tileLoadFunction: (ol.TileLoadFunctionType|undefined),
* url: (string|undefined),
* urls: (Array.<string>|undefined)}}
* urls: (Array.<string>|undefined),
* wrapX: (boolean|undefined)}}
* @api
*/
olx.source.TileWMSOptions;
@@ -5298,6 +5370,18 @@ olx.source.TileWMSOptions.prototype.url;
olx.source.TileWMSOptions.prototype.urls;
/**
* Whether to wrap the world horizontally. The default, `undefined`, is to
* request out-of-bounds tiles from the server. This works well in e.g.
* GeoServer. When set to `false`, only one world will be rendered. When set to
* `true`, tiles will be requested for one world only, but they will be wrapped
* horizontally to render multiple worlds.
* @type {boolean|undefined}
* @api
*/
olx.source.TileWMSOptions.prototype.wrapX;
/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* features: (Array.<ol.Feature>|undefined),
@@ -5474,7 +5558,8 @@ olx.source.StaticVectorOptions.prototype.urls;
* urls: (Array.<string>|undefined),
* tileClass: (function(new: ol.ImageTile, ol.TileCoord,
* ol.TileState, string, ?string,
* ol.TileLoadFunctionType)|undefined)}}
* ol.TileLoadFunctionType)|undefined),
* wrapX: (boolean|undefined)}}
* @api
*/
olx.source.WMTSOptions;
@@ -5633,6 +5718,14 @@ olx.source.WMTSOptions.prototype.tileLoadFunction;
olx.source.WMTSOptions.prototype.urls;
/**
* Whether to wrap the world horizontally. Default is `false`.
* @type {boolean|undefined}
* @api
*/
olx.source.WMTSOptions.prototype.wrapX;
/**
* @typedef {{attributions: (Array.<ol.Attribution>|undefined),
* crossOrigin: (null|string|undefined),
@@ -6048,7 +6141,7 @@ olx.style.IconOptions.prototype.rotateWithView;
/**
* Rotation.
* Rotation in radians (positive rotation clockwise). Default is `0`.
* @type {number|undefined}
* @api
*/
@@ -6293,7 +6386,7 @@ olx.style.TextOptions.prototype.scale;
/**
* Rotation.
* Rotation in radians (positive rotation clockwise). Default is `0`.
* @type {number|undefined}
* @api
*/
@@ -6414,7 +6507,8 @@ olx.tilegrid;
* origins: (Array.<ol.Coordinate>|undefined),
* resolutions: !Array.<number>,
* tileSize: (number|undefined),
* tileSizes: (Array.<number>|undefined)}}
* tileSizes: (Array.<number>|undefined),
* widths: (Array.<number>|undefined)}}
* @api
*/
olx.tilegrid.TileGridOptions;
@@ -6437,8 +6531,8 @@ olx.tilegrid.TileGridOptions.prototype.origin;
/**
* Origins. If given, the array should match the `resolutions` array, i.e.
* each resolution can have a different origin.
* Origins. If given, the array length should match the length of the
* `resolutions` array, i.e. each resolution can have a different origin.
* @type {Array.<ol.Coordinate>|undefined}
* @api stable
*/
@@ -6446,7 +6540,9 @@ olx.tilegrid.TileGridOptions.prototype.origins;
/**
* Resolutions.
* Resolutions. The array index of each resolution needs to match the zoom
* level. This means that even if a `minZoom` is configured, the resolutions
* array will have a length of `maxZoom + 1`.
* @type {!Array.<number>}
* @api stable
*/
@@ -6462,21 +6558,34 @@ olx.tilegrid.TileGridOptions.prototype.tileSize;
/**
* Tile sizes. If given, the array should match the `resolutions` array, i.e.
* each resolution can have a different tile size.
* Tile sizes. If given, the array length should match the length of the
* `resolutions` array, i.e. each resolution can have a different tile size.
* @type {Array.<number>|undefined}
* @api stable
*/
olx.tilegrid.TileGridOptions.prototype.tileSizes;
/**
* Number of tile columns that cover the grid's extent for each zoom level. Only
* required when used with a source that has `wrapX` set to `true`, and only
* when the grid's origin differs from the one of the projection's extent. The
* array length has to match the length of the `resolutions` array, i.e. each
* resolution will have a matching entry here.
* @type {Array.<number>|undefined}
* @api
*/
olx.tilegrid.TileGridOptions.prototype.widths;
/**
* @typedef {{origin: (ol.Coordinate|undefined),
* origins: (Array.<ol.Coordinate>|undefined),
* resolutions: !Array.<number>,
* matrixIds: !Array.<string>,
* tileSize: (number|undefined),
* tileSizes: (Array.<number>|undefined)}}
* tileSizes: (Array.<number>|undefined),
* widths: (Array.<number>|undefined)}}
* @api
*/
olx.tilegrid.WMTSOptions;
@@ -6491,7 +6600,8 @@ olx.tilegrid.WMTSOptions.prototype.origin;
/**
* Origins.
* Origins. The length of this array needs to match the length of the
* `resolutions` array.
* @type {Array.<ol.Coordinate>|undefined}
* @api
*/
@@ -6499,7 +6609,9 @@ olx.tilegrid.WMTSOptions.prototype.origins;
/**
* Resolutions.
* Resolutions. The array index of each resolution needs to match the zoom
* level. This means that even if a `minZoom` is configured, the resolutions
* array will have a length of `maxZoom + 1`
* @type {!Array.<number>}
* @api
*/
@@ -6507,7 +6619,8 @@ olx.tilegrid.WMTSOptions.prototype.resolutions;
/**
* matrix IDs.
* matrix IDs. The length of this array needs to match the length of the
* `resolutions` array.
* @type {!Array.<string>}
* @api
*/
@@ -6523,13 +6636,26 @@ olx.tilegrid.WMTSOptions.prototype.tileSize;
/**
* Tile sizes.
* Tile sizes. The length of this array needs to match the length of the
* `resolutions` array.
* @type {Array.<number>|undefined}
* @api
*/
olx.tilegrid.WMTSOptions.prototype.tileSizes;
/**
* Number of tile columns that cover the grid's extent for each zoom level. Only
* required when used with a source that has `wrapX` set to `true`, and only
* when the grid's origin differs from the one of the projection's extent. The
* array length has to match the length of the `resolutions` array, i.e. each
* resolution will have a matching entry here.
* @type {Array.<number>|undefined}
* @api
*/
olx.tilegrid.WMTSOptions.prototype.widths;
/**
* @typedef {{extent: (ol.Extent|undefined),
* maxZoom: (number|undefined),

View File

@@ -1,6 +1,6 @@
{
"name": "openlayers",
"version": "3.3.0",
"version": "3.4.0",
"description": "Build tools and sources for developing OpenLayers based mapping applications",
"keywords": [
"map",
@@ -31,7 +31,7 @@
"htmlparser2": "3.7.3",
"jsdoc": "3.3.0-alpha9",
"nomnom": "1.8.0",
"rbush": "1.3.4",
"rbush": "1.3.5",
"temp": "0.8.1",
"walk": "2.3.4"
},

View File

@@ -1,5 +1,7 @@
goog.provide('ol.Attribution');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('ol.TileRange');
@@ -54,22 +56,43 @@ ol.Attribution.prototype.getHTML = function() {
/**
* @param {Object.<string, ol.TileRange>} tileRanges Tile ranges.
* @param {!ol.tilegrid.TileGrid} tileGrid Tile grid.
* @param {!ol.proj.Projection} projection Projection.
* @return {boolean} Intersects any tile range.
*/
ol.Attribution.prototype.intersectsAnyTileRange = function(tileRanges) {
ol.Attribution.prototype.intersectsAnyTileRange =
function(tileRanges, tileGrid, projection) {
if (goog.isNull(this.tileRanges_)) {
return true;
}
var i, ii, tileRange, z;
for (z in tileRanges) {
if (!(z in this.tileRanges_)) {
var i, ii, tileRange, zKey;
for (zKey in tileRanges) {
if (!(zKey in this.tileRanges_)) {
continue;
}
tileRange = tileRanges[z];
for (i = 0, ii = this.tileRanges_[z].length; i < ii; ++i) {
if (this.tileRanges_[z][i].intersects(tileRange)) {
tileRange = tileRanges[zKey];
var testTileRange;
for (i = 0, ii = this.tileRanges_[zKey].length; i < ii; ++i) {
testTileRange = this.tileRanges_[zKey][i];
if (testTileRange.intersects(tileRange)) {
return true;
}
var extentTileRange = tileGrid.getTileRange(
parseInt(zKey, 10), projection);
var width = extentTileRange.getWidth();
if (tileRange.minX < extentTileRange.minX ||
tileRange.maxX > extentTileRange.maxX) {
if (testTileRange.intersects(new ol.TileRange(
goog.math.modulo(tileRange.minX, width),
goog.math.modulo(tileRange.maxX, width),
tileRange.minY, tileRange.maxY))) {
return true;
}
if (tileRange.getWidth() > width &&
testTileRange.intersects(extentTileRange)) {
return true;
}
}
}
}
return false;

View File

@@ -2,6 +2,7 @@
goog.provide('ol.control.Attribution');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.dom.classlist');
@@ -12,6 +13,7 @@ goog.require('goog.style');
goog.require('ol.Attribution');
goog.require('ol.control.Control');
goog.require('ol.css');
goog.require('ol.source.Tile');
@@ -158,11 +160,14 @@ goog.inherits(ol.control.Attribution, ol.control.Control);
ol.control.Attribution.prototype.getSourceAttributions = function(frameState) {
var i, ii, j, jj, tileRanges, source, sourceAttribution,
sourceAttributionKey, sourceAttributions, sourceKey;
var intersectsTileRange;
var layerStatesArray = frameState.layerStatesArray;
/** @type {Object.<string, ol.Attribution>} */
var attributions = goog.object.clone(frameState.attributions);
/** @type {Object.<string, ol.Attribution>} */
var hiddenAttributions = {};
var projection = frameState.viewState.projection;
goog.asserts.assert(!goog.isNull(projection));
for (i = 0, ii = layerStatesArray.length; i < ii; i++) {
source = layerStatesArray[i].layer.getSource();
if (goog.isNull(source)) {
@@ -180,14 +185,21 @@ ol.control.Attribution.prototype.getSourceAttributions = function(frameState) {
continue;
}
tileRanges = frameState.usedTiles[sourceKey];
if (goog.isDef(tileRanges) &&
sourceAttribution.intersectsAnyTileRange(tileRanges)) {
if (goog.isDef(tileRanges)) {
goog.asserts.assertInstanceof(source, ol.source.Tile);
var tileGrid = source.getTileGridForProjection(projection);
goog.asserts.assert(!goog.isNull(tileGrid));
intersectsTileRange = sourceAttribution.intersectsAnyTileRange(
tileRanges, tileGrid, projection);
} else {
intersectsTileRange = false;
}
if (intersectsTileRange) {
if (sourceAttributionKey in hiddenAttributions) {
delete hiddenAttributions[sourceAttributionKey];
}
attributions[sourceAttributionKey] = sourceAttribution;
}
else {
} else {
hiddenAttributions[sourceAttributionKey] = sourceAttribution;
}
}

View File

@@ -3,6 +3,7 @@ goog.provide('ol.control.FullScreen');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.dom.classlist');
goog.require('goog.dom.fullscreen');
goog.require('goog.dom.fullscreen.EventType');
goog.require('goog.events');
@@ -138,10 +139,15 @@ ol.control.FullScreen.prototype.handleFullScreen_ = function() {
* @private
*/
ol.control.FullScreen.prototype.handleFullScreenChange_ = function() {
var opened = this.cssClassName_ + '-true';
var closed = this.cssClassName_ + '-false';
var button = goog.dom.getFirstElementChild(this.element);
var map = this.getMap();
if (goog.dom.fullscreen.isFullScreen()) {
goog.dom.classlist.swap(button, closed, opened);
goog.dom.replaceNode(this.labelActiveNode_, this.labelNode_);
} else {
goog.dom.classlist.swap(button, opened, closed);
goog.dom.replaceNode(this.labelNode_, this.labelActiveNode_);
}
if (!goog.isNull(map)) {

View File

@@ -13,6 +13,7 @@ goog.require('ol.TransformFunction');
goog.require('ol.control.Control');
goog.require('ol.css');
goog.require('ol.proj');
goog.require('ol.proj.METERS_PER_UNIT');
goog.require('ol.proj.Units');
goog.require('ol.sphere.NORMAL');
@@ -227,20 +228,18 @@ ol.control.ScaleLine.prototype.updateElement_ = function() {
pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180;
projectionUnits = ol.proj.Units.METERS;
} else if ((projectionUnits == ol.proj.Units.FEET ||
projectionUnits == ol.proj.Units.METERS) &&
} else if (projectionUnits != ol.proj.Units.DEGREES &&
units == ol.control.ScaleLineUnits.DEGREES) {
// Convert pointResolution from meters or feet to degrees
// Convert pointResolution from other units to degrees
if (goog.isNull(this.toEPSG4326_)) {
this.toEPSG4326_ = ol.proj.getTransformFromProjections(
projection, ol.proj.get('EPSG:4326'));
}
cosLatitude = Math.cos(goog.math.toRadians(this.toEPSG4326_(center)[1]));
var radius = ol.sphere.NORMAL.radius;
if (projectionUnits == ol.proj.Units.FEET) {
radius /= 0.3048;
}
goog.asserts.assert(goog.isDef(ol.proj.METERS_PER_UNIT[projectionUnits]));
radius /= ol.proj.METERS_PER_UNIT[projectionUnits];
pointResolution *= 180 / (Math.PI * cosLatitude * radius);
projectionUnits = ol.proj.Units.DEGREES;

View File

@@ -68,7 +68,8 @@ ol.format.Feature.prototype.adaptOptions = function(options) {
updatedOptions = {
featureProjection: options.featureProjection,
dataProjection: goog.isDefAndNotNull(options.dataProjection) ?
options.dataProjection : this.defaultDataProjection
options.dataProjection : this.defaultDataProjection,
rightHanded: options.rightHanded
};
}
return updatedOptions;

View File

@@ -178,7 +178,8 @@ ol.format.GeoJSON.writeGeometry_ = function(geometry, opt_options) {
var geometryWriter = ol.format.GeoJSON.GEOMETRY_WRITERS_[geometry.getType()];
goog.asserts.assert(goog.isDef(geometryWriter));
return geometryWriter(/** @type {ol.geom.Geometry} */ (
ol.format.Feature.transformWithOptions(geometry, true, opt_options)));
ol.format.Feature.transformWithOptions(geometry, true, opt_options)),
opt_options);
};
@@ -217,10 +218,11 @@ ol.format.GeoJSON.writeGeometryCollectionGeometry_ = function(
/**
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry) {
ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.LineString);
return /** @type {GeoJSONGeometry} */ ({
'type': 'LineString',
@@ -231,10 +233,12 @@ ol.format.GeoJSON.writeLineStringGeometry_ = function(geometry) {
/**
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry) {
ol.format.GeoJSON.writeMultiLineStringGeometry_ =
function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.MultiLineString);
goog.asserts.assert(
geometry.getType() == ol.geom.GeometryType.MULTI_LINE_STRING);
@@ -247,10 +251,11 @@ ol.format.GeoJSON.writeMultiLineStringGeometry_ = function(geometry) {
/**
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry) {
ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPoint);
return /** @type {GeoJSONGeometry} */ ({
'type': 'MultiPoint',
@@ -261,24 +266,30 @@ ol.format.GeoJSON.writeMultiPointGeometry_ = function(geometry) {
/**
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry) {
ol.format.GeoJSON.writeMultiPolygonGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.MultiPolygon);
var right;
if (goog.isDef(opt_options)) {
right = opt_options.rightHanded;
}
return /** @type {GeoJSONGeometry} */ ({
'type': 'MultiPolygon',
'coordinates': geometry.getCoordinates()
'coordinates': geometry.getCoordinates(right)
});
};
/**
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
ol.format.GeoJSON.writePointGeometry_ = function(geometry) {
ol.format.GeoJSON.writePointGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
return /** @type {GeoJSONGeometry} */ ({
'type': 'Point',
@@ -289,14 +300,19 @@ ol.format.GeoJSON.writePointGeometry_ = function(geometry) {
/**
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @private
* @return {GeoJSONGeometry} GeoJSON geometry.
*/
ol.format.GeoJSON.writePolygonGeometry_ = function(geometry) {
ol.format.GeoJSON.writePolygonGeometry_ = function(geometry, opt_options) {
goog.asserts.assertInstanceof(geometry, ol.geom.Polygon);
var right;
if (goog.isDef(opt_options)) {
right = opt_options.rightHanded;
}
return /** @type {GeoJSONGeometry} */ ({
'type': 'Polygon',
'coordinates': geometry.getCoordinates()
'coordinates': geometry.getCoordinates(right)
});
};
@@ -320,7 +336,7 @@ ol.format.GeoJSON.GEOMETRY_READERS_ = {
/**
* @const
* @private
* @type {Object.<string, function(ol.geom.Geometry): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
* @type {Object.<string, function(ol.geom.Geometry, olx.format.WriteOptions=): (GeoJSONGeometry|GeoJSONGeometryCollection)>}
*/
ol.format.GeoJSON.GEOMETRY_WRITERS_ = {
'Point': ol.format.GeoJSON.writePointGeometry_,
@@ -482,7 +498,7 @@ ol.format.GeoJSON.prototype.readProjectionFromObject = function(object) {
*
* @function
* @param {ol.Feature} feature Feature.
* @param {olx.format.WriteOptions} options Write options.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @return {string} GeoJSON.
* @api stable
*/
@@ -516,6 +532,8 @@ ol.format.GeoJSON.prototype.writeFeatureObject = function(
goog.object.remove(properties, feature.getGeometryName());
if (!goog.object.isEmpty(properties)) {
object['properties'] = properties;
} else {
object['properties'] = null;
}
return object;
};
@@ -526,7 +544,7 @@ ol.format.GeoJSON.prototype.writeFeatureObject = function(
*
* @function
* @param {Array.<ol.Feature>} features Features.
* @param {olx.format.WriteOptions} options Write options.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @return {string} GeoJSON.
* @api stable
*/
@@ -561,7 +579,7 @@ ol.format.GeoJSON.prototype.writeFeaturesObject =
*
* @function
* @param {ol.geom.Geometry} geometry Geometry.
* @param {olx.format.WriteOptions} options Write options.
* @param {olx.format.WriteOptions=} opt_options Write options.
* @return {string} GeoJSON.
* @api stable
*/

View File

@@ -45,13 +45,13 @@ ol.format.GMLBase = function(opt_options) {
/**
* @protected
* @type {string}
* @type {Array.<string>|string|undefined}
*/
this.featureType = options.featureType;
/**
* @protected
* @type {string}
* @type {Object.<string, string>|string|undefined}
*/
this.featureNS = options.featureNS;
@@ -107,18 +107,52 @@ ol.format.GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
var context = objectStack[0];
goog.asserts.assert(goog.isObject(context));
var featureType = context['featureType'];
if (!goog.isDef(featureType) && !goog.isNull(node.firstElementChild)) {
var member = node.firstElementChild;
featureType = member.nodeName.split(':').pop();
var featureNS = context['featureNS'];
var i, ii, prefix = 'p', defaultPrefix = 'p0';
if (!goog.isDef(featureType) && goog.isDefAndNotNull(node.childNodes)) {
featureType = [], featureNS = {};
for (i = 0, ii = node.childNodes.length; i < ii; ++i) {
var child = node.childNodes[i];
if (child.nodeType === 1) {
var ft = child.nodeName.split(':').pop();
if (goog.array.indexOf(featureType, ft) === -1) {
var key;
if (!goog.object.contains(featureNS, child.namespaceURI)) {
key = prefix + goog.object.getCount(featureNS);
featureNS[key] = child.namespaceURI;
} else {
key = goog.object.findKey(featureNS, function(value) {
return value === child.namespaceURI;
});
}
featureType.push(key + ':' + ft);
}
}
}
context['featureType'] = featureType;
context['featureNS'] = member.namespaceURI;
context['featureNS'] = featureNS;
}
if (goog.isString(featureNS)) {
var ns = featureNS;
featureNS = {};
featureNS[defaultPrefix] = ns;
}
var parsers = {};
var parsersNS = {};
parsers[featureType] = (localName == 'featureMembers') ?
ol.xml.makeArrayPusher(this.readFeatureElement, this) :
ol.xml.makeReplacer(this.readFeatureElement, this);
parsersNS[context['featureNS']] = parsers;
var featureTypes = goog.isArray(featureType) ? featureType : [featureType];
for (var p in featureNS) {
var parsers = {};
for (i = 0, ii = featureTypes.length; i < ii; ++i) {
var featurePrefix = featureTypes[i].indexOf(':') === -1 ?
defaultPrefix : featureTypes[i].split(':')[0];
if (featurePrefix === p) {
parsers[featureTypes[i].split(':').pop()] =
(localName == 'featureMembers') ?
ol.xml.makeArrayPusher(this.readFeatureElement, this) :
ol.xml.makeReplacer(this.readFeatureElement, this);
}
}
parsersNS[featureNS[p]] = parsers;
}
features = ol.xml.pushParseAndPop([], parsersNS, node, objectStack);
}
if (!goog.isDef(features)) {

View File

@@ -5,6 +5,7 @@ goog.require('ol.Feature');
goog.require('ol.format.Feature');
goog.require('ol.format.TextFeature');
goog.require('ol.geom.LineString');
goog.require('ol.geom.SimpleGeometry');
goog.require('ol.geom.flat.flip');
goog.require('ol.geom.flat.inflate');
goog.require('ol.proj');
@@ -38,6 +39,13 @@ ol.format.Polyline = function(opt_options) {
* @type {number}
*/
this.factor_ = goog.isDef(options.factor) ? options.factor : 1e5;
/**
* @private
* @type {ol.geom.GeometryLayout}
*/
this.geometryLayout_ = goog.isDef(options.geometryLayout) ?
options.geometryLayout : ol.geom.GeometryLayout.XY;
};
goog.inherits(ol.format.Polyline, ol.format.TextFeature);
@@ -316,15 +324,17 @@ ol.format.Polyline.prototype.readGeometry;
*/
ol.format.Polyline.prototype.readGeometryFromText =
function(text, opt_options) {
var flatCoordinates = ol.format.Polyline.decodeDeltas(text, 2, this.factor_);
var stride = ol.geom.SimpleGeometry.getStrideForLayout(this.geometryLayout_);
var flatCoordinates = ol.format.Polyline.decodeDeltas(
text, stride, this.factor_);
ol.geom.flat.flip.flipXY(
flatCoordinates, 0, flatCoordinates.length, 2, flatCoordinates);
flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
var coordinates = ol.geom.flat.inflate.coordinates(
flatCoordinates, 0, flatCoordinates.length, 2);
flatCoordinates, 0, flatCoordinates.length, stride);
return /** @type {ol.geom.Geometry} */ (
ol.format.Feature.transformWithOptions(
new ol.geom.LineString(coordinates), false,
new ol.geom.LineString(coordinates, this.geometryLayout_), false,
this.adaptOptions(opt_options)));
};

View File

@@ -31,13 +31,13 @@ ol.format.WFS = function(opt_options) {
/**
* @private
* @type {string}
* @type {Array.<string>|string|undefined}
*/
this.featureType_ = options.featureType;
/**
* @private
* @type {string}
* @type {Object.<string, string>|string|undefined}
*/
this.featureNS_ = options.featureNS;

View File

@@ -29,22 +29,34 @@ ol.geom.flat.orient.linearRingIsClockwise =
/**
* Determines if linear rings are oriented. By default, left-hand orientation
* is tested (first ring must be clockwise, remaining rings counter-clockwise).
* To test for right-hand orientation, use the `opt_right` argument.
*
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array.<number>} ends Ends.
* @param {Array.<number>} ends Array of end indexes.
* @param {number} stride Stride.
* @return {boolean} `true` if all rings are correctly oriented, `false`
* otherwise.
* @param {boolean=} opt_right Test for right-hand orientation
* (counter-clockwise exterior ring and clockwise interior rings).
* @return {boolean} Rings are correctly oriented.
*/
ol.geom.flat.orient.linearRingsAreOriented =
function(flatCoordinates, offset, ends, stride) {
function(flatCoordinates, offset, ends, stride, opt_right) {
var right = goog.isDef(opt_right) ? opt_right : false;
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
var end = ends[i];
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
flatCoordinates, offset, end, stride);
if (i === 0 ? !isClockwise : isClockwise) {
return false;
if (i === 0) {
if ((right && isClockwise) || (!right && !isClockwise)) {
return false;
}
} else {
if ((right && !isClockwise) || (!right && isClockwise)) {
return false;
}
}
offset = end;
}
@@ -53,19 +65,24 @@ ol.geom.flat.orient.linearRingsAreOriented =
/**
* Determines if linear rings are oriented. By default, left-hand orientation
* is tested (first ring must be clockwise, remaining rings counter-clockwise).
* To test for right-hand orientation, use the `opt_right` argument.
*
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array.<Array.<number>>} endss Endss.
* @param {Array.<Array.<number>>} endss Array of array of end indexes.
* @param {number} stride Stride.
* @return {boolean} `true` if all rings are correctly oriented, `false`
* otherwise.
* @param {boolean=} opt_right Test for right-hand orientation
* (counter-clockwise exterior ring and clockwise interior rings).
* @return {boolean} Rings are correctly oriented.
*/
ol.geom.flat.linearRingssAreOriented =
function(flatCoordinates, offset, endss, stride) {
ol.geom.flat.orient.linearRingssAreOriented =
function(flatCoordinates, offset, endss, stride, opt_right) {
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
if (!ol.geom.flat.orient.linearRingsAreOriented(
flatCoordinates, offset, endss[i], stride)) {
flatCoordinates, offset, endss[i], stride, opt_right)) {
return false;
}
}
@@ -74,20 +91,29 @@ ol.geom.flat.linearRingssAreOriented =
/**
* Orient coordinates in a flat array of linear rings. By default, rings
* are oriented following the left-hand rule (clockwise for exterior and
* counter-clockwise for interior rings). To orient according to the
* right-hand rule, use the `opt_right` argument.
*
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array.<number>} ends Ends.
* @param {number} stride Stride.
* @param {boolean=} opt_right Follow the right-hand rule for orientation.
* @return {number} End.
*/
ol.geom.flat.orient.orientLinearRings =
function(flatCoordinates, offset, ends, stride) {
function(flatCoordinates, offset, ends, stride, opt_right) {
var right = goog.isDef(opt_right) ? opt_right : false;
var i, ii;
for (i = 0, ii = ends.length; i < ii; ++i) {
var end = ends[i];
var isClockwise = ol.geom.flat.orient.linearRingIsClockwise(
flatCoordinates, offset, end, stride);
var reverse = i === 0 ? !isClockwise : isClockwise;
var reverse = i === 0 ?
(right && isClockwise) || (!right && !isClockwise) :
(right && !isClockwise) || (!right && isClockwise);
if (reverse) {
ol.geom.flat.reverse.coordinates(flatCoordinates, offset, end, stride);
}
@@ -98,18 +124,24 @@ ol.geom.flat.orient.orientLinearRings =
/**
* Orient coordinates in a flat array of linear rings. By default, rings
* are oriented following the left-hand rule (clockwise for exterior and
* counter-clockwise for interior rings). To orient according to the
* right-hand rule, use the `opt_right` argument.
*
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array.<Array.<number>>} endss Endss.
* @param {Array.<Array.<number>>} endss Array of array of end indexes.
* @param {number} stride Stride.
* @param {boolean=} opt_right Follow the right-hand rule for orientation.
* @return {number} End.
*/
ol.geom.flat.orient.orientLinearRingss =
function(flatCoordinates, offset, endss, stride) {
function(flatCoordinates, offset, endss, stride, opt_right) {
var i, ii;
for (i = 0, ii = endss.length; i < ii; ++i) {
offset = ol.geom.flat.orient.orientLinearRings(
flatCoordinates, offset, endss[i], stride);
flatCoordinates, offset, endss[i], stride, opt_right);
}
return offset;
};

View File

@@ -9,20 +9,22 @@ goog.provide('ol.geom.flat.segments');
* @param {number} offset Offset.
* @param {number} end End.
* @param {number} stride Stride.
* @param {function(ol.Coordinate, ol.Coordinate): T} callback Function
* @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
* called for each segment.
* @param {S=} opt_this The object to be used as the value of 'this'
* within callback.
* @return {T|boolean} Value.
* @template T
* @template T,S
*/
ol.geom.flat.segments.forEach =
function(flatCoordinates, offset, end, stride, callback) {
function(flatCoordinates, offset, end, stride, callback, opt_this) {
var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]];
var point2 = [];
var ret;
for (; (offset + stride) < end; offset += stride) {
point2[0] = flatCoordinates[offset + stride];
point2[1] = flatCoordinates[offset + stride + 1];
ret = callback(point1, point2);
ret = callback.call(opt_this, point1, point2);
if (ret) {
return ret;
}

View File

@@ -11,6 +11,7 @@ goog.require('ol.geom.flat.inflate');
goog.require('ol.geom.flat.interpolate');
goog.require('ol.geom.flat.intersectsextent');
goog.require('ol.geom.flat.length');
goog.require('ol.geom.flat.segments');
goog.require('ol.geom.flat.simplify');
@@ -107,6 +108,25 @@ ol.geom.LineString.prototype.closestPointXY =
};
/**
* Iterate over each segment, calling the provided callback.
* If the callback returns a truthy value the function returns that
* value immediately. Otherwise the function returns `false`.
*
* @param {function(this: S, ol.Coordinate, ol.Coordinate): T} callback Function
* called for each segment.
* @param {S=} opt_this The object to be used as the value of 'this'
* within callback.
* @return {T|boolean} Value.
* @template T,S
* @api
*/
ol.geom.LineString.prototype.forEachSegment = function(callback, opt_this) {
return ol.geom.flat.segments.forEach(this.flatCoordinates, 0,
this.flatCoordinates.length, this.stride, callback, opt_this);
};
/**
* Returns the coordinate at `m` using linear interpolation, or `null` if no
* such coordinate exists.

View File

@@ -162,12 +162,30 @@ ol.geom.MultiPolygon.prototype.getArea = function() {
/**
* Get the coordinate array for this geometry. This array has the structure
* of a GeoJSON coordinate array for multi-polygons.
*
* @param {boolean=} opt_right Orient coordinates according to the right-hand
* rule (counter-clockwise for exterior and clockwise for interior rings).
* If `false`, coordinates will be oriented according to the left-hand rule
* (clockwise for exterior and counter-clockwise for interior rings).
* By default, coordinate orientation will depend on how the geometry was
* constructed.
* @return {Array.<Array.<Array.<ol.Coordinate>>>} Coordinates.
* @api stable
*/
ol.geom.MultiPolygon.prototype.getCoordinates = function() {
ol.geom.MultiPolygon.prototype.getCoordinates = function(opt_right) {
var flatCoordinates;
if (goog.isDef(opt_right)) {
flatCoordinates = this.getOrientedFlatCoordinates().slice();
ol.geom.flat.orient.orientLinearRingss(
flatCoordinates, 0, this.endss_, this.stride, opt_right);
} else {
flatCoordinates = this.flatCoordinates;
}
return ol.geom.flat.inflate.coordinatesss(
this.flatCoordinates, 0, this.endss_, this.stride);
flatCoordinates, 0, this.endss_, this.stride);
};
@@ -213,7 +231,7 @@ ol.geom.MultiPolygon.prototype.getInteriorPoints = function() {
ol.geom.MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
if (this.orientedRevision_ != this.getRevision()) {
var flatCoordinates = this.flatCoordinates;
if (ol.geom.flat.linearRingssAreOriented(
if (ol.geom.flat.orient.linearRingssAreOriented(
flatCoordinates, 0, this.endss_, this.stride)) {
this.orientedFlatCoordinates_ = flatCoordinates;
} else {

View File

@@ -151,12 +151,30 @@ ol.geom.Polygon.prototype.getArea = function() {
/**
* Get the coordinate array for this geometry. This array has the structure
* of a GeoJSON coordinate array for polygons.
*
* @param {boolean=} opt_right Orient coordinates according to the right-hand
* rule (counter-clockwise for exterior and clockwise for interior rings).
* If `false`, coordinates will be oriented according to the left-hand rule
* (clockwise for exterior and counter-clockwise for interior rings).
* By default, coordinate orientation will depend on how the geometry was
* constructed.
* @return {Array.<Array.<ol.Coordinate>>} Coordinates.
* @api stable
*/
ol.geom.Polygon.prototype.getCoordinates = function() {
ol.geom.Polygon.prototype.getCoordinates = function(opt_right) {
var flatCoordinates;
if (goog.isDef(opt_right)) {
flatCoordinates = this.getOrientedFlatCoordinates().slice();
ol.geom.flat.orient.orientLinearRings(
flatCoordinates, 0, this.ends_, this.stride, opt_right);
} else {
flatCoordinates = this.flatCoordinates;
}
return ol.geom.flat.inflate.coordinatess(
this.flatCoordinates, 0, this.ends_, this.stride);
flatCoordinates, 0, this.ends_, this.stride);
};

View File

@@ -64,10 +64,9 @@ ol.geom.SimpleGeometry.getLayoutForStride_ = function(stride) {
/**
* @param {ol.geom.GeometryLayout} layout Layout.
* @private
* @return {number} Stride.
*/
ol.geom.SimpleGeometry.getStrideForLayout_ = function(layout) {
ol.geom.SimpleGeometry.getStrideForLayout = function(layout) {
if (layout == ol.geom.GeometryLayout.XY) {
return 2;
} else if (layout == ol.geom.GeometryLayout.XYZ) {
@@ -200,7 +199,7 @@ ol.geom.SimpleGeometry.prototype.getStride = function() {
*/
ol.geom.SimpleGeometry.prototype.setFlatCoordinatesInternal =
function(layout, flatCoordinates) {
this.stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
this.stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
this.layout = layout;
this.flatCoordinates = flatCoordinates;
};
@@ -217,7 +216,7 @@ ol.geom.SimpleGeometry.prototype.setLayout =
/** @type {number} */
var stride;
if (goog.isDef(layout)) {
stride = ol.geom.SimpleGeometry.getStrideForLayout_(layout);
stride = ol.geom.SimpleGeometry.getStrideForLayout(layout);
} else {
var i;
for (i = 0; i < nesting; ++i) {

View File

@@ -128,6 +128,7 @@ ol.Image.prototype.handleImageLoad_ = function() {
ol.Image.prototype.load = function() {
if (this.state == ol.ImageState.IDLE) {
this.state = ol.ImageState.LOADING;
this.changed();
goog.asserts.assert(goog.isNull(this.imageListenerKeys_));
this.imageListenerKeys_ = [
goog.events.listenOnce(this.image_, goog.events.EventType.ERROR,

View File

@@ -68,7 +68,9 @@ goog.inherits(ol.ImageTile, ol.Tile);
* @inheritDoc
*/
ol.ImageTile.prototype.disposeInternal = function() {
this.unlistenImage_();
if (this.state == ol.TileState.LOADING) {
this.unlistenImage_();
}
goog.base(this, 'disposeInternal');
};

View File

@@ -9,11 +9,11 @@ goog.require('ol.Collection');
goog.require('ol.Coordinate');
goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.Map');
goog.require('ol.MapBrowserEvent');
goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.Object');
goog.require('ol.events.condition');
goog.require('ol.geom.Circle');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
goog.require('ol.geom.MultiLineString');
@@ -247,10 +247,6 @@ ol.interaction.Draw.prototype.setMap = function(map) {
* @api
*/
ol.interaction.Draw.handleEvent = function(mapBrowserEvent) {
var map = mapBrowserEvent.map;
if (!map.isDef()) {
return true;
}
var pass = true;
if (mapBrowserEvent.type === ol.MapBrowserEvent.EventType.POINTERMOVE) {
pass = this.handlePointerMove_(mapBrowserEvent);
@@ -295,6 +291,8 @@ ol.interaction.Draw.handleUpEvent_ = function(event) {
if (goog.isNull(this.finishCoordinate_)) {
this.startDrawing_(event);
} else if (this.mode_ === ol.interaction.DrawMode.POINT ||
this.mode_ === ol.interaction.DrawMode.CIRCLE &&
!goog.isNull(this.finishCoordinate_) ||
this.atFinish_(event)) {
this.finishDrawing();
} else {
@@ -403,6 +401,10 @@ ol.interaction.Draw.prototype.startDrawing_ = function(event) {
start.slice()]));
this.sketchPolygonCoords_ = [[start.slice(), start.slice()]];
geometry = new ol.geom.Polygon(this.sketchPolygonCoords_);
} else if (this.mode_ === ol.interaction.DrawMode.CIRCLE) {
geometry = new ol.geom.Circle(start.slice(), 0);
this.sketchLine_ = new ol.Feature(new ol.geom.LineString([start.slice(),
start.slice()]));
}
}
goog.asserts.assert(goog.isDef(geometry));
@@ -425,7 +427,7 @@ ol.interaction.Draw.prototype.startDrawing_ = function(event) {
ol.interaction.Draw.prototype.modifyDrawing_ = function(event) {
var coordinate = event.coordinate;
var geometry = this.sketchFeature_.getGeometry();
var coordinates, last;
var coordinates, last, sketchLineGeom;
if (this.mode_ === ol.interaction.DrawMode.POINT) {
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
last = geometry.getCoordinates();
@@ -439,6 +441,9 @@ ol.interaction.Draw.prototype.modifyDrawing_ = function(event) {
} else if (this.mode_ === ol.interaction.DrawMode.POLYGON) {
goog.asserts.assertInstanceof(geometry, ol.geom.Polygon);
coordinates = this.sketchPolygonCoords_[0];
} else if (this.mode_ === ol.interaction.DrawMode.CIRCLE) {
goog.asserts.assertInstanceof(geometry, ol.geom.Circle);
coordinates = geometry.getCenter();
}
if (this.atFinish_(event)) {
// snap to finish
@@ -454,11 +459,17 @@ ol.interaction.Draw.prototype.modifyDrawing_ = function(event) {
goog.asserts.assertInstanceof(geometry, ol.geom.LineString);
geometry.setCoordinates(coordinates);
} else if (this.mode_ === ol.interaction.DrawMode.POLYGON) {
var sketchLineGeom = this.sketchLine_.getGeometry();
sketchLineGeom = this.sketchLine_.getGeometry();
goog.asserts.assertInstanceof(sketchLineGeom, ol.geom.LineString);
sketchLineGeom.setCoordinates(coordinates);
goog.asserts.assertInstanceof(geometry, ol.geom.Polygon);
geometry.setCoordinates(this.sketchPolygonCoords_);
} else if (this.mode_ === ol.interaction.DrawMode.CIRCLE) {
goog.asserts.assertInstanceof(geometry, ol.geom.Circle);
sketchLineGeom = this.sketchLine_.getGeometry();
goog.asserts.assertInstanceof(sketchLineGeom, ol.geom.LineString);
sketchLineGeom.setCoordinates([geometry.getCenter(), coordinate]);
geometry.setRadius(sketchLineGeom.getLength());
}
}
this.updateSketchFeatures_();
@@ -562,7 +573,7 @@ ol.interaction.Draw.prototype.shouldStopEvent = goog.functions.FALSE;
/**
* Redraw the skecth features.
* Redraw the sketch features.
* @private
*/
ol.interaction.Draw.prototype.updateSketchFeatures_ = function() {
@@ -611,6 +622,8 @@ ol.interaction.Draw.getMode_ = function(type) {
} else if (type === ol.geom.GeometryType.POLYGON ||
type === ol.geom.GeometryType.MULTI_POLYGON) {
mode = ol.interaction.DrawMode.POLYGON;
} else if (type === ol.geom.GeometryType.CIRCLE) {
mode = ol.interaction.DrawMode.CIRCLE;
}
goog.asserts.assert(goog.isDef(mode));
return mode;
@@ -625,5 +638,6 @@ ol.interaction.Draw.getMode_ = function(type) {
ol.interaction.DrawMode = {
POINT: 'Point',
LINE_STRING: 'LineString',
POLYGON: 'Polygon'
POLYGON: 'Polygon',
CIRCLE: 'Circle'
};

View File

@@ -391,6 +391,17 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
};
/**
* @param {ol.interaction.SegmentDataType} a
* @param {ol.interaction.SegmentDataType} b
* @return {number}
* @private
*/
ol.interaction.Modify.compareIndexes_ = function(a, b) {
return a.index - b.index;
};
/**
* @param {ol.MapBrowserPointerEvent} evt Event.
* @return {boolean} Start drag sequence?
@@ -403,18 +414,44 @@ ol.interaction.Modify.handleDownEvent_ = function(evt) {
var vertexFeature = this.vertexFeature_;
if (!goog.isNull(vertexFeature)) {
var insertVertices = [];
var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
var vertex = geometry.getCoordinates();
var vertexExtent = ol.extent.boundingExtent([vertex]);
var segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
var componentSegments = {};
segmentDataMatches.sort(ol.interaction.Modify.compareIndexes_);
for (var i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
var segmentDataMatch = segmentDataMatches[i];
var segment = segmentDataMatch.segment;
if (ol.coordinate.equals(segment[0], vertex)) {
var uid = goog.getUid(segmentDataMatch.feature);
var depth = segmentDataMatch.depth;
if (depth) {
uid += '-' + depth.join('-'); // separate feature components
}
if (!componentSegments[uid]) {
componentSegments[uid] = new Array(2);
}
if (ol.coordinate.equals(segment[0], vertex) &&
!componentSegments[uid][0]) {
this.dragSegments_.push([segmentDataMatch, 0]);
} else if (ol.coordinate.equals(segment[1], vertex)) {
componentSegments[uid][0] = segmentDataMatch;
} else if (ol.coordinate.equals(segment[1], vertex) &&
!componentSegments[uid][1]) {
// prevent dragging closed linestrings by the connecting node
if ((segmentDataMatch.geometry.getType() ===
ol.geom.GeometryType.LINE_STRING ||
segmentDataMatch.geometry.getType() ===
ol.geom.GeometryType.MULTI_LINE_STRING) &&
componentSegments[uid][0] &&
componentSegments[uid][0].index === 0) {
continue;
}
this.dragSegments_.push([segmentDataMatch, 1]);
} else if (goog.getUid(segment) in this.vertexSegments_) {
componentSegments[uid][1] = segmentDataMatch;
} else if (goog.getUid(segment) in this.vertexSegments_ &&
(!componentSegments[uid][0] && !componentSegments[uid][1])) {
insertVertices.push([segmentDataMatch, vertex]);
}
}
@@ -474,8 +511,8 @@ ol.interaction.Modify.handleDragEvent_ = function(evt) {
}
geometry.setCoordinates(coordinates);
this.createOrUpdateVertexFeature_(vertex);
}
this.createOrUpdateVertexFeature_(vertex);
};
@@ -505,10 +542,11 @@ ol.interaction.Modify.handleUpEvent_ = function(evt) {
ol.interaction.Modify.handleEvent = function(mapBrowserEvent) {
var handled;
if (!mapBrowserEvent.map.getView().getHints()[ol.ViewHint.INTERACTING] &&
mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERMOVE) {
mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERMOVE &&
!this.handlingDownUpSequence) {
this.handlePointerMove_(mapBrowserEvent);
}
if (!goog.isNull(this.vertexFeature_) && this.snappedToVertex_ &&
if (!goog.isNull(this.vertexFeature_) &&
this.deleteCondition_(mapBrowserEvent)) {
var geometry = this.vertexFeature_.getGeometry();
goog.asserts.assertInstanceof(geometry, ol.geom.Point);
@@ -674,15 +712,18 @@ ol.interaction.Modify.prototype.insertVertex_ = function(segmentData, vertex) {
ol.interaction.Modify.prototype.removeVertex_ = function() {
var dragSegments = this.dragSegments_;
var segmentsByFeature = {};
var deleted = false;
var component, coordinates, dragSegment, geometry, i, index, left;
var newIndex, newSegment, right, segmentData, uid;
var newIndex, newSegment, right, segmentData, uid, deleted;
for (i = dragSegments.length - 1; i >= 0; --i) {
dragSegment = dragSegments[i];
segmentData = dragSegment[0];
geometry = segmentData.geometry;
coordinates = geometry.getCoordinates();
uid = goog.getUid(segmentData.feature);
if (segmentData.depth) {
// separate feature components
uid += '-' + segmentData.depth.join('-');
}
left = right = index = undefined;
if (dragSegment[1] === 0) {
right = segmentData;
@@ -756,7 +797,7 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
}
}
}
return deleted;
return true;
};

View File

@@ -184,13 +184,10 @@ ol.interaction.Pointer.handleEvent = function(mapBrowserEvent) {
var stopEvent = false;
this.updateTrackedPointers_(mapBrowserEvent);
if (this.handlingDownUpSequence) {
if (mapBrowserEvent.type ==
ol.MapBrowserEvent.EventType.POINTERDRAG) {
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERDRAG) {
this.handleDragEvent_(mapBrowserEvent);
} else if (mapBrowserEvent.type ==
ol.MapBrowserEvent.EventType.POINTERUP) {
this.handlingDownUpSequence =
this.handleUpEvent_(mapBrowserEvent);
} else if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERUP) {
this.handlingDownUpSequence = this.handleUpEvent_(mapBrowserEvent);
}
}
if (mapBrowserEvent.type == ol.MapBrowserEvent.EventType.POINTERDOWN) {

View File

@@ -36,6 +36,7 @@ ol.SelectEventType = {
* @param {string} type The event type.
* @param {Array.<ol.Feature>} selected Selected features.
* @param {Array.<ol.Feature>} deselected Deselected features.
* @implements {oli.SelectEvent}
* @extends {goog.events.Event}
* @constructor
*/
@@ -198,7 +199,8 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
*/
function(feature, layer) {
selected.push(feature);
}, undefined, this.layerFilter_);
return !this.multi_;
}, this, this.layerFilter_);
if (selected.length > 0 && features.getLength() == 1 &&
features.item(0) == selected[0]) {
// No change
@@ -208,11 +210,7 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
deselected = Array.prototype.concat(features.getArray());
features.clear();
}
if (this.multi_) {
features.extend(selected);
} else if (selected.length > 0) {
features.push(selected[0]);
}
features.extend(selected);
}
} else {
// Modify the currently selected feature(s).

View File

@@ -1024,13 +1024,7 @@ ol.Map.prototype.handleTargetChanged_ = function() {
// If it's not now an Element we remove the viewport from the DOM.
// If it's an Element we append the viewport element to it.
var target = this.getTarget();
/**
* @type {Element}
*/
var targetElement = goog.isDef(target) ?
goog.dom.getElement(target) : null;
var targetElement = this.getTargetElement();
this.keyHandler_.detach();
@@ -1431,12 +1425,7 @@ ol.Map.prototype.skipFeature = function(feature) {
* @api stable
*/
ol.Map.prototype.updateSize = function() {
var target = this.getTarget();
/**
* @type {Element}
*/
var targetElement = goog.isDef(target) ? goog.dom.getElement(target) : null;
var targetElement = this.getTargetElement();
if (goog.isNull(targetElement)) {
this.setSize(undefined);

View File

@@ -16,12 +16,6 @@ goog.provide('ol');
ol.ASSUME_TOUCH = false;
/**
* @define {boolean} Replace unused entries with NaNs.
*/
ol.BUFFER_REPLACE_UNUSED_ENTRIES_WITH_NANS = goog.DEBUG;
/**
* TODO: rename this to something having to do with tile grids
* see https://github.com/openlayers/ol3/issues/2076

View File

@@ -90,7 +90,9 @@ ol.Overlay = function(options) {
* @private
* @type {Element}
*/
this.element_ = goog.dom.createElement(goog.dom.TagName.DIV);
this.element_ = goog.dom.createDom(goog.dom.TagName.DIV, {
'class': 'ol-overlay-container'
});
this.element_.style.position = 'absolute';
/**

View File

@@ -121,12 +121,54 @@ ol.proj.Projection = function(options) {
*/
this.global_ = goog.isDef(options.global) ? options.global : false;
/**
* @private
* @type {function(number, ol.Coordinate):number}
*/
this.getPointResolutionFunc_ = goog.isDef(options.getPointResolution) ?
options.getPointResolution : this.getPointResolution_;
/**
* @private
* @type {ol.tilegrid.TileGrid}
*/
this.defaultTileGrid_ = null;
if (ol.ENABLE_PROJ4JS && typeof proj4 == 'function') {
var code = options.code;
var def = proj4.defs(code);
if (goog.isDef(def)) {
if (goog.isDef(def.axis) && !goog.isDef(options.axisOrientation)) {
this.axisOrientation_ = def.axis;
}
if (!goog.isDef(options.units)) {
var units = def.units;
if (!goog.isDef(units)) {
if (goog.isDef(def.to_meter)) {
units = def.to_meter.toString();
ol.proj.METERS_PER_UNIT[units] = def.to_meter;
}
}
this.units_ = units;
}
var projections = ol.proj.projections_;
var currentCode, currentDef, currentProj, proj4Transform;
for (currentCode in projections) {
currentDef = proj4.defs(currentCode);
if (goog.isDef(currentDef)) {
currentProj = ol.proj.get(currentCode);
if (currentDef === def) {
ol.proj.addEquivalentProjections([currentProj, this]);
} else {
proj4Transform = proj4(currentCode, code);
ol.proj.addCoordinateTransforms(currentProj, this,
proj4Transform.forward, proj4Transform.inverse);
}
}
}
}
}
};
@@ -206,6 +248,16 @@ ol.proj.Projection.prototype.isGlobal = function() {
};
/**
* Set if the projection is a global projection which spans the whole world
* @param {boolean} global Whether the projection is global.
* @api stable
*/
ol.proj.Projection.prototype.setGlobal = function(global) {
this.global_ = global;
};
/**
* @return {ol.tilegrid.TileGrid} The default tile grid.
*/
@@ -244,16 +296,29 @@ ol.proj.Projection.prototype.setWorldExtent = function(worldExtent) {
/**
* Get the resolution of the point in degrees. For projections with degrees as
* the unit this will simply return the provided resolution. For other
* projections the point resolution is estimated by transforming the center
* pixel to EPSG:4326, measuring its width and height on the normal sphere,
* and taking the average of the width and height.
* @param {number} resolution Resolution.
* @param {ol.Coordinate} point Point.
* @return {number} Point resolution.
*/
ol.proj.Projection.prototype.getPointResolution = function(resolution, point) {
* Set the getPointResolution function for this projection.
* @param {function(number, ol.Coordinate):number} func Function
* @api
*/
ol.proj.Projection.prototype.setGetPointResolution = function(func) {
this.getPointResolutionFunc_ = func;
};
/**
* Default version.
* Get the resolution of the point in degrees or distance units.
* For projections with degrees as the unit this will simply return the
* provided resolution. For other projections the point resolution is
* estimated by transforming the 'point' pixel to EPSG:4326,
* measuring its width and height on the normal sphere,
* and taking the average of the width and height.
* @param {number} resolution Nominal resolution in projection units.
* @param {ol.Coordinate} point Point to find adjusted resolution at.
* @return {number} Point resolution at point in projection units.
* @private
*/
ol.proj.Projection.prototype.getPointResolution_ = function(resolution, point) {
var units = this.getUnits();
if (units == ol.proj.Units.DEGREES) {
return resolution;
@@ -284,6 +349,26 @@ ol.proj.Projection.prototype.getPointResolution = function(resolution, point) {
};
/**
* Get the resolution of the point in degrees or distance units.
* For projections with degrees as the unit this will simply return the
* provided resolution. The default for other projections is to estimate
* the point resolution by transforming the 'point' pixel to EPSG:4326,
* measuring its width and height on the normal sphere,
* and taking the average of the width and height.
* An alternative implementation may be given when constructing a
* projection. For many local projections,
* such a custom function will return the resolution unchanged.
* @param {number} resolution Resolution in projection units.
* @param {ol.Coordinate} point Point.
* @return {number} Point resolution in projection units.
* @api
*/
ol.proj.Projection.prototype.getPointResolution = function(resolution, point) {
return this.getPointResolutionFunc_(resolution, point);
};
/**
* @private
* @type {Object.<string, ol.proj.Projection>}
@@ -342,7 +427,8 @@ ol.proj.addEquivalentTransforms =
/**
* Add a Projection object to the list of supported projections.
* Add a Projection object to the list of supported projections that can be
* looked up by their code.
*
* @param {ol.proj.Projection} projection Projection instance.
* @api stable
@@ -512,43 +598,11 @@ ol.proj.get = function(projectionLike) {
projection = projectionLike;
} else if (goog.isString(projectionLike)) {
var code = projectionLike;
var projections = ol.proj.projections_;
projection = projections[code];
projection = ol.proj.projections_[code];
if (ol.ENABLE_PROJ4JS && !goog.isDef(projection) &&
typeof proj4 == 'function') {
var def = proj4.defs(code);
if (goog.isDef(def)) {
var units = def.units;
if (!goog.isDef(units)) {
if (goog.isDef(def.to_meter)) {
units = def.to_meter.toString();
ol.proj.METERS_PER_UNIT[units] = def.to_meter;
}
}
projection = new ol.proj.Projection({
code: code,
units: units,
axisOrientation: def.axis
});
ol.proj.addProjection(projection);
var currentCode, currentDef, currentProj, proj4Transform;
for (currentCode in projections) {
currentDef = proj4.defs(currentCode);
if (goog.isDef(currentDef)) {
currentProj = ol.proj.get(currentCode);
if (currentDef === def) {
ol.proj.addEquivalentProjections([currentProj, projection]);
} else {
proj4Transform = proj4(currentCode, code);
ol.proj.addCoordinateTransforms(currentProj, projection,
proj4Transform.forward, proj4Transform.inverse);
}
}
}
} else {
goog.asserts.assert(goog.isDef(projection));
projection = null;
}
typeof proj4 == 'function' && goog.isDef(proj4.defs(code))) {
projection = new ol.proj.Projection({code: code});
ol.proj.addProjection(projection);
}
} else {
projection = null;

View File

@@ -1,6 +1,5 @@
goog.provide('ol.renderer.Layer');
goog.require('goog.Disposable');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
@@ -151,7 +150,7 @@ ol.renderer.Layer.prototype.loadImage = function(image) {
// listener (a noop if the listener was already registered)
goog.asserts.assert(imageState == ol.ImageState.IDLE ||
imageState == ol.ImageState.LOADING);
goog.events.listenOnce(image, goog.events.EventType.CHANGE,
goog.events.listen(image, goog.events.EventType.CHANGE,
this.handleImageChange_, false, this);
}
if (imageState == ol.ImageState.IDLE) {

View File

@@ -33,7 +33,8 @@ ol.source.BingMaps = function(options) {
opaque: true,
projection: ol.proj.get('EPSG:3857'),
state: ol.source.State.LOADING,
tileLoadFunction: options.tileLoadFunction
tileLoadFunction: options.tileLoadFunction,
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
});
/**
@@ -48,12 +49,6 @@ ol.source.BingMaps = function(options) {
*/
this.maxZoom_ = goog.isDef(options.maxZoom) ? options.maxZoom : -1;
/**
* @private
* @type {boolean}
*/
this.wrapX_ = goog.isDef(options.wrapX) ? options.wrapX : true;
var protocol = ol.IS_HTTPS ? 'https:' : 'http:';
var uri = new goog.Uri(
protocol + '//dev.virtualearth.net/REST/v1/Imagery/Metadata/' +
@@ -117,7 +112,7 @@ ol.source.BingMaps.prototype.handleImageryMetadataResponse =
var culture = this.culture_;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
tileGrid.createTileCoordTransform({wrapX: this.wrapX_}),
tileGrid.createTileCoordTransform(),
ol.TileUrlFunction.createFromTileUrlFunctions(
goog.array.map(
resource.imageUrlSubdomains,

View File

@@ -1,5 +1,7 @@
goog.provide('ol.source.ImageMapGuide');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('goog.uri.utils');
goog.require('ol.Image');
@@ -15,6 +17,7 @@ goog.require('ol.source.Image');
* Source for images from Mapguide servers
*
* @constructor
* @fires ol.source.ImageEvent
* @extends {ol.source.Image}
* @param {olx.source.ImageMapGuideOptions} options Options.
* @api stable
@@ -150,6 +153,8 @@ ol.source.ImageMapGuide.prototype.getImage =
image = new ol.Image(extent, resolution, pixelRatio,
this.getAttributions(), imageUrl, this.crossOrigin_,
this.imageLoadFunction_);
goog.events.listen(image, goog.events.EventType.CHANGE,
this.handleImageChange, false, this);
} else {
image = null;
}

View File

@@ -2,8 +2,10 @@ goog.provide('ol.source.Image');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events.Event');
goog.require('ol.Attribution');
goog.require('ol.Extent');
goog.require('ol.ImageState');
goog.require('ol.array');
goog.require('ol.source.Source');
@@ -90,6 +92,33 @@ ol.source.Image.prototype.findNearestResolution =
ol.source.Image.prototype.getImage = goog.abstractMethod;
/**
* Handle image change events.
* @param {goog.events.Event} event Event.
* @protected
*/
ol.source.Image.prototype.handleImageChange = function(event) {
var image = /** @type {ol.Image} */ (event.target);
switch (image.getState()) {
case ol.ImageState.LOADING:
this.dispatchEvent(
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADSTART,
image));
break;
case ol.ImageState.LOADED:
this.dispatchEvent(
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADEND,
image));
break;
case ol.ImageState.ERROR:
this.dispatchEvent(
new ol.source.ImageEvent(ol.source.ImageEventType.IMAGELOADERROR,
image));
break;
}
};
/**
* Default image load function for image sources that use ol.Image image
* instances.
@@ -99,3 +128,59 @@ ol.source.Image.prototype.getImage = goog.abstractMethod;
ol.source.Image.defaultImageLoadFunction = function(image, src) {
image.getImage().src = src;
};
/**
* @classdesc
* Events emitted by {@link ol.source.Image} instances are instances of this
* type.
*
* @constructor
* @extends {goog.events.Event}
* @implements {oli.source.ImageEvent}
* @param {string} type Type.
* @param {ol.Image} image The image.
*/
ol.source.ImageEvent = function(type, image) {
goog.base(this, type);
/**
* The image related to the event.
* @type {ol.Image}
* @api
*/
this.image = image;
};
goog.inherits(ol.source.ImageEvent, goog.events.Event);
/**
* @enum {string}
*/
ol.source.ImageEventType = {
/**
* Triggered when an image starts loading.
* @event ol.source.ImageEvent#imageloadstart
* @api
*/
IMAGELOADSTART: 'imageloadstart',
/**
* Triggered when an image finishes loading.
* @event ol.source.ImageEvent#imageloadend
* @api
*/
IMAGELOADEND: 'imageloadend',
/**
* Triggered if image loading results in an error.
* @event ol.source.ImageEvent#imageloaderror
* @api
*/
IMAGELOADERROR: 'imageloaderror'
};

View File

@@ -3,6 +3,8 @@
goog.provide('ol.source.ImageWMS');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.uri.utils');
@@ -22,6 +24,7 @@ goog.require('ol.source.wms.ServerType');
* Source for WMS servers providing single, untiled images.
*
* @constructor
* @fires ol.source.ImageEvent
* @extends {ol.source.Image}
* @param {olx.source.ImageWMSOptions=} opt_options Options.
* @api stable
@@ -247,6 +250,9 @@ ol.source.ImageWMS.prototype.getImage =
this.renderedRevision_ = this.getRevision();
goog.events.listen(this.image_, goog.events.EventType.CHANGE,
this.handleImageChange, false, this);
return this.image_;
};

View File

@@ -42,7 +42,8 @@ ol.source.TileArcGISRest = function(opt_options) {
projection: options.projection,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
tileUrlFunction: goog.bind(this.tileUrlFunction_, this)
tileUrlFunction: goog.bind(this.tileUrlFunction_, this),
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
});
var urls = options.urls;
@@ -109,6 +110,7 @@ ol.source.TileArcGISRest.prototype.getRequestUrl_ =
params['BBOX'] = tileExtent.join(',');
params['BBOXSR'] = srid;
params['IMAGESR'] = srid;
params['DPI'] = 90 * pixelRatio;
var url;
if (urls.length == 1) {
@@ -137,6 +139,23 @@ ol.source.TileArcGISRest.prototype.getRequestUrl_ =
};
/**
* @param {number} z Z.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.proj.Projection} projection Projection.
* @return {number} Size.
*/
ol.source.TileArcGISRest.prototype.getTilePixelSize =
function(z, pixelRatio, projection) {
var tileSize = goog.base(this, 'getTilePixelSize', z, pixelRatio, projection);
if (pixelRatio == 1) {
return tileSize;
} else {
return (tileSize * pixelRatio + 0.5) | 0;
}
};
/**
* Return the URLs used for this ArcGIS source.
* @return {!Array.<string>} URLs.

View File

@@ -34,7 +34,8 @@ ol.source.TileImage = function(options) {
state: goog.isDef(options.state) ?
/** @type {ol.source.State} */ (options.state) : undefined,
tileGrid: options.tileGrid,
tilePixelRatio: options.tilePixelRatio
tilePixelRatio: options.tilePixelRatio,
wrapX: options.wrapX
});
/**
@@ -91,7 +92,9 @@ ol.source.TileImage.prototype.getTile =
} else {
goog.asserts.assert(projection);
var tileCoord = [z, x, y];
var tileUrl = this.tileUrlFunction(tileCoord, pixelRatio, projection);
var urlTileCoord = this.getWrapXTileCoord(tileCoord, projection);
var tileUrl = goog.isNull(urlTileCoord) ? undefined :
this.tileUrlFunction(urlTileCoord, pixelRatio, projection);
var tile = new this.tileClass(
tileCoord,
goog.isDef(tileUrl) ? ol.TileState.IDLE : ol.TileState.EMPTY,

View File

@@ -37,15 +37,10 @@ ol.source.TileJSON = function(options) {
crossOrigin: options.crossOrigin,
projection: ol.proj.get('EPSG:3857'),
state: ol.source.State.LOADING,
tileLoadFunction: options.tileLoadFunction
tileLoadFunction: options.tileLoadFunction,
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
});
/**
* @type {boolean|undefined}
* @private
*/
this.wrapX_ = options.wrapX;
var request = new goog.net.Jsonp(options.url);
request.send(undefined, goog.bind(this.handleTileJSONResponse, this));
@@ -82,10 +77,7 @@ ol.source.TileJSON.prototype.handleTileJSONResponse = function(tileJSON) {
this.tileGrid = tileGrid;
this.tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
tileGrid.createTileCoordTransform({
extent: extent,
wrapX: this.wrapX_
}),
tileGrid.createTileCoordTransform({extent: extent}),
ol.TileUrlFunction.createFromTemplates(tileJSON.tiles));
if (goog.isDef(tileJSON.attribution) &&

View File

@@ -20,7 +20,8 @@ goog.require('ol.tilegrid.TileGrid');
* tilePixelRatio: (number|undefined),
* projection: ol.proj.ProjectionLike,
* state: (ol.source.State|undefined),
* tileGrid: (ol.tilegrid.TileGrid|undefined)}}
* tileGrid: (ol.tilegrid.TileGrid|undefined),
* wrapX: (boolean|undefined)}}
*/
ol.source.TileOptions;
@@ -72,6 +73,12 @@ ol.source.Tile = function(options) {
*/
this.tileCache = new ol.TileCache();
/**
* @private
* @type {boolean|undefined}
*/
this.wrapX_ = options.wrapX;
};
goog.inherits(ol.source.Tile, ol.source.Source);
@@ -203,6 +210,31 @@ ol.source.Tile.prototype.getTilePixelSize =
};
/**
* Handles x-axis wrapping. When `this.wrapX_` is undefined or the projection
* is not a global projection, `tileCoord` will be returned unaltered. When
* `this.wrapX_` is true, the tile coordinate will be wrapped horizontally.
* When `this.wrapX_` is `false`, `null` will be returned for tiles that are
* outside the projection extent.
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.proj.Projection=} opt_projection Projection.
* @return {ol.TileCoord} Tile coordinate.
*/
ol.source.Tile.prototype.getWrapXTileCoord =
function(tileCoord, opt_projection) {
var projection = goog.isDef(opt_projection) ?
opt_projection : this.getProjection();
var tileGrid = this.getTileGridForProjection(projection);
if (goog.isDef(this.wrapX_) && tileGrid.isGlobal(tileCoord[0], projection)) {
return this.wrapX_ ?
ol.tilecoord.wrapX(tileCoord, tileGrid, projection) :
ol.tilecoord.clipX(tileCoord, tileGrid, projection);
} else {
return tileCoord;
}
};
/**
* Marks a tile coord as being used, without triggering a load.
* @param {number} z Tile coordinate z.

View File

@@ -47,7 +47,8 @@ ol.source.TileWMS = function(opt_options) {
projection: options.projection,
tileGrid: options.tileGrid,
tileLoadFunction: options.tileLoadFunction,
tileUrlFunction: goog.bind(this.tileUrlFunction_, this)
tileUrlFunction: goog.bind(this.tileUrlFunction_, this),
wrapX: options.wrapX
});
var urls = options.urls;

View File

@@ -3,7 +3,6 @@ goog.provide('ol.source.WMTSRequestEncoding');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.math');
goog.require('goog.object');
goog.require('goog.string');
goog.require('goog.uri.utils');
@@ -170,7 +169,6 @@ ol.source.WMTS = function(options) {
}
var tmpExtent = ol.extent.createEmpty();
var tmpTileCoord = [0, 0, 0];
tileUrlFunction = ol.TileUrlFunction.withTileCoordTransform(
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
@@ -188,16 +186,6 @@ ol.source.WMTS = function(options) {
var tileExtent = tileGrid.getTileCoordExtent(tileCoord, tmpExtent);
var extent = projection.getExtent();
if (!goog.isNull(extent) && projection.isGlobal()) {
var numCols = Math.ceil(
ol.extent.getWidth(extent) /
ol.extent.getWidth(tileExtent));
x = goog.math.modulo(x, numCols);
tmpTileCoord[0] = tileCoord[0];
tmpTileCoord[1] = x;
tmpTileCoord[2] = tileCoord[2];
tileExtent = tileGrid.getTileCoordExtent(tmpTileCoord, tmpExtent);
}
if (!ol.extent.intersects(tileExtent, extent) ||
ol.extent.touches(tileExtent, extent)) {
return null;
@@ -215,7 +203,8 @@ ol.source.WMTS = function(options) {
tileGrid: tileGrid,
tileLoadFunction: options.tileLoadFunction,
tilePixelRatio: options.tilePixelRatio,
tileUrlFunction: tileUrlFunction
tileUrlFunction: tileUrlFunction,
wrapX: goog.isDef(options.wrapX) ? options.wrapX : false
});
};
@@ -348,7 +337,7 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
goog.asserts.assert(!goog.isNull(l));
goog.asserts.assert(l['TileMatrixSetLink'].length > 0);
var idx, matrixSet;
var idx, matrixSet, wrapX;
if (l['TileMatrixSetLink'].length > 1) {
idx = goog.array.findIndex(l['TileMatrixSetLink'],
function(elt, index, array) {
@@ -372,6 +361,13 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
goog.asserts.assert(!goog.isNull(matrixSet));
var wgs84BoundingBox = l['WGS84BoundingBox'];
if (goog.isDef(wgs84BoundingBox)) {
var wgs84ProjectionExtent = ol.proj.get('EPSG:4326').getExtent();
wrapX = (wgs84BoundingBox[0] == wgs84ProjectionExtent[0] &&
wgs84BoundingBox[2] == wgs84ProjectionExtent[2]);
}
var format = /** @type {string} */ (l['Format'][0]);
if (goog.isDef(config['format'])) {
format = config['format'];
@@ -463,7 +459,8 @@ ol.source.WMTS.optionsFromCapabilities = function(wmtsCap, config) {
requestEncoding: requestEncoding,
tileGrid: tileGrid,
style: style,
dimensions: dimensions
dimensions: dimensions,
wrapX: wrapX
};
/* jshint +W069 */

View File

@@ -34,16 +34,15 @@ ol.source.XYZ = function(options) {
tileGrid: tileGrid,
tileLoadFunction: options.tileLoadFunction,
tilePixelRatio: options.tilePixelRatio,
tileUrlFunction: ol.TileUrlFunction.nullTileUrlFunction
tileUrlFunction: ol.TileUrlFunction.nullTileUrlFunction,
wrapX: goog.isDef(options.wrapX) ? options.wrapX : true
});
/**
* @private
* @type {ol.TileCoordTransformType}
*/
this.tileCoordTransform_ = tileGrid.createTileCoordTransform({
wrapX: options.wrapX
});
this.tileCoordTransform_ = tileGrid.createTileCoordTransform();
if (goog.isDef(options.tileUrlFunction)) {
this.setTileUrlFunction(options.tileUrlFunction);

View File

@@ -309,6 +309,12 @@ ol.style.createDefaultEditingStyles = function() {
styles[ol.geom.GeometryType.MULTI_LINE_STRING] =
styles[ol.geom.GeometryType.LINE_STRING];
styles[ol.geom.GeometryType.CIRCLE] =
styles[ol.geom.GeometryType.POLYGON].concat(
styles[ol.geom.GeometryType.LINE_STRING]
);
styles[ol.geom.GeometryType.POINT] = [
new ol.style.Style({
image: new ol.style.Circle({

View File

@@ -3,6 +3,7 @@ goog.provide('ol.tilecoord');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.math');
/**
@@ -137,3 +138,35 @@ ol.tilecoord.quadKey = function(tileCoord) {
ol.tilecoord.toString = function(tileCoord) {
return ol.tilecoord.getKeyZXY(tileCoord[0], tileCoord[1], tileCoord[2]);
};
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
* @param {ol.proj.Projection} projection Projection.
* @return {ol.TileCoord} Tile coordinate.
*/
ol.tilecoord.wrapX = function(tileCoord, tileGrid, projection) {
var z = tileCoord[0];
var x = tileCoord[1];
var tileRange = tileGrid.getTileRange(z, projection);
if (x < tileRange.minX || x > tileRange.maxX) {
x = goog.math.modulo(x, tileRange.getWidth());
return [z, x, tileCoord[2]];
}
return tileCoord;
};
/**
* @param {ol.TileCoord} tileCoord Tile coordinate.
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid.
* @param {ol.proj.Projection} projection Projection.
* @return {ol.TileCoord} Tile coordinate.
*/
ol.tilecoord.clipX = function(tileCoord, tileGrid, projection) {
var z = tileCoord[0];
var x = tileCoord[1];
var tileRange = tileGrid.getTileRange(z, projection);
return (x < tileRange.minX || x > tileRange.maxX) ? null : tileCoord;
};

View File

@@ -3,6 +3,7 @@ goog.provide('ol.tilegrid.TileGrid');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.functions');
goog.require('goog.math');
goog.require('ol');
goog.require('ol.Coordinate');
goog.require('ol.TileCoord');
@@ -64,7 +65,7 @@ ol.tilegrid.TileGrid = function(options) {
this.origins_ = null;
if (goog.isDef(options.origins)) {
this.origins_ = options.origins;
goog.asserts.assert(this.origins_.length == this.maxZoom + 1);
goog.asserts.assert(this.origins_.length == this.resolutions_.length);
}
goog.asserts.assert(
(goog.isNull(this.origin_) && !goog.isNull(this.origins_)) ||
@@ -77,7 +78,7 @@ ol.tilegrid.TileGrid = function(options) {
this.tileSizes_ = null;
if (goog.isDef(options.tileSizes)) {
this.tileSizes_ = options.tileSizes;
goog.asserts.assert(this.tileSizes_.length == this.maxZoom + 1);
goog.asserts.assert(this.tileSizes_.length == this.resolutions_.length);
}
/**
@@ -91,6 +92,16 @@ ol.tilegrid.TileGrid = function(options) {
(!goog.isDef(this.tileSize_) && !goog.isNull(this.tileSizes_)) ||
(goog.isDef(this.tileSize_) && goog.isNull(this.tileSizes_)));
/**
* @private
* @type {Array.<number>}
*/
this.widths_ = null;
if (goog.isDef(options.widths)) {
this.widths_ = options.widths;
goog.asserts.assert(this.widths_.length == this.resolutions_.length);
}
};
@@ -103,8 +114,7 @@ ol.tilegrid.TileGrid.tmpTileCoord_ = [0, 0, 0];
/**
* Returns the identity function. May be overridden in subclasses.
* @param {{extent: (ol.Extent|undefined),
* wrapX: (boolean|undefined)}=} opt_options Options.
* @param {{extent: (ol.Extent|undefined)}=} opt_options Options.
* @return {function(ol.TileCoord, ol.proj.Projection, ol.TileCoord=):
* ol.TileCoord} Tile coordinate transform.
*/
@@ -373,6 +383,25 @@ ol.tilegrid.TileGrid.prototype.getTileCoordResolution = function(tileCoord) {
};
/**
* @param {number} z Zoom level.
* @param {ol.proj.Projection} projection Projection.
* @param {ol.TileRange=} opt_tileRange Tile range.
* @return {ol.TileRange} Tile range.
*/
ol.tilegrid.TileGrid.prototype.getTileRange =
function(z, projection, opt_tileRange) {
var projectionExtentTileRange = this.getTileRangeForExtentAndZ(
ol.tilegrid.extentFromProjection(projection), z);
var width = this.getWidth(z);
if (!goog.isDef(width)) {
width = projectionExtentTileRange.getWidth();
}
return ol.TileRange.createOrUpdate(
0, width - 1, 0, projectionExtentTileRange.getHeight(), opt_tileRange);
};
/**
* @param {number} z Z.
* @return {number} Tile size.
@@ -389,12 +418,46 @@ ol.tilegrid.TileGrid.prototype.getTileSize = function(z) {
};
/**
* @param {number} z Zoom level.
* @return {number|undefined} Width for the specified zoom level or `undefined`
* if unknown.
*/
ol.tilegrid.TileGrid.prototype.getWidth = function(z) {
if (!goog.isNull(this.widths_)) {
goog.asserts.assert(this.minZoom <= z && z <= this.maxZoom);
return this.widths_[z];
}
};
/**
* @param {number} resolution Resolution.
* @return {number} Z.
*/
ol.tilegrid.TileGrid.prototype.getZForResolution = function(resolution) {
return ol.array.linearFindNearest(this.resolutions_, resolution, 0);
var z = ol.array.linearFindNearest(this.resolutions_, resolution, 0);
return goog.math.clamp(z, this.minZoom, this.maxZoom);
};
/**
* @param {number} z Zoom level.
* @param {ol.proj.Projection} projection Projection.
* @return {boolean} Whether the tile grid is defined for the whole globe when
* used with the provided `projection` at zoom level `z`.
*/
ol.tilegrid.TileGrid.prototype.isGlobal = function(z, projection) {
var width = this.getWidth(z);
if (goog.isDef(width)) {
var projTileGrid = ol.tilegrid.getForProjection(projection);
var projExtent = projection.getExtent();
return this.getTileSize(z) * width ==
projTileGrid.getTileSize(z) *
projTileGrid.getTileRangeForExtentAndZ(projExtent, z).getWidth();
} else {
return projection.isGlobal();
}
};
@@ -432,10 +495,17 @@ ol.tilegrid.createForExtent =
var resolutions = ol.tilegrid.resolutionsFromExtent(
extent, opt_maxZoom, tileSize);
var widths = new Array(resolutions.length);
var extentWidth = ol.extent.getWidth(extent);
for (var z = resolutions.length - 1; z >= 0; --z) {
widths[z] = extentWidth / tileSize / resolutions[z];
}
return new ol.tilegrid.TileGrid({
origin: ol.extent.getCorner(extent, corner),
resolutions: resolutions,
tileSize: tileSize
tileSize: tileSize,
widths: widths
});
};

View File

@@ -34,7 +34,8 @@ ol.tilegrid.WMTS = function(options) {
origins: options.origins,
resolutions: options.resolutions,
tileSize: options.tileSize,
tileSizes: options.tileSizes
tileSizes: options.tileSizes,
widths: options.widths
});
};
@@ -77,6 +78,8 @@ ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet =
var origins = [];
/** @type {!Array.<number>} */
var tileSizes = [];
/** @type {!Array.<number>} */
var widths = [];
var supportedCRSPropName = 'SupportedCRS';
var matrixIdsPropName = 'TileMatrix';
@@ -112,12 +115,14 @@ ol.tilegrid.WMTS.createFromCapabilitiesMatrixSet =
var tileHeight = elt[tileHeightPropName];
goog.asserts.assert(tileWidth == tileHeight);
tileSizes.push(tileWidth);
widths.push(elt['MatrixWidth']);
});
return new ol.tilegrid.WMTS({
origins: origins,
resolutions: resolutions,
matrixIds: matrixIds,
tileSizes: tileSizes
tileSizes: tileSizes,
widths: widths
});
};

View File

@@ -47,7 +47,6 @@ ol.tilegrid.XYZ.prototype.createTileCoordTransform = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : {};
var minZ = this.minZoom;
var maxZ = this.maxZoom;
var wrapX = goog.isDef(options.wrapX) ? options.wrapX : true;
/** @type {Array.<ol.TileRange>} */
var tileRangeByZ = null;
if (goog.isDef(options.extent)) {
@@ -75,11 +74,6 @@ ol.tilegrid.XYZ.prototype.createTileCoordTransform = function(opt_options) {
}
var n = Math.pow(2, z);
var x = tileCoord[1];
if (wrapX) {
x = goog.math.modulo(x, n);
} else if (x < 0 || n <= x) {
return null;
}
var y = tileCoord[2];
if (y < -n || -1 < y) {
return null;

View File

@@ -64,13 +64,18 @@ assert_version_match() {
#
# Build all of the distribution profiles.
#
build_profiles() {
build_js() {
for p in ${@}; do
echo building ${BUILDS}/${p}.js
node ./tasks/build.js config/${p}.json ${BUILDS}/${p}.js
done
}
build_css() {
./node_modules/clean-css/bin/cleancss css/ol.css -o ${BUILDS}/ol.css
cp css/ol.css ${BUILDS}/ol-debug.css
}
#
# Check out the provided tag. This ensures that the tag has been pushed to
# the canonical remote.
@@ -90,7 +95,8 @@ main() {
checkout_tag ${1}
assert_version_match ${1}
rm -rf ${BUILDS}
build_profiles ${PROFILES}
build_js ${PROFILES}
build_css
npm publish
}

View File

@@ -31,7 +31,7 @@ function listen(min, max, server, callback) {
callback(err);
}
});
server.listen(port, callback);
server.listen(port, '127.0.0.1', callback);
}
_listen(min);
}

View File

@@ -301,6 +301,7 @@ describe('ol.format.GeoJSON', function() {
var obj = format.readGeometry(str);
expect(obj).to.be.a(ol.geom.Point);
expect(obj.getCoordinates()).to.eql([10, 20]);
expect(obj.getLayout()).to.eql(ol.geom.GeometryLayout.XY);
});
it('parses linestring', function() {
@@ -312,6 +313,19 @@ describe('ol.format.GeoJSON', function() {
var obj = format.readGeometry(str);
expect(obj).to.be.a(ol.geom.LineString);
expect(obj.getCoordinates()).to.eql([[10, 20], [30, 40]]);
expect(obj.getLayout()).to.eql(ol.geom.GeometryLayout.XY);
});
it('parses XYZ linestring', function() {
var str = JSON.stringify({
type: 'LineString',
coordinates: [[10, 20, 1534], [30, 40, 1420]]
});
var obj = format.readGeometry(str);
expect(obj).to.be.a(ol.geom.LineString);
expect(obj.getLayout()).to.eql(ol.geom.GeometryLayout.XYZ);
expect(obj.getCoordinates()).to.eql([[10, 20, 1534], [30, 40, 1420]]);
});
it('parses polygon', function() {
@@ -325,6 +339,7 @@ describe('ol.format.GeoJSON', function() {
var obj = format.readGeometry(str);
expect(obj).to.be.a(ol.geom.Polygon);
expect(obj.getLayout()).to.eql(ol.geom.GeometryLayout.XY);
var rings = obj.getLinearRings();
expect(rings.length).to.be(3);
expect(rings[0]).to.be.a(ol.geom.LinearRing);
@@ -346,7 +361,9 @@ describe('ol.format.GeoJSON', function() {
var array = geometryCollection.getGeometries();
expect(array.length).to.be(2);
expect(array[0]).to.be.a(ol.geom.Point);
expect(array[0].getLayout()).to.eql(ol.geom.GeometryLayout.XY);
expect(array[1]).to.be.a(ol.geom.LineString);
expect(array[1].getLayout()).to.eql(ol.geom.GeometryLayout.XY);
});
});
@@ -507,6 +524,12 @@ describe('ol.format.GeoJSON', function() {
expect(geojson.features[0].properties.mygeom).to.eql(undefined);
});
it('writes out a feature without properties correctly', function() {
var feature = new ol.Feature(new ol.geom.Point([5, 10]));
var geojson = format.writeFeatureObject(feature);
expect(geojson.properties).to.eql(null);
});
});
describe('#writeGeometry', function() {
@@ -535,6 +558,106 @@ describe('ol.format.GeoJSON', function() {
format.readGeometry(geojson).getCoordinates());
});
it('maintains coordinate order by default', function() {
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
var right = new ol.geom.Polygon([ccw, cw]);
var rightMulti = new ol.geom.MultiPolygon([[ccw, cw]]);
var left = new ol.geom.Polygon([cw, ccw]);
var leftMulti = new ol.geom.MultiPolygon([[cw, ccw]]);
var rightObj = {
type: 'Polygon',
coordinates: [ccw, cw]
};
var rightMultiObj = {
type: 'MultiPolygon',
coordinates: [[ccw, cw]]
};
var leftObj = {
type: 'Polygon',
coordinates: [cw, ccw]
};
var leftMultiObj = {
type: 'MultiPolygon',
coordinates: [[cw, ccw]]
};
expect(JSON.parse(format.writeGeometry(right))).to.eql(rightObj);
expect(
JSON.parse(format.writeGeometry(rightMulti))).to.eql(rightMultiObj);
expect(JSON.parse(format.writeGeometry(left))).to.eql(leftObj);
expect(JSON.parse(format.writeGeometry(leftMulti))).to.eql(leftMultiObj);
});
it('allows serializing following the right-hand rule', function() {
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
var right = new ol.geom.Polygon([ccw, cw]);
var rightMulti = new ol.geom.MultiPolygon([[ccw, cw]]);
var left = new ol.geom.Polygon([cw, ccw]);
var leftMulti = new ol.geom.MultiPolygon([[cw, ccw]]);
var rightObj = {
type: 'Polygon',
coordinates: [ccw, cw]
};
var rightMultiObj = {
type: 'MultiPolygon',
coordinates: [[ccw, cw]]
};
var json = format.writeGeometry(right, {rightHanded: true});
expect(JSON.parse(json)).to.eql(rightObj);
json = format.writeGeometry(rightMulti, {rightHanded: true});
expect(JSON.parse(json)).to.eql(rightMultiObj);
json = format.writeGeometry(left, {rightHanded: true});
expect(JSON.parse(json)).to.eql(rightObj);
json = format.writeGeometry(leftMulti, {rightHanded: true});
expect(JSON.parse(json)).to.eql(rightMultiObj);
});
it('allows serializing following the left-hand rule', function() {
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
var right = new ol.geom.Polygon([ccw, cw]);
var rightMulti = new ol.geom.MultiPolygon([[ccw, cw]]);
var left = new ol.geom.Polygon([cw, ccw]);
var leftMulti = new ol.geom.MultiPolygon([[cw, ccw]]);
var leftObj = {
type: 'Polygon',
coordinates: [cw, ccw]
};
var leftMultiObj = {
type: 'MultiPolygon',
coordinates: [[cw, ccw]]
};
var json = format.writeGeometry(right, {rightHanded: false});
expect(JSON.parse(json)).to.eql(leftObj);
json = format.writeGeometry(rightMulti, {rightHanded: false});
expect(JSON.parse(json)).to.eql(leftMultiObj);
json = format.writeGeometry(left, {rightHanded: false});
expect(JSON.parse(json)).to.eql(leftObj);
json = format.writeGeometry(leftMulti, {rightHanded: false});
expect(JSON.parse(json)).to.eql(leftMultiObj);
});
it('encodes geometry collection', function() {
var collection = new ol.geom.GeometryCollection([
new ol.geom.Point([10, 20]),
@@ -588,6 +711,7 @@ goog.require('ol.geom.Circle');
goog.require('ol.geom.GeometryCollection');
goog.require('ol.geom.LineString');
goog.require('ol.geom.LinearRing');
goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon');
goog.require('ol.proj');

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<wfs:FeatureCollection xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:it.geosolutions="http://www.geo-solutions.it"
xmlns:cite="http://www.opengeospatial.net/cite" xmlns:ogc="http://www.opengis.net/ogc"
xmlns:tiger="http://www.census.gov" xmlns:sde="http://geoserver.sf.net"
xmlns:topp="http://www.openplans.org/topp" xmlns:wfs="http://www.opengis.net/wfs"
xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sf="http://www.openplans.org/spearfish" xmlns:gml="http://www.opengis.net/gml"
xmlns:nurc="http://www.nurc.nato.int" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
numberOfFeatures="874" timeStamp="2015-03-04T09:53:58.763Z"
xsi:schemaLocation="http://www.openplans.org/topp http://localhost:8080/geoserver/wfs?service=WFS&amp;version=1.1.0&amp;request=DescribeFeatureType&amp;typeName=topp%3Astates http://www.openplans.org/spearfish http://localhost:8080/geoserver/wfs?service=WFS&amp;version=1.1.0&amp;request=DescribeFeatureType&amp;typeName=sf%3Aroads http://www.opengis.net/wfs http://localhost:8080/geoserver/schemas/wfs/1.1.0/wfs.xsd">
<gml:featureMembers>
<topp:states gml:id="states.1">
<topp:the_geom>
<gml:MultiSurface srsDimension="2" srsName="EPSG:4326">
<gml:surfaceMember>
<gml:Polygon srsDimension="2">
<gml:exterior>
<gml:LinearRing srsDimension="2">
<gml:posList>37.51099000000001 -88.071564 37.476273000000006
-88.087883 37.442852 -88.311707 37.40930899999999 -88.359177
37.51099000000001 -88.071564</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</gml:surfaceMember>
</gml:MultiSurface>
</topp:the_geom>
<topp:STATE_NAME>Illinois</topp:STATE_NAME>
<topp:STATE_FIPS>17</topp:STATE_FIPS>
<topp:SUB_REGION>E N Cen</topp:SUB_REGION>
<topp:STATE_ABBR>IL</topp:STATE_ABBR>
<topp:LAND_KM>143986.61</topp:LAND_KM>
<topp:WATER_KM>1993.335</topp:WATER_KM>
<topp:PERSONS>1.1430602E7</topp:PERSONS>
<topp:FAMILIES>2924880.0</topp:FAMILIES>
<topp:HOUSHOLD>4202240.0</topp:HOUSHOLD>
<topp:MALE>5552233.0</topp:MALE>
<topp:FEMALE>5878369.0</topp:FEMALE>
<topp:WORKERS>4199206.0</topp:WORKERS>
<topp:DRVALONE>3741715.0</topp:DRVALONE>
<topp:CARPOOL>652603.0</topp:CARPOOL>
<topp:PUBTRANS>538071.0</topp:PUBTRANS>
<topp:EMPLOYED>5417967.0</topp:EMPLOYED>
<topp:UNEMPLOY>385040.0</topp:UNEMPLOY>
<topp:SERVICE>1360159.0</topp:SERVICE>
<topp:MANUAL>828906.0</topp:MANUAL>
<topp:P_MALE>0.486</topp:P_MALE>
<topp:P_FEMALE>0.514</topp:P_FEMALE>
<topp:SAMP_POP>1747776.0</topp:SAMP_POP>
</topp:states>
<sf:roads gml:id="roads.1">
<sf:the_geom>
<gml:MultiLineString srsDimension="2" srsName="EPSG:4326">
<gml:lineStringMember>
<gml:LineString srsDimension="2">
<gml:posList>37.51099000000001 -88.071564 37.476273000000006
-88.087883 37.442852 -88.311707 37.40930899999999 -88.359177
37.51099000000001 -88.071564</gml:posList>
</gml:LineString>
</gml:lineStringMember>
</gml:MultiLineString>
</sf:the_geom>
<sf:cat>5</sf:cat>
<sf:label>unimproved road</sf:label>
</sf:roads>
</gml:featureMembers>
</wfs:FeatureCollection>

View File

@@ -0,0 +1,44 @@
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http://www.opengis.net/gml"
xmlns:official="http://localhost:8080/official" xmlns:ogc="http://www.opengis.net/ogc"
xmlns:ows="http://www.opengis.net/ows" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" numberOfFeatures="12"
timeStamp="2014-11-03T21:04:28.345Z">
<gml:featureMembers>
<official:planet_osm_line gml:id="planet_osm_line.fid-53719711_14976c6c1aa_6795">
<official:osm_id>3822829</official:osm_id>
</official:planet_osm_line>
<official:planet_osm_line gml:id="planet_osm_line.fid-53719711_14976c6c1aa_6796">
<official:osm_id>3820888</official:osm_id>
</official:planet_osm_line>
<official:planet_osm_line gml:id="planet_osm_line.fid-53719711_14976c6c1aa_6797">
<official:osm_id>296916318</official:osm_id>
</official:planet_osm_line>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_6798">
<official:osm_id>37244</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_6799">
<official:osm_id>1641478</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_679a">
<official:osm_id>1244004</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_679b">
<official:osm_id>22259</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_679c">
<official:osm_id>1606103</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_679d">
<official:osm_id>3217145</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_679e">
<official:osm_id>3228576</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_679f">
<official:osm_id>936994</official:osm_id>
</official:planet_osm_polygon>
<official:planet_osm_polygon gml:id="planet_osm_polygon.fid-53719711_14976c6c1aa_67a0">
<official:osm_id>936990</official:osm_id>
</official:planet_osm_polygon>
</gml:featureMembers>
</wfs:FeatureCollection>

View File

@@ -977,7 +977,6 @@ describe('ol.format.GML3', function() {
});
it('writes back features as GML', function() {
this.timeout(4000);
var serialized = gmlFormat.writeFeaturesNode(features);
expect(serialized).to.xmleql(ol.xml.parse(text));
});
@@ -1107,6 +1106,97 @@ describe('ol.format.GML3', function() {
});
describe('when parsing multiple feature types', function() {
var features;
before(function(done) {
afterLoadText('spec/ol/format/gml/multiple-typenames.xml', function(xml) {
try {
features = new ol.format.GML({
featureNS: 'http://localhost:8080/official',
featureType: ['planet_osm_polygon', 'planet_osm_line']
}).readFeatures(xml);
} catch (e) {
done(e);
}
done();
});
});
it('reads all features', function() {
expect(features.length).to.be(12);
});
});
describe('when parsing multiple feature types', function() {
var features;
before(function(done) {
afterLoadText('spec/ol/format/gml/multiple-typenames.xml', function(xml) {
try {
features = new ol.format.GML().readFeatures(xml);
} catch (e) {
done(e);
}
done();
});
});
it('reads all features with autoconfigure', function() {
expect(features.length).to.be(12);
});
});
describe('when parsing multiple feature types / namespaces', function() {
var features;
before(function(done) {
var url = 'spec/ol/format/gml/multiple-typenames-ns.xml';
afterLoadText(url, function(xml) {
try {
features = new ol.format.GML({
featureNS: {
'topp': 'http://www.openplans.org/topp',
'sf': 'http://www.openplans.org/spearfish'
},
featureType: ['topp:states', 'sf:roads']
}).readFeatures(xml);
} catch (e) {
done(e);
}
done();
});
});
it('reads all features', function() {
expect(features.length).to.be(2);
});
});
describe('when parsing multiple feature types / namespaces', function() {
var features;
before(function(done) {
var url = 'spec/ol/format/gml/multiple-typenames-ns.xml';
afterLoadText(url, function(xml) {
try {
features = new ol.format.GML().readFeatures(xml);
} catch (e) {
done(e);
}
done();
});
});
it('reads all features with autoconfigure', function() {
expect(features.length).to.be(2);
});
});
});

View File

@@ -314,6 +314,25 @@ describe('ol.format.Polyline', function() {
expect(geometry.getFlatCoordinates()).to.eql(flatPoints);
});
it('parses XYZ linestring', function() {
var xyz = ol.format.Polyline.encodeDeltas([
38.500, -120.200, 100,
40.700, -120.950, 200,
43.252, -126.453, 20
], 3);
var format = new ol.format.Polyline({
geometryLayout: ol.geom.GeometryLayout.XYZ
});
var geometry = format.readGeometry(xyz);
expect(geometry.getLayout()).to.eql(ol.geom.GeometryLayout.XYZ);
expect(geometry.getCoordinates()).to.eql([
[-120.200, 38.500, 100],
[-120.950, 40.700, 200],
[-126.453, 43.252, 20]
]);
});
it('transforms and returns the expected geometry', function() {
var geometry = format.readGeometry(encodedFlatPoints, {
featureProjection: 'EPSG:3857'

View File

@@ -448,6 +448,49 @@ describe('ol.format.WFS', function() {
});
describe('when parsing multiple feature types', function() {
var features;
before(function(done) {
afterLoadText('spec/ol/format/gml/multiple-typenames.xml', function(xml) {
try {
features = new ol.format.WFS({
featureNS: 'http://localhost:8080/official',
featureType: ['planet_osm_polygon', 'planet_osm_line']
}).readFeatures(xml);
} catch (e) {
done(e);
}
done();
});
});
it('reads all features', function() {
expect(features.length).to.be(12);
});
});
describe('when parsing multiple feature types', function() {
var features;
before(function(done) {
afterLoadText('spec/ol/format/gml/multiple-typenames.xml', function(xml) {
try {
features = new ol.format.WFS().readFeatures(xml);
} catch (e) {
done(e);
}
done();
});
});
it('reads all features with autoconfigure', function() {
expect(features.length).to.be(12);
});
});
});

View File

@@ -2,7 +2,7 @@ goog.provide('ol.test.geom.flat.orient');
describe('ol.geom.flat.orient', function() {
describe('ol.geom.flat.orient.linearRingIsClockwise', function() {
describe('ol.geom.flat.orient.linearRingIsClockwise()', function() {
it('identifies clockwise rings', function() {
var flatCoordinates = [0, 1, 1, 4, 4, 3, 3, 0];
@@ -20,6 +20,143 @@ describe('ol.geom.flat.orient', function() {
});
describe('ol.geom.flat.orient.linearRingsAreOriented()', function() {
var oriented = ol.geom.flat.orient.linearRingsAreOriented;
var rightCoords = [
-180, -90, 180, -90, 180, 90, -180, 90, -180, -90,
-100, -45, -100, 45, 100, 45, 100, -45, -100, -45
];
var leftCoords = [
-180, -90, -180, 90, 180, 90, 180, -90, -180, -90,
-100, -45, 100, -45, 100, 45, -100, 45, -100, -45
];
var ends = [10, 20];
it('checks for left-hand orientation by default', function() {
expect(oriented(rightCoords, 0, ends, 2)).to.be(false);
expect(oriented(leftCoords, 0, ends, 2)).to.be(true);
});
it('can check for right-hand orientation', function() {
expect(oriented(rightCoords, 0, ends, 2, true)).to.be(true);
expect(oriented(leftCoords, 0, ends, 2, true)).to.be(false);
});
});
describe('ol.geom.flat.orient.linearRingssAreOriented()', function() {
var oriented = ol.geom.flat.orient.linearRingssAreOriented;
var rightCoords = [
-180, -90, 180, -90, 180, 90, -180, 90, -180, -90,
-100, -45, -100, 45, 100, 45, 100, -45, -100, -45,
-180, -90, 180, -90, 180, 90, -180, 90, -180, -90,
-100, -45, -100, 45, 100, 45, 100, -45, -100, -45
];
var leftCoords = [
-180, -90, -180, 90, 180, 90, 180, -90, -180, -90,
-100, -45, 100, -45, 100, 45, -100, 45, -100, -45,
-180, -90, -180, 90, 180, 90, 180, -90, -180, -90,
-100, -45, 100, -45, 100, 45, -100, 45, -100, -45
];
var ends = [[10, 20], [30, 40]];
it('checks for left-hand orientation by default', function() {
expect(oriented(rightCoords, 0, ends, 2)).to.be(false);
expect(oriented(leftCoords, 0, ends, 2)).to.be(true);
});
it('can check for right-hand orientation', function() {
expect(oriented(rightCoords, 0, ends, 2, true)).to.be(true);
expect(oriented(leftCoords, 0, ends, 2, true)).to.be(false);
});
});
describe('ol.geom.flat.orient.orientLinearRings()', function() {
var orient = ol.geom.flat.orient.orientLinearRings;
var rightCoords = [
-180, -90, 180, -90, 180, 90, -180, 90, -180, -90,
-100, -45, -100, 45, 100, 45, 100, -45, -100, -45
];
var leftCoords = [
-180, -90, -180, 90, 180, 90, 180, -90, -180, -90,
-100, -45, 100, -45, 100, 45, -100, 45, -100, -45
];
var ends = [10, 20];
it('orients using the left-hand rule by default', function() {
var rightClone = rightCoords.slice();
orient(rightClone, 0, ends, 2);
expect(rightClone).to.eql(leftCoords);
var leftClone = leftCoords.slice();
orient(leftClone, 0, ends, 2);
expect(leftClone).to.eql(leftCoords);
});
it('can orient using the right-hand rule', function() {
var rightClone = rightCoords.slice();
orient(rightClone, 0, ends, 2, true);
expect(rightClone).to.eql(rightCoords);
var leftClone = leftCoords.slice();
orient(leftClone, 0, ends, 2, true);
expect(leftClone).to.eql(rightCoords);
});
});
describe('ol.geom.flat.orient.orientLinearRingss()', function() {
var orient = ol.geom.flat.orient.orientLinearRingss;
var rightCoords = [
-180, -90, 180, -90, 180, 90, -180, 90, -180, -90,
-100, -45, -100, 45, 100, 45, 100, -45, -100, -45,
-180, -90, 180, -90, 180, 90, -180, 90, -180, -90,
-100, -45, -100, 45, 100, 45, 100, -45, -100, -45
];
var leftCoords = [
-180, -90, -180, 90, 180, 90, 180, -90, -180, -90,
-100, -45, 100, -45, 100, 45, -100, 45, -100, -45,
-180, -90, -180, 90, 180, 90, 180, -90, -180, -90,
-100, -45, 100, -45, 100, 45, -100, 45, -100, -45
];
var ends = [[10, 20], [30, 40]];
it('orients using the left-hand rule by default', function() {
var rightClone = rightCoords.slice();
orient(rightClone, 0, ends, 2);
expect(rightClone).to.eql(leftCoords);
var leftClone = leftCoords.slice();
orient(leftClone, 0, ends, 2);
expect(leftClone).to.eql(leftCoords);
});
it('can orient using the right-hand rule', function() {
var rightClone = rightCoords.slice();
orient(rightClone, 0, ends, 2, true);
expect(rightClone).to.eql(rightCoords);
var leftClone = leftCoords.slice();
orient(leftClone, 0, ends, 2, true);
expect(leftClone).to.eql(rightCoords);
});
});
});
goog.require('ol.geom.flat.orient');

View File

@@ -89,6 +89,32 @@ describe('ol.geom.MultiPolygon', function() {
[[[3, 0], [4, 1], [5, 2], [5, 0]]]);
});
describe('#getCoordinates()', function() {
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
var cw2 = [[-140, -60], [-140, 60], [140, 60], [140, -60], [-140, -60]];
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
var ccw2 = [[-140, -60], [140, -60], [140, 60], [-140, 60], [-140, -60]];
var right = new ol.geom.MultiPolygon([[ccw, cw], [ccw2, cw2]]);
var left = new ol.geom.MultiPolygon([[cw, ccw], [cw2, ccw2]]);
it('returns coordinates as they were constructed', function() {
expect(right.getCoordinates()).to.eql([[ccw, cw], [ccw2, cw2]]);
expect(left.getCoordinates()).to.eql([[cw, ccw], [cw2, ccw2]]);
});
it('can return coordinates with right-hand orientation', function() {
expect(right.getCoordinates(true)).to.eql([[ccw, cw], [ccw2, cw2]]);
expect(left.getCoordinates(true)).to.eql([[ccw, cw], [ccw2, cw2]]);
});
it('can return coordinates with left-hand orientation', function() {
expect(right.getCoordinates(false)).to.eql([[cw, ccw], [cw2, ccw2]]);
expect(left.getCoordinates(false)).to.eql([[cw, ccw], [cw2, ccw2]]);
});
});
describe('#getSimplifiedGeometry', function() {
it('returns the expected result', function() {

View File

@@ -120,6 +120,30 @@ describe('ol.geom.Polygon', function() {
expect(polygon.containsCoordinate(insideInner)).to.be(false);
});
describe('#getCoordinates()', function() {
var cw = [[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]];
var ccw = [[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]];
var right = new ol.geom.Polygon([ccw, cw]);
var left = new ol.geom.Polygon([cw, ccw]);
it('returns coordinates as they were constructed', function() {
expect(right.getCoordinates()).to.eql([ccw, cw]);
expect(left.getCoordinates()).to.eql([cw, ccw]);
});
it('can return coordinates with right-hand orientation', function() {
expect(right.getCoordinates(true)).to.eql([ccw, cw]);
expect(left.getCoordinates(true)).to.eql([ccw, cw]);
});
it('can return coordinates with left-hand orientation', function() {
expect(right.getCoordinates(false)).to.eql([cw, ccw]);
expect(left.getCoordinates(false)).to.eql([cw, ccw]);
});
});
describe('#getOrientedFlatCoordinates', function() {
it('reverses the outer ring if necessary', function() {

View File

@@ -470,6 +470,58 @@ describe('ol.interaction.Draw', function() {
});
describe('drawing circles', function() {
var draw;
beforeEach(function() {
draw = new ol.interaction.Draw({
source: source,
type: ol.geom.GeometryType.CIRCLE
});
map.addInteraction(draw);
});
it('draws circle with clicks, finishing on second point', function() {
// first point
simulateEvent('pointermove', 10, 20);
simulateEvent('pointerdown', 10, 20);
simulateEvent('pointerup', 10, 20);
// finish on second point
simulateEvent('pointermove', 30, 20);
simulateEvent('pointerdown', 30, 20);
simulateEvent('pointerup', 30, 20);
var features = source.getFeatures();
expect(features).to.have.length(1);
var geometry = features[0].getGeometry();
expect(geometry).to.be.a(ol.geom.Circle);
expect(geometry.getCenter()).to.eql([10, -20]);
expect(geometry.getRadius()).to.eql(20);
});
it('triggers draw events', function() {
var ds = sinon.spy();
var de = sinon.spy();
goog.events.listen(draw, ol.DrawEventType.DRAWSTART, ds);
goog.events.listen(draw, ol.DrawEventType.DRAWEND, de);
// first point
simulateEvent('pointermove', 10, 20);
simulateEvent('pointerdown', 10, 20);
simulateEvent('pointerup', 10, 20);
// finish on second point
simulateEvent('pointermove', 30, 20);
simulateEvent('pointerdown', 30, 20);
simulateEvent('pointerup', 30, 20);
expect(ds).to.be.called(1);
expect(de).to.be.called(1);
});
});
describe('#setActive()', function() {
var interaction;
@@ -596,6 +648,7 @@ goog.require('ol.DrawEventType');
goog.require('ol.Map');
goog.require('ol.MapBrowserPointerEvent');
goog.require('ol.View');
goog.require('ol.geom.Circle');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
goog.require('ol.geom.MultiLineString');

View File

@@ -66,7 +66,6 @@ describe('ol.interaction.Select', function() {
clientY: position.y + y + height / 2,
shiftKey: shiftKey
})));
console.debug(event);
map.handleMapBrowserEvent(event);
}
@@ -89,8 +88,15 @@ describe('ol.interaction.Select', function() {
});
it('select with single-click', function() {
var listenerSpy = sinon.spy(function(e) {
expect(e.selected).to.have.length(1);
});
select.on('select', listenerSpy);
simulateEvent(ol.MapBrowserEvent.EventType.SINGLECLICK, 10, -20);
expect(listenerSpy.callCount).to.be(1);
var features = select.getFeatures();
expect(features.getLength()).to.equal(1);
});
@@ -107,8 +113,15 @@ describe('ol.interaction.Select', function() {
});
it('select with single-click', function() {
var listenerSpy = sinon.spy(function(e) {
expect(e.selected).to.have.length(2);
});
select.on('select', listenerSpy);
simulateEvent(ol.MapBrowserEvent.EventType.SINGLECLICK, 10, -20);
expect(listenerSpy.callCount).to.be(1);
var features = select.getFeatures();
expect(features.getLength()).to.equal(2);
});

View File

@@ -115,6 +115,56 @@ describe('ol.source.Tile', function() {
});
describe('#getWrapXTileCoord()', function() {
it('returns the expected tile coordinate - {wrapX: undefined}', function() {
var tileSource = new ol.source.Tile({
projection: 'EPSG:3857'
});
var tileCoord = tileSource.getWrapXTileCoord([6, -31, 22]);
expect(tileCoord).to.eql([6, -31, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 33, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 97, 22]);
expect(tileCoord).to.eql([6, 97, 22]);
});
it('returns the expected tile coordinate - {wrapX: true}', function() {
var tileSource = new ol.source.Tile({
projection: 'EPSG:3857',
wrapX: true
});
var tileCoord = tileSource.getWrapXTileCoord([6, -31, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 33, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 97, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
});
it('returns the expected tile coordinate - {wrapX: false}', function() {
var tileSource = new ol.source.Tile({
projection: 'EPSG:3857',
wrapX: false
});
var tileCoord = tileSource.getWrapXTileCoord([6, -31, 22]);
expect(tileCoord).to.eql(null);
tileCoord = tileSource.getWrapXTileCoord([6, 33, 22]);
expect(tileCoord).to.eql([6, 33, 22]);
tileCoord = tileSource.getWrapXTileCoord([6, 97, 22]);
expect(tileCoord).to.eql(null);
});
});
});

View File

@@ -64,14 +64,17 @@ describe('ol.source.XYZ', function() {
describe('wrap x', function() {
it('returns the expected URL', function() {
var projection = xyzTileSource.getProjection();
var tileUrl = xyzTileSource.tileUrlFunction(
[6, -31, -23]);
xyzTileSource.getWrapXTileCoord([6, -31, -23], projection));
expect(tileUrl).to.eql('6/33/22');
tileUrl = xyzTileSource.tileUrlFunction([6, 33, -23]);
tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getWrapXTileCoord([6, 33, -23], projection));
expect(tileUrl).to.eql('6/33/22');
tileUrl = xyzTileSource.tileUrlFunction([6, 97, -23]);
tileUrl = xyzTileSource.tileUrlFunction(
xyzTileSource.getWrapXTileCoord([6, 97, -23], projection));
expect(tileUrl).to.eql('6/33/22');
});

View File

@@ -97,7 +97,7 @@
return node.childNodes;
} else {
var nodes = [];
for (var i = 0, ii=node.childNodes.length; i < ii; i++ ) {
for (var i = 0, ii = node.childNodes.length; i < ii; i++) {
var child = node.childNodes[i];
if (child.nodeType == 1) {
// element node, add it
@@ -116,36 +116,32 @@
function assertElementNodesEqual(node1, node2, options, errors) {
var testPrefix = (options && options.prefix === true);
try {
expect(node1.nodeType).to.equal(node2.nodeType);
} catch(e) {
if (node1.nodeType !== node2.nodeType) {
errors.push('nodeType test failed for: ' + node1.nodeName + ' | ' +
node2.nodeName + ' | ' + e.message);
node2.nodeName + ' | expected ' + node1.nodeType + ' to equal ' +
node2.nodeType);
}
if (testPrefix) {
try {
expect(node1.nodeName).to.equal(node2.nodeName);
} catch(e) {
if (node1.nodeName !== node2.nodeName) {
errors.push('nodeName test failed for: ' + node1.nodeName + ' | ' +
node2.nodeName + ' | ' + e.message);
node2.nodeName + ' | expected ' + node1.nodeName + ' to equal ' +
node2.nodeName);
}
} else {
try {
expect(node1.nodeName.split(':').pop()).to.equal(
node2.nodeName.split(':').pop());
} catch(e) {
var n1 = node1.nodeName.split(':').pop();
var n2 = node2.nodeName.split(':').pop();
if (n1 !== n2) {
errors.push('nodeName test failed for: ' + node1.nodeName + ' | ' +
node2.nodeName + ' | ' + e.message);
node2.nodeName + ' | expected ' + n1 + ' to equal ' + n2);
}
}
// for text nodes compare value
if (node1.nodeType === 3) {
try {
// TODO should we make this optional?
expect(node1.nodeValue.replace(/\s/g, '')).to.equal(
node2.nodeValue.replace(/\s/g, ''));
} catch(e) {
errors.push('nodeValue test failed | ' + e.message);
var nv1 = node1.nodeValue.replace(/\s/g, '');
var nv2 = node2.nodeValue.replace(/\s/g, '');
if (nv1 !== nv2) {
errors.push('nodeValue test failed | expected ' + nv1 + ' to equal ' +
nv2);
}
}
// for element type nodes compare namespace, attributes, and children
@@ -153,20 +149,17 @@
// test namespace alias and uri
if (node1.prefix || node2.prefix) {
if (testPrefix) {
try {
expect(node1.prefix).to.equal(node2.prefix);
} catch(e) {
errors.push('Prefix test failed for: ' + node1.nodeName + ' | ' +
e.message);
if (node1.prefix !== node2.prefix) {
errors.push('Prefix test failed for: ' + node1.nodeName +
' | expected ' + node1.prefix + ' to equal ' + node2.prefix);
}
}
}
if (node1.namespaceURI || node2.namespaceURI) {
try {
expect(node1.namespaceURI).to.equal(node2.namespaceURI);
} catch(e) {
if (node1.namespaceURI !== node2.namespaceURI) {
errors.push('namespaceURI test failed for: ' + node1.nodeName +
' | ' + e.message);
' | expected ' + node1.namespaceURI + ' to equal ' +
node2.namespaceURI);
}
}
// compare attributes - disregard xmlns given namespace handling above
@@ -177,7 +170,7 @@
var ga, ea, gn, en;
var i, ii;
if (node1.attributes) {
for (i=0, ii=node1.attributes.length; i<ii; ++i) {
for (i = 0, ii = node1.attributes.length; i < ii; ++i) {
ga = node1.attributes[i];
if (ga.specified === undefined || ga.specified === true) {
if (ga.name.split(':').shift() != 'xmlns') {
@@ -189,7 +182,7 @@
}
}
if (node2.attributes) {
for (i=0, ii=node2.attributes.length; i<ii; ++i) {
for (i = 0, ii = node2.attributes.length; i < ii; ++i) {
ea = node2.attributes[i];
if (ea.specified === undefined || ea.specified === true) {
if (ea.name.split(':').shift() != 'xmlns') {
@@ -200,11 +193,9 @@
}
}
}
try {
expect(node1AttrLen).to.equal(node2AttrLen);
} catch(e) {
if (node1AttrLen !== node2AttrLen) {
errors.push('Number of attributes test failed for: ' + node1.nodeName +
' | ' + e.message);
' | expected ' + node1AttrLen + ' to equal ' + node2AttrLen);
}
var gv, ev;
for (var name in node1Attr) {
@@ -213,36 +204,52 @@
' expected for element ' + node1.nodeName);
}
// test attribute namespace
try {
// we do not care about the difference between an empty string and
// null for namespaceURI some tests will fail in IE9 otherwise
// see also
// http://msdn.microsoft.com/en-us/library/ff460650(v=vs.85).aspx
expect(node1Attr[name].namespaceURI || null).to.be(
node2Attr[name].namespaceURI || null);
} catch(e) {
// we do not care about the difference between an empty string and
// null for namespaceURI some tests will fail in IE9 otherwise
// see also
// http://msdn.microsoft.com/en-us/library/ff460650(v=vs.85).aspx
if ((node1Attr[name].namespaceURI || null) !==
(node2Attr[name].namespaceURI || null)) {
errors.push('namespaceURI attribute test failed for: ' +
node1.nodeName + ' | ' + e.message);
node1.nodeName + ' | expected ' + node1Attr[name].namespaceURI +
' to equal ' + node2Attr[name].namespaceURI);
}
try {
expect(node1Attr[name].value).to.equal(node2Attr[name].value);
} catch(e) {
if (node1Attr[name].value !== node2Attr[name].value) {
errors.push('Attribute value test failed for: ' + node1.nodeName +
' | ' + e.message);
' | expected ' + node1Attr[name].value + ' to equal ' +
node2Attr[name].value);
}
}
// compare children
var node1ChildNodes = getChildNodes(node1, options);
var node2ChildNodes = getChildNodes(node2, options);
try {
expect(node1ChildNodes.length).to.equal(node2ChildNodes.length);
} catch(e) {
errors.push('Number of childNodes test failed for: ' + node1.nodeName +
' | ' + e.message);
if (node1ChildNodes.length !== node2ChildNodes.length) {
// check if all child nodes are text, they could be split up in
// 4096 chunks
// if so, ignore the childnode count error
var allText = true;
var c, cc;
for (c = 0, cc = node1ChildNodes.length; c < cc; ++c) {
if (node1ChildNodes[c].nodeType !== 3) {
allText = false;
break;
}
}
for (c = 0, cc = node2ChildNodes.length; c < cc; ++c) {
if (node2ChildNodes[c].nodeType !== 3) {
allText = false;
break;
}
}
if (!allText) {
errors.push('Number of childNodes test failed for: ' +
node1.nodeName + ' | expected ' + node1ChildNodes.length +
' to equal ' + node2ChildNodes.length);
}
}
// only compare if they are equal
if (node1ChildNodes.length === node2ChildNodes.length) {
for (var j=0, jj=node1ChildNodes.length; j<jj; ++j) {
for (var j = 0, jj = node1ChildNodes.length; j < jj; ++j) {
assertElementNodesEqual(
node1ChildNodes[j], node2ChildNodes[j], options, errors);
}
@@ -283,7 +290,7 @@
/**
* Checks if the array sort of equals another array.
*/
expect.Assertion.prototype.arreql = function (obj) {
expect.Assertion.prototype.arreql = function(obj) {
this.assert(
goog.array.equals(this.obj, obj),
function() {
@@ -301,7 +308,7 @@
/**
* Checks if the array sort of equals another array (allows NaNs to be equal).
*/
expect.Assertion.prototype.arreqlNaN = function (obj) {
expect.Assertion.prototype.arreqlNaN = function(obj) {
function compare(a, b) {
return a === b || (typeof a === 'number' && typeof b === 'number' &&
isNaN(a) && isNaN(b));